// // Copyright 2017 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // ResourceManager11: // Centralized point of allocation for all D3D11 Resources. #ifndef LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ #include #include #include "common/MemoryBuffer.h" #include "common/angleutils.h" #include "common/debug.h" #include "libANGLE/Error.h" #include "libANGLE/renderer/renderer_utils.h" namespace rx { // These two methods are declared here to prevent circular includes. namespace d3d11 { HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); template HRESULT SetDebugName(angle::ComPtr &resource, const char *name) { return SetDebugName(resource.Get(), name); } } // namespace d3d11 class Renderer11; class ResourceManager11; template class SharedResource11; class TextureHelper11; using InputElementArray = WrappedArray; using ShaderData = WrappedArray; // Format: ResourceType, D3D11 type, DESC type, init data type. #define ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ OP(NAME, BlendState, ID3D11BlendState, D3D11_BLEND_DESC, void) \ OP(NAME, Buffer, ID3D11Buffer, D3D11_BUFFER_DESC, const D3D11_SUBRESOURCE_DATA) \ OP(NAME, ComputeShader, ID3D11ComputeShader, ShaderData, void) \ OP(NAME, DepthStencilState, ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC, void) \ OP(NAME, DepthStencilView, ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, \ ID3D11Resource) \ OP(NAME, GeometryShader, ID3D11GeometryShader, ShaderData, \ const std::vector) \ OP(NAME, InputLayout, ID3D11InputLayout, InputElementArray, const ShaderData) \ OP(NAME, PixelShader, ID3D11PixelShader, ShaderData, void) \ OP(NAME, Query, ID3D11Query, D3D11_QUERY_DESC, void) \ OP(NAME, RasterizerState, ID3D11RasterizerState, D3D11_RASTERIZER_DESC, void) \ OP(NAME, RenderTargetView, ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, \ ID3D11Resource) \ OP(NAME, SamplerState, ID3D11SamplerState, D3D11_SAMPLER_DESC, void) \ OP(NAME, ShaderResourceView, ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, \ ID3D11Resource) \ OP(NAME, Texture2D, ID3D11Texture2D, D3D11_TEXTURE2D_DESC, const D3D11_SUBRESOURCE_DATA) \ OP(NAME, Texture3D, ID3D11Texture3D, D3D11_TEXTURE3D_DESC, const D3D11_SUBRESOURCE_DATA) \ OP(NAME, VertexShader, ID3D11VertexShader, ShaderData, void) #define ANGLE_RESOURCE_TYPE_LIST(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) RESTYPE, enum class ResourceType { ANGLE_RESOURCE_TYPE_OP(List, ANGLE_RESOURCE_TYPE_LIST) Last }; #undef ANGLE_RESOURCE_TYPE_LIST constexpr size_t ResourceTypeIndex(ResourceType resourceType) { return static_cast(resourceType); } constexpr size_t NumResourceTypes = ResourceTypeIndex(ResourceType::Last); #define ANGLE_RESOURCE_TYPE_TO_D3D11(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ \ template<> struct NAME \ { \ using Value = D3D11TYPE; \ }; #define ANGLE_RESOURCE_TYPE_TO_DESC(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ \ template<> struct NAME \ { \ using Value = DESCTYPE; \ }; #define ANGLE_RESOURCE_TYPE_TO_INIT_DATA(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ \ template<> struct NAME \ { \ using Value = INITDATATYPE; \ }; #define ANGLE_RESOURCE_TYPE_TO_TYPE(NAME, OP) \ template \ struct NAME; \ ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ \ template struct NAME \ { \ }; \ \ template using Get##NAME = typename NAME::Value; ANGLE_RESOURCE_TYPE_TO_TYPE(D3D11Type, ANGLE_RESOURCE_TYPE_TO_D3D11) ANGLE_RESOURCE_TYPE_TO_TYPE(DescType, ANGLE_RESOURCE_TYPE_TO_DESC) ANGLE_RESOURCE_TYPE_TO_TYPE(InitDataType, ANGLE_RESOURCE_TYPE_TO_INIT_DATA) #undef ANGLE_RESOURCE_TYPE_TO_D3D11 #undef ANGLE_RESOURCE_TYPE_TO_DESC #undef ANGLE_RESOURCE_TYPE_TO_INIT_DATA #undef ANGLE_RESOURCE_TYPE_TO_TYPE #define ANGLE_TYPE_TO_RESOURCE_TYPE(NAME, OP) \ template \ struct NAME; \ ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ \ template struct NAME \ { \ }; \ \ template constexpr ResourceType Get##NAME() \ { \ return NAME::Value; \ } #define ANGLE_D3D11_TO_RESOURCE_TYPE(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ \ template<> struct NAME \ { \ static constexpr ResourceType Value = ResourceType::RESTYPE; \ }; ANGLE_TYPE_TO_RESOURCE_TYPE(ResourceTypeFromD3D11, ANGLE_D3D11_TO_RESOURCE_TYPE) #undef ANGLE_D3D11_TO_RESOURCE_TYPE #undef ANGLE_TYPE_TO_RESOURCE_TYPE template using GetDescFromD3D11 = GetDescType::Value>; template using GetInitDataFromD3D11 = GetInitDataType::Value>; template constexpr size_t ResourceTypeIndex() { return static_cast(GetResourceTypeFromD3D11()); } template struct TypedData { TypedData() {} ~TypedData(); T *object = nullptr; ResourceManager11 *manager = nullptr; }; // Smart pointer type. Wraps the resource and a factory for safe deletion. template class Pointer, typename DataT> class Resource11Base : angle::NonCopyable { public: T *get() const { return mData->object; } T *const *getPointer() const { return &mData->object; } void setDebugName(const char *name) { d3d11::SetDebugName(mData->object, name); } void set(T *object) { ASSERT(!valid()); mData->object = object; } bool valid() const { return (mData->object != nullptr); } void reset() { if (valid()) mData.reset(new DataT()); } ResourceSerial getSerial() const { return ResourceSerial(reinterpret_cast(mData->object)); } protected: friend class TextureHelper11; Resource11Base() : mData(new DataT()) {} Resource11Base(Resource11Base &&movedObj) : mData(new DataT()) { std::swap(mData, movedObj.mData); } virtual ~Resource11Base() { mData.reset(); } Resource11Base &operator=(Resource11Base &&movedObj) { std::swap(mData, movedObj.mData); return *this; } Pointer mData; }; template using UniquePtr = typename std::unique_ptr>; template class Resource11 : public Resource11Base> { public: Resource11() {} Resource11(Resource11 &&other) : Resource11Base>(std::move(other)) { } Resource11 &operator=(Resource11 &&other) { std::swap(this->mData, other.mData); return *this; } private: template friend class SharedResource11; friend class ResourceManager11; Resource11(ResourceT *object, ResourceManager11 *manager) { this->mData->object = object; this->mData->manager = manager; } }; template class SharedResource11 : public Resource11Base> { public: SharedResource11() {} SharedResource11(SharedResource11 &&movedObj) : Resource11Base>(std::move(movedObj)) { } SharedResource11 &operator=(SharedResource11 &&other) { std::swap(this->mData, other.mData); return *this; } SharedResource11 makeCopy() const { SharedResource11 copy; copy.mData = this->mData; return std::move(copy); } private: friend class ResourceManager11; SharedResource11(Resource11 &&obj) : Resource11Base>() { std::swap(this->mData->manager, obj.mData->manager); // Can't use std::swap because of ID3D11Resource. auto temp = this->mData->object; this->mData->object = obj.mData->object; obj.mData->object = static_cast(temp); } }; class ResourceManager11 final : angle::NonCopyable { public: ResourceManager11(); ~ResourceManager11(); template gl::Error allocate(Renderer11 *renderer, const GetDescFromD3D11 *desc, GetInitDataFromD3D11 *initData, Resource11 *resourceOut); template gl::Error allocate(Renderer11 *renderer, const GetDescFromD3D11 *desc, GetInitDataFromD3D11 *initData, SharedResource11 *sharedRes) { Resource11 res; ANGLE_TRY(allocate(renderer, desc, initData, &res)); *sharedRes = std::move(res); return gl::NoError(); } template void onRelease(T *resource) { onReleaseGeneric(GetResourceTypeFromD3D11(), resource); } void onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource); void setAllocationsInitialized(bool initialize); private: void incrResource(ResourceType resourceType, uint64_t memorySize); void decrResource(ResourceType resourceType, uint64_t memorySize); template GetInitDataFromD3D11 *createInitDataIfNeeded(const GetDescFromD3D11 *desc); bool mInitializeAllocations; std::array mAllocatedResourceCounts; std::array mAllocatedResourceDeviceMemory; angle::MemoryBuffer mZeroMemory; std::vector mShadowInitData; }; template TypedData::~TypedData() { if (object) { // We can have a nullptr factory when holding passed-in resources. if (manager) { manager->onRelease(object); } object->Release(); } } #define ANGLE_RESOURCE_TYPE_CLASS(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ using RESTYPE = Resource11; namespace d3d11 { ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS) using SharedSRV = SharedResource11; } // namespace d3d11 #undef ANGLE_RESOURCE_TYPE_CLASS } // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_