ResourceManager11.h (14466B)
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> 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 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> 175 constexpr size_t ResourceTypeIndex() 176 { 177 return static_cast<size_t>(GetResourceTypeFromD3D11<T>()); 178 } 179 180 template <typename T> 181 struct TypedData 182 { 183 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: 195 T *get() const { return mData->object; } 196 T *const *getPointer() const { return &mData->object; } 197 198 void setInternalName(const char *name) 199 { 200 mInternalDebugName = name; 201 UpdateDebugNameWithD3D(); 202 } 203 204 void setKHRDebugLabel(const std::string *label) 205 { 206 mKhrDebugName = label; 207 UpdateDebugNameWithD3D(); 208 } 209 210 void setLabels(const char *name, const std::string *label) 211 { 212 mInternalDebugName = name; 213 mKhrDebugName = label; 214 UpdateDebugNameWithD3D(); 215 } 216 217 void set(T *object) 218 { 219 ASSERT(!valid()); 220 mData->object = object; 221 } 222 223 bool valid() const { return (mData->object != nullptr); } 224 225 void reset() 226 { 227 if (valid()) 228 mData.reset(new DataT()); 229 } 230 231 ResourceSerial getSerial() const 232 { 233 return ResourceSerial(reinterpret_cast<uintptr_t>(mData->object)); 234 } 235 236 protected: 237 friend class TextureHelper11; 238 239 Resource11Base() : mData(new DataT()) {} 240 241 Resource11Base(Resource11Base &&movedObj) : mData(new DataT()) 242 { 243 std::swap(mData, movedObj.mData); 244 } 245 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: 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: 273 Resource11() {} 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 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: 299 SharedResource11() {} 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 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; 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> 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> 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> 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_