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