1
2 /*
3 * Copyright 2020 Google LLC
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9 #ifndef GrD3DTypes_DEFINED
10 #define GrD3DTypes_DEFINED
11
12 // This file includes d3d12.h, which in turn includes windows.h, which redefines many
13 // common identifiers such as:
14 // * interface
15 // * small
16 // * near
17 // * far
18 // * CreateSemaphore
19 // * MemoryBarrier
20 //
21 // You should only include this header if you need the Direct3D definitions and are
22 // prepared to rename those identifiers. Otherwise use GrD3DTypesMinimal.h.
23
24 #include "include/core/SkRefCnt.h"
25 #include "include/gpu/d3d/GrD3DTypesMinimal.h"
26 #include <d3d12.h>
27 #include <dxgi1_4.h>
28
29 class GrD3DGpu;
30
31 /** Check if the argument is non-null, and if so, call obj->AddRef() and return obj.
32 */
GrSafeComAddRef(T * obj)33 template <typename T> static inline T* GrSafeComAddRef(T* obj) {
34 if (obj) {
35 obj->AddRef();
36 }
37 return obj;
38 }
39
40 /** Check if the argument is non-null, and if so, call obj->Release()
41 */
GrSafeComRelease(T * obj)42 template <typename T> static inline void GrSafeComRelease(T* obj) {
43 if (obj) {
44 obj->Release();
45 }
46 }
47
48 template <typename T> class gr_cp {
49 public:
50 using element_type = T;
51
gr_cp()52 constexpr gr_cp() : fObject(nullptr) {}
gr_cp(std::nullptr_t)53 constexpr gr_cp(std::nullptr_t) : fObject(nullptr) {}
54
55 /**
56 * Shares the underlying object by calling AddRef(), so that both the argument and the newly
57 * created gr_cp both have a reference to it.
58 */
gr_cp(const gr_cp<T> & that)59 gr_cp(const gr_cp<T>& that) : fObject(GrSafeComAddRef(that.get())) {}
60
61 /**
62 * Move the underlying object from the argument to the newly created gr_cp. Afterwards only
63 * the new gr_cp will have a reference to the object, and the argument will point to null.
64 * No call to AddRef() or Release() will be made.
65 */
gr_cp(gr_cp<T> && that)66 gr_cp(gr_cp<T>&& that) : fObject(that.release()) {}
67
68 /**
69 * Adopt the bare object into the newly created gr_cp.
70 * No call to AddRef() or Release() will be made.
71 */
gr_cp(T * obj)72 explicit gr_cp(T* obj) {
73 fObject = obj;
74 }
75
76 /**
77 * Calls Release() on the underlying object pointer.
78 */
~gr_cp()79 ~gr_cp() {
80 GrSafeComRelease(fObject);
81 SkDEBUGCODE(fObject = nullptr);
82 }
83
84 /**
85 * Shares the underlying object referenced by the argument by calling AddRef() on it. If this
86 * gr_cp previously had a reference to an object (i.e. not null) it will call Release()
87 * on that object.
88 */
89 gr_cp<T>& operator=(const gr_cp<T>& that) {
90 if (this != &that) {
91 this->reset(GrSafeComAddRef(that.get()));
92 }
93 return *this;
94 }
95
96 /**
97 * Move the underlying object from the argument to the gr_cp. If the gr_cp
98 * previously held a reference to another object, Release() will be called on that object.
99 * No call to AddRef() will be made.
100 */
101 gr_cp<T>& operator=(gr_cp<T>&& that) {
102 this->reset(that.release());
103 return *this;
104 }
105
106 explicit operator bool() const { return this->get() != nullptr; }
107
get()108 T* get() const { return fObject; }
109 T* operator->() const { return fObject; }
110 T** operator&() { return &fObject; }
111
112 /**
113 * Adopt the new object, and call Release() on any previously held object (if not null).
114 * No call to AddRef() will be made.
115 */
116 void reset(T* object = nullptr) {
117 T* oldObject = fObject;
118 fObject = object;
119 GrSafeComRelease(oldObject);
120 }
121
122 /**
123 * Shares the new object by calling AddRef() on it. If this gr_cp previously had a
124 * reference to an object (i.e. not null) it will call Release() on that object.
125 */
retain(T * object)126 void retain(T* object) {
127 if (this->fObject != object) {
128 this->reset(GrSafeComAddRef(object));
129 }
130 }
131
132 /**
133 * Return the original object, and set the internal object to nullptr.
134 * The caller must assume ownership of the object, and manage its reference count directly.
135 * No call to Release() will be made.
136 */
release()137 T* SK_WARN_UNUSED_RESULT release() {
138 T* obj = fObject;
139 fObject = nullptr;
140 return obj;
141 }
142
143 private:
144 T* fObject;
145 };
146
147 template <typename T> inline bool operator==(const gr_cp<T>& a,
148 const gr_cp<T>& b) {
149 return a.get() == b.get();
150 }
151
152 template <typename T> inline bool operator!=(const gr_cp<T>& a,
153 const gr_cp<T>& b) {
154 return a.get() != b.get();
155 }
156
157 // interface classes for the GPU memory allocator
158 class GrD3DAlloc : public SkRefCnt {
159 public:
160 ~GrD3DAlloc() override = default;
161 };
162
163 class GrD3DMemoryAllocator : public SkRefCnt {
164 public:
165 virtual gr_cp<ID3D12Resource> createResource(D3D12_HEAP_TYPE, const D3D12_RESOURCE_DESC*,
166 D3D12_RESOURCE_STATES initialResourceState,
167 sk_sp<GrD3DAlloc>* allocation,
168 const D3D12_CLEAR_VALUE*) = 0;
169 virtual gr_cp<ID3D12Resource> createAliasingResource(sk_sp<GrD3DAlloc>& allocation,
170 uint64_t localOffset,
171 const D3D12_RESOURCE_DESC*,
172 D3D12_RESOURCE_STATES initialResourceState,
173 const D3D12_CLEAR_VALUE*) = 0;
174 };
175
176 // Note: there is no notion of Borrowed or Adopted resources in the D3D backend,
177 // so Ganesh will ref fResource once it's asked to wrap it.
178 // Clients are responsible for releasing their own ref to avoid memory leaks.
179 struct GrD3DTextureResourceInfo {
180 gr_cp<ID3D12Resource> fResource = nullptr;
181 sk_sp<GrD3DAlloc> fAlloc = nullptr;
182 D3D12_RESOURCE_STATES fResourceState = D3D12_RESOURCE_STATE_COMMON;
183 DXGI_FORMAT fFormat = DXGI_FORMAT_UNKNOWN;
184 uint32_t fSampleCount = 1;
185 uint32_t fLevelCount = 0;
186 unsigned int fSampleQualityPattern = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
187 GrProtected fProtected = GrProtected::kNo;
188
189 GrD3DTextureResourceInfo() = default;
190
191 GrD3DTextureResourceInfo(ID3D12Resource* resource,
192 const sk_sp<GrD3DAlloc> alloc,
193 D3D12_RESOURCE_STATES resourceState,
194 DXGI_FORMAT format,
195 uint32_t sampleCount,
196 uint32_t levelCount,
197 unsigned int sampleQualityLevel,
198 GrProtected isProtected = GrProtected::kNo)
fResourceGrD3DTextureResourceInfo199 : fResource(resource)
200 , fAlloc(alloc)
201 , fResourceState(resourceState)
202 , fFormat(format)
203 , fSampleCount(sampleCount)
204 , fLevelCount(levelCount)
205 , fSampleQualityPattern(sampleQualityLevel)
206 , fProtected(isProtected) {}
207
GrD3DTextureResourceInfoGrD3DTextureResourceInfo208 GrD3DTextureResourceInfo(const GrD3DTextureResourceInfo& info,
209 GrD3DResourceStateEnum resourceState)
210 : fResource(info.fResource)
211 , fAlloc(info.fAlloc)
212 , fResourceState(static_cast<D3D12_RESOURCE_STATES>(resourceState))
213 , fFormat(info.fFormat)
214 , fSampleCount(info.fSampleCount)
215 , fLevelCount(info.fLevelCount)
216 , fSampleQualityPattern(info.fSampleQualityPattern)
217 , fProtected(info.fProtected) {}
218
219 #if GR_TEST_UTILS
220 bool operator==(const GrD3DTextureResourceInfo& that) const {
221 return fResource == that.fResource && fResourceState == that.fResourceState &&
222 fFormat == that.fFormat && fSampleCount == that.fSampleCount &&
223 fLevelCount == that.fLevelCount &&
224 fSampleQualityPattern == that.fSampleQualityPattern && fProtected == that.fProtected;
225 }
226 #endif
227 };
228
229 struct GrD3DFenceInfo {
GrD3DFenceInfoGrD3DFenceInfo230 GrD3DFenceInfo()
231 : fFence(nullptr)
232 , fValue(0) {
233 }
234
235 gr_cp<ID3D12Fence> fFence;
236 uint64_t fValue; // signal value for the fence
237 };
238
239 #endif
240