1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ResourceManager11:
7 // Centralized point of allocation for all D3D11 Resources.
8
9 #ifndef LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
10 #define LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
11
12 #include <array>
13 #include <memory>
14
15 #include "common/MemoryBuffer.h"
16 #include "common/angleutils.h"
17 #include "common/debug.h"
18 #include "libANGLE/Error.h"
19 #include "libANGLE/renderer/renderer_utils.h"
20
21 namespace rx
22 {
23 // These two methods are declared here to prevent circular includes.
24 namespace d3d11
25 {
26 HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
27
28 template <typename T>
SetDebugName(angle::ComPtr<T> & resource,const char * name)29 HRESULT SetDebugName(angle::ComPtr<T> &resource, const char *name)
30 {
31 return SetDebugName(resource.Get(), name);
32 }
33 } // namespace d3d11
34
35 class Renderer11;
36 class ResourceManager11;
37 template <typename T>
38 class SharedResource11;
39 class TextureHelper11;
40
41 using InputElementArray = WrappedArray<D3D11_INPUT_ELEMENT_DESC>;
42 using ShaderData = WrappedArray<uint8_t>;
43
44 // Format: ResourceType, D3D11 type, DESC type, init data type.
45 #define ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
46 OP(NAME, BlendState, ID3D11BlendState, D3D11_BLEND_DESC, void) \
47 OP(NAME, Buffer, ID3D11Buffer, D3D11_BUFFER_DESC, const D3D11_SUBRESOURCE_DATA) \
48 OP(NAME, ComputeShader, ID3D11ComputeShader, ShaderData, void) \
49 OP(NAME, DepthStencilState, ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC, void) \
50 OP(NAME, DepthStencilView, ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, \
51 ID3D11Resource) \
52 OP(NAME, GeometryShader, ID3D11GeometryShader, ShaderData, \
53 const std::vector<D3D11_SO_DECLARATION_ENTRY>) \
54 OP(NAME, InputLayout, ID3D11InputLayout, InputElementArray, const ShaderData) \
55 OP(NAME, PixelShader, ID3D11PixelShader, ShaderData, void) \
56 OP(NAME, Query, ID3D11Query, D3D11_QUERY_DESC, void) \
57 OP(NAME, RasterizerState, ID3D11RasterizerState, D3D11_RASTERIZER_DESC, void) \
58 OP(NAME, RenderTargetView, ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, \
59 ID3D11Resource) \
60 OP(NAME, SamplerState, ID3D11SamplerState, D3D11_SAMPLER_DESC, void) \
61 OP(NAME, ShaderResourceView, ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, \
62 ID3D11Resource) \
63 OP(NAME, Texture2D, ID3D11Texture2D, D3D11_TEXTURE2D_DESC, const D3D11_SUBRESOURCE_DATA) \
64 OP(NAME, Texture3D, ID3D11Texture3D, D3D11_TEXTURE3D_DESC, const D3D11_SUBRESOURCE_DATA) \
65 OP(NAME, VertexShader, ID3D11VertexShader, ShaderData, void)
66
67 #define ANGLE_RESOURCE_TYPE_LIST(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) RESTYPE,
68
69 enum class ResourceType
70 {
71 ANGLE_RESOURCE_TYPE_OP(List, ANGLE_RESOURCE_TYPE_LIST) Last
72 };
73
74 #undef ANGLE_RESOURCE_TYPE_LIST
75
ResourceTypeIndex(ResourceType resourceType)76 constexpr size_t ResourceTypeIndex(ResourceType resourceType)
77 {
78 return static_cast<size_t>(resourceType);
79 }
80
81 constexpr size_t NumResourceTypes = ResourceTypeIndex(ResourceType::Last);
82
83 #define ANGLE_RESOURCE_TYPE_TO_D3D11(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
84 \
85 template<> struct NAME<ResourceType::RESTYPE> \
86 { \
87 using Value = D3D11TYPE; \
88 };
89
90 #define ANGLE_RESOURCE_TYPE_TO_DESC(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
91 \
92 template<> struct NAME<ResourceType::RESTYPE> \
93 { \
94 using Value = DESCTYPE; \
95 };
96
97 #define ANGLE_RESOURCE_TYPE_TO_INIT_DATA(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
98 \
99 template<> struct NAME<ResourceType::RESTYPE> \
100 { \
101 using Value = INITDATATYPE; \
102 };
103
104 #define ANGLE_RESOURCE_TYPE_TO_TYPE(NAME, OP) \
105 template <ResourceType Param> \
106 struct NAME; \
107 ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
108 \
109 template<ResourceType Param> struct NAME \
110 { \
111 }; \
112 \
113 template<ResourceType Param> using Get##NAME = typename NAME<Param>::Value;
114
115 ANGLE_RESOURCE_TYPE_TO_TYPE(D3D11Type, ANGLE_RESOURCE_TYPE_TO_D3D11)
116 ANGLE_RESOURCE_TYPE_TO_TYPE(DescType, ANGLE_RESOURCE_TYPE_TO_DESC)
117 ANGLE_RESOURCE_TYPE_TO_TYPE(InitDataType, ANGLE_RESOURCE_TYPE_TO_INIT_DATA)
118
119 #undef ANGLE_RESOURCE_TYPE_TO_D3D11
120 #undef ANGLE_RESOURCE_TYPE_TO_DESC
121 #undef ANGLE_RESOURCE_TYPE_TO_INIT_DATA
122 #undef ANGLE_RESOURCE_TYPE_TO_TYPE
123
124 #define ANGLE_TYPE_TO_RESOURCE_TYPE(NAME, OP) \
125 template <typename Param> \
126 struct NAME; \
127 ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
128 \
129 template<typename Param> struct NAME \
130 { \
131 }; \
132 \
133 template<typename Param> constexpr ResourceType Get##NAME() \
134 { \
135 return NAME<Param>::Value; \
136 }
137
138 #define ANGLE_D3D11_TO_RESOURCE_TYPE(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
139 \
140 template<> struct NAME<D3D11TYPE> \
141 { \
142 static constexpr ResourceType Value = ResourceType::RESTYPE; \
143 };
144
145 ANGLE_TYPE_TO_RESOURCE_TYPE(ResourceTypeFromD3D11, ANGLE_D3D11_TO_RESOURCE_TYPE)
146
147 #undef ANGLE_D3D11_TO_RESOURCE_TYPE
148 #undef ANGLE_TYPE_TO_RESOURCE_TYPE
149
150 template <typename T>
151 using GetDescFromD3D11 = GetDescType<ResourceTypeFromD3D11<T>::Value>;
152
153 template <typename T>
154 using GetInitDataFromD3D11 = GetInitDataType<ResourceTypeFromD3D11<T>::Value>;
155
156 template <typename T>
ResourceTypeIndex()157 constexpr size_t ResourceTypeIndex()
158 {
159 return static_cast<size_t>(GetResourceTypeFromD3D11<T>());
160 }
161
162 template <typename T>
163 struct TypedData
164 {
TypedDataTypedData165 TypedData() {}
166 ~TypedData();
167
168 T *object = nullptr;
169 ResourceManager11 *manager = nullptr;
170 };
171
172 // Smart pointer type. Wraps the resource and a factory for safe deletion.
173 template <typename T, template <class> class Pointer, typename DataT>
174 class Resource11Base : angle::NonCopyable
175 {
176 public:
get()177 T *get() const { return mData->object; }
getPointer()178 T *const *getPointer() const { return &mData->object; }
179
setDebugName(const char * name)180 void setDebugName(const char *name) { d3d11::SetDebugName(mData->object, name); }
181
set(T * object)182 void set(T *object)
183 {
184 ASSERT(!valid());
185 mData->object = object;
186 }
187
valid()188 bool valid() const { return (mData->object != nullptr); }
189
reset()190 void reset()
191 {
192 if (valid())
193 mData.reset(new DataT());
194 }
195
getSerial()196 ResourceSerial getSerial() const
197 {
198 return ResourceSerial(reinterpret_cast<uintptr_t>(mData->object));
199 }
200
201 protected:
202 friend class TextureHelper11;
203
Resource11Base()204 Resource11Base() : mData(new DataT()) {}
205
Resource11Base(Resource11Base && movedObj)206 Resource11Base(Resource11Base &&movedObj) : mData(new DataT())
207 {
208 std::swap(mData, movedObj.mData);
209 }
210
~Resource11Base()211 virtual ~Resource11Base() { mData.reset(); }
212
213 Resource11Base &operator=(Resource11Base &&movedObj)
214 {
215 std::swap(mData, movedObj.mData);
216 return *this;
217 }
218
219 Pointer<DataT> mData;
220 };
221
222 template <typename T>
223 using UniquePtr = typename std::unique_ptr<T, std::default_delete<T>>;
224
225 template <typename ResourceT>
226 class Resource11 : public Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>
227 {
228 public:
Resource11()229 Resource11() {}
Resource11(Resource11 && other)230 Resource11(Resource11 &&other)
231 : Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>(std::move(other))
232 {
233 }
234 Resource11 &operator=(Resource11 &&other)
235 {
236 std::swap(this->mData, other.mData);
237 return *this;
238 }
239
240 private:
241 template <typename T>
242 friend class SharedResource11;
243 friend class ResourceManager11;
244
Resource11(ResourceT * object,ResourceManager11 * manager)245 Resource11(ResourceT *object, ResourceManager11 *manager)
246 {
247 this->mData->object = object;
248 this->mData->manager = manager;
249 }
250 };
251
252 template <typename T>
253 class SharedResource11 : public Resource11Base<T, std::shared_ptr, TypedData<T>>
254 {
255 public:
SharedResource11()256 SharedResource11() {}
SharedResource11(SharedResource11 && movedObj)257 SharedResource11(SharedResource11 &&movedObj)
258 : Resource11Base<T, std::shared_ptr, TypedData<T>>(std::move(movedObj))
259 {
260 }
261
262 SharedResource11 &operator=(SharedResource11 &&other)
263 {
264 std::swap(this->mData, other.mData);
265 return *this;
266 }
267
makeCopy()268 SharedResource11 makeCopy() const
269 {
270 SharedResource11 copy;
271 copy.mData = this->mData;
272 return std::move(copy);
273 }
274
275 private:
276 friend class ResourceManager11;
SharedResource11(Resource11<T> && obj)277 SharedResource11(Resource11<T> &&obj) : Resource11Base<T, std::shared_ptr, TypedData<T>>()
278 {
279 std::swap(this->mData->manager, obj.mData->manager);
280
281 // Can't use std::swap because of ID3D11Resource.
282 auto temp = this->mData->object;
283 this->mData->object = obj.mData->object;
284 obj.mData->object = static_cast<T *>(temp);
285 }
286 };
287
288 class ResourceManager11 final : angle::NonCopyable
289 {
290 public:
291 ResourceManager11();
292 ~ResourceManager11();
293
294 template <typename T>
295 gl::Error allocate(Renderer11 *renderer,
296 const GetDescFromD3D11<T> *desc,
297 GetInitDataFromD3D11<T> *initData,
298 Resource11<T> *resourceOut);
299
300 template <typename T>
allocate(Renderer11 * renderer,const GetDescFromD3D11<T> * desc,GetInitDataFromD3D11<T> * initData,SharedResource11<T> * sharedRes)301 gl::Error allocate(Renderer11 *renderer,
302 const GetDescFromD3D11<T> *desc,
303 GetInitDataFromD3D11<T> *initData,
304 SharedResource11<T> *sharedRes)
305 {
306 Resource11<T> res;
307 ANGLE_TRY(allocate(renderer, desc, initData, &res));
308 *sharedRes = std::move(res);
309 return gl::NoError();
310 }
311
312 template <typename T>
onRelease(T * resource)313 void onRelease(T *resource)
314 {
315 onReleaseGeneric(GetResourceTypeFromD3D11<T>(), resource);
316 }
317
318 void onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource);
319
320 void setAllocationsInitialized(bool initialize);
321
322 private:
323 void incrResource(ResourceType resourceType, uint64_t memorySize);
324 void decrResource(ResourceType resourceType, uint64_t memorySize);
325
326 template <typename T>
327 GetInitDataFromD3D11<T> *createInitDataIfNeeded(const GetDescFromD3D11<T> *desc);
328
329 bool mInitializeAllocations;
330
331 std::array<size_t, NumResourceTypes> mAllocatedResourceCounts;
332 std::array<uint64_t, NumResourceTypes> mAllocatedResourceDeviceMemory;
333 angle::MemoryBuffer mZeroMemory;
334
335 std::vector<D3D11_SUBRESOURCE_DATA> mShadowInitData;
336 };
337
338 template <typename ResourceT>
~TypedData()339 TypedData<ResourceT>::~TypedData()
340 {
341 if (object)
342 {
343 // We can have a nullptr factory when holding passed-in resources.
344 if (manager)
345 {
346 manager->onRelease(object);
347 }
348 object->Release();
349 }
350 }
351
352 #define ANGLE_RESOURCE_TYPE_CLASS(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
353 using RESTYPE = Resource11<D3D11TYPE>;
354
355 namespace d3d11
356 {
357 ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS)
358
359 using SharedSRV = SharedResource11<ID3D11ShaderResourceView>;
360 } // namespace d3d11
361
362 #undef ANGLE_RESOURCE_TYPE_CLASS
363
364 } // namespace rx
365
366 #endif // LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
367