diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-08-25 04:30:56 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-08-25 04:30:56 +0000 |
| commit | e4d4b58af6aedc7a0bffd821d86947f3b7c8b937 (patch) | |
| tree | 1610c6de05bb2d1e73ad0658e9be245960ce5744 /Graphics/GraphicsEngineD3D12 | |
| parent | Implemented shader variable access by Index in GL backend (diff) | |
| download | DiligentCore-e4d4b58af6aedc7a0bffd821d86947f3b7c8b937.tar.gz DiligentCore-e4d4b58af6aedc7a0bffd821d86947f3b7c8b937.zip | |
Fixed https://github.com/DiligentGraphics/DiligentCore/issues/16 (Rework D3D12 shader resource layout to use shader variable manager)
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
12 files changed, 795 insertions, 744 deletions
diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt index f0902987..0bdae324 100644 --- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt @@ -29,6 +29,7 @@ set(INCLUDE include/ShaderResourceCacheD3D12.h include/ShaderResourceLayoutD3D12.h include/ShaderResourcesD3D12.h + include/ShaderVariableD3D12.h include/SwapChainD3D12Impl.h include/TextureD3D12Impl.h include/TextureViewD3D12Impl.h @@ -76,6 +77,7 @@ set(SRC src/ShaderResourceCacheD3D12.cpp src/ShaderResourceLayoutD3D12.cpp src/ShaderResourcesD3D12.cpp + src/ShaderVariableD3D12.cpp src/SwapChainD3D12Impl.cpp src/TextureD3D12Impl.cpp src/TextureViewD3D12Impl.cpp diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h index ecc26865..4d4ef36c 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h @@ -32,16 +32,12 @@ #include "ShaderD3DBase.h" #include "ShaderResourceLayoutD3D12.h" #include "RenderDeviceD3D12Impl.h" - -#ifdef _DEBUG -# define VERIFY_SHADER_BINDINGS -#endif +#include "ShaderVariableD3D12.h" namespace Diligent { class ResourceMapping; -class FixedBlockMemoryAllocator; /// Implementation of the Diligent::IShaderD3D12 interface class ShaderD3D12Impl final : public ShaderBase<IShaderD3D12, RenderDeviceD3D12Impl>, public ShaderD3DBase @@ -54,42 +50,44 @@ public: const ShaderCreationAttribs& ShaderCreationAttribs); ~ShaderD3D12Impl(); - //virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; + virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; - virtual void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )override + virtual void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )override final { - m_StaticResLayout.BindResources(pResourceMapping, Flags, &m_StaticResCache); + m_StaticVarsMgr.BindResources(pResourceMapping, Flags); } virtual IShaderVariable* GetShaderVariable(const Char* Name)override final { - return m_StaticResLayout.GetShaderVariable(Name); + return m_StaticVarsMgr.GetVariable(Name); } virtual Uint32 GetVariableCount() const override final { - return m_StaticResLayout.GetVariableCount(); + return m_StaticVarsMgr.GetVariableCount(); } virtual IShaderVariable* GetShaderVariable(Uint32 Index)override final { - return m_StaticResLayout.GetShaderVariable(Index); + return m_StaticVarsMgr.GetVariable(Index); } ID3DBlob* GetShaderByteCode(){return m_pShaderByteCode;} - const std::shared_ptr<const ShaderResourcesD3D12>& GetShaderResources()const{return m_pShaderResources;} - const ShaderResourceLayoutD3D12& GetStaticResLayout()const{return m_StaticResLayout;} + const std::shared_ptr<const ShaderResourcesD3D12>& GetShaderResources()const { return m_pShaderResources; } + const ShaderResourceLayoutD3D12& GetStaticResLayout()const { return m_StaticResLayout; } + const ShaderResourceCacheD3D12& GetStaticResCache() const { return m_StaticResCache; } -#ifdef VERIFY_SHADER_BINDINGS - void DbgVerifyStaticResourceBindings(); +#ifdef DEVELOPMENT + void DvpVerifyStaticResourceBindings(); #endif private: // ShaderResources class instance must be referenced through the shared pointer, because // it is referenced by ShaderResourceLayoutD3D12 class instances std::shared_ptr<const ShaderResourcesD3D12> m_pShaderResources; - ShaderResourceLayoutD3D12 m_StaticResLayout; - ShaderResourceCacheD3D12 m_StaticResCache; + ShaderResourceLayoutD3D12 m_StaticResLayout; + ShaderResourceCacheD3D12 m_StaticResCache; + ShaderVariableManagerD3D12 m_StaticVarsMgr; }; } diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h index 968ac85c..5a237414 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h @@ -32,12 +32,13 @@ #include "ShaderBase.h" #include "ShaderResourceCacheD3D12.h" #include "ShaderResourceLayoutD3D12.h" +#include "ShaderVariableD3D12.h" namespace Diligent { -class FixedBlockMemoryAllocator; /// Implementation of the Diligent::IShaderResourceBindingD3D12 interface +// sizeof(ShaderResourceBindingD3D12Impl) == 152 (x64, msvc, Release) class ShaderResourceBindingD3D12Impl final : public ShaderResourceBindingBase<IShaderResourceBindingD3D12> { public: @@ -58,15 +59,10 @@ public: virtual IShaderVariable* GetVariable(SHADER_TYPE ShaderType, Uint32 Index)override final; - ShaderResourceLayoutD3D12& GetResourceLayout(Uint32 ResLayoutInd) - { - VERIFY_EXPR(ResLayoutInd < m_NumShaders); - return m_pResourceLayouts[ResLayoutInd]; - } ShaderResourceCacheD3D12& GetResourceCache(){return m_ShaderResourceCache;} -#ifdef VERIFY_SHADER_BINDINGS - void dbgVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO); +#ifdef DEVELOPMENT + void dvpVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO); #endif bool StaticResourcesInitialized()const{return m_bStaticResourcesInitialized;} @@ -75,11 +71,11 @@ public: private: ShaderResourceCacheD3D12 m_ShaderResourceCache; - ShaderResourceLayoutD3D12* m_pResourceLayouts = nullptr; + ShaderVariableManagerD3D12* m_pShaderVarMgrs = nullptr; // Resource layout index in m_ResourceLayouts[] array for every shader stage Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; bool m_bStaticResourcesInitialized = false; - const Uint32 m_NumShaders = 0; + const Uint8 m_NumShaders = 0; }; } diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h index dc4f61a8..fb7a08d5 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h @@ -142,16 +142,22 @@ public: m_pResources (pResources) {} - inline Resource& GetResource(Uint32 OffsetFromTableStart, - const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, - const SHADER_TYPE dbgRefShaderType) + inline const Resource& GetResource(Uint32 OffsetFromTableStart, + const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, + const SHADER_TYPE dbgRefShaderType)const { VERIFY(m_dbgHeapType == dbgDescriptorHeapType, "Incosistent descriptor heap type" ); VERIFY(m_dbgShaderType == dbgRefShaderType, "Incosistent shader type" ); - VERIFY(OffsetFromTableStart < m_NumResources, "Root table at index is not large enough to store descriptor at offset ", OffsetFromTableStart ); + VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart ); return m_pResources[OffsetFromTableStart]; } + inline Resource& GetResource(Uint32 OffsetFromTableStart, + const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, + const SHADER_TYPE dbgRefShaderType) + { + return const_cast<Resource&>(const_cast<const RootTable*>(this)->GetResource(OffsetFromTableStart, dbgDescriptorHeapType, dbgRefShaderType)); + } inline Uint32 GetSize()const{return m_NumResources; } @@ -187,6 +193,11 @@ public: VERIFY_EXPR(RootIndex < m_NumTables); return reinterpret_cast<RootTable*>(m_pMemory)[RootIndex]; } + inline const RootTable& GetRootTable(Uint32 RootIndex)const + { + VERIFY_EXPR(RootIndex < m_NumTables); + return reinterpret_cast<const RootTable*>(m_pMemory)[RootIndex]; + } inline Uint32 GetNumRootTables()const{return m_NumTables; } diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h index 9b9520f4..f32e89eb 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h @@ -30,54 +30,52 @@ // All resources are stored in a single continuous chunk of memory using the following layout: // -// m_ResourceBuffer m_Samplers -// | | -// | SRV_CBV_UAV[0] ... SRV_CBV_UAV[s-1] | SRV_CBV_UAV[s] ... SRV_CBV_UAV[s+m-1] | SRV_CBV_UAV[s+m] ... SRV_CBV_UAV[s+m+d-1] || Sampler[0] ... Sampler[s'-1] | Sampler[s'] ... Sampler[s'+m'-1] | Sampler[s'+m'] ... Sampler[s'+m'+d'-1] || -// | | | || | | || -// | SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC || SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC || -// | | | || +// m_ResourceBuffer +// | | | +// | D3D12Resource[0] ... | D3D12Resource[s] ... | D3D12Resource[s+m] ... | D3D12Resource[smd] ... | D3D12Resource[smd+s'] ... | D3D12Resource[smd+s'+m'] ... D3D12Resource[s+m+d+s'+m'+d'-1] || +// | | | | | | || +// | SRV/CBV/UAV - STATIC | SRV/CBV/UAV - MUTABLE | SRV/CBV/UAV - DYNAMIC | Samplers - STATIC | Samplers - MUTABLE | Samplers - DYNAMIC || +// | | | | // -// s == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] -// m == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] -// d == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC] +// s == NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] +// m == NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] +// d == NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC] +// smd = s+m+d // -// s' == m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] -// m' == m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] -// d' == m_NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC] +// s' == NumSamplers[SHADER_VARIABLE_TYPE_STATIC] +// m' == NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] +// d' == NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC] // +// Every D3D12Resource structure holds a reference to D3DShaderResourceAttribs structure from ShaderResourcesD3D12. +// ShaderResourceLayoutD3D12 holds shared pointer to ShaderResourcesD3D12 instance. Note that ShaderResourcesD3D12::SamplerId +// references a sampler in ShaderResourcesD3D12, while D3D12Resource::SamplerId references a sampler in ShaderResourceLayoutD3D12, +// and the two are not necessarily the same // -// Memory buffer is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block -// memory allocator is used. This ensures that all resources from different shader resource bindings reside in -// continuous memory. If allocation granularity == 1, raw allocator is used. -// -// -// Every SRV_CBV_UAV and Sampler structure holds a reference to D3DShaderResourceAttribs structure from ShaderResources. -// ShaderResourceLayoutD3D12 holds shared pointer to ShaderResourcesD3D12 instance. Note that ShaderResources::SamplerId -// references a sampler in ShaderResources, while SRV_CBV_UAV::SamplerId references a sampler in ShaderResourceLayoutD3D12, -// and the two are not the same -// -// -// ________________SamplerId____________________ -// | | -// _________________ ______________|_____________________________________________V________ -// | | unique_ptr | | | | | | | -// | ShaderResources |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | -// |_________________| |________|___________|___________|___________|___________|____________| +// +// ________________SamplerId____________________ +// | | +// _____________________ ______________|_____________________________________________V________ +// | | unique_ptr | | | | | | | +// |ShaderResourcesD3D12 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | +// |_____________________| |________|___________|___________|___________|___________|____________| // A A A A // | \ / \ // |shared_ptr Ref Ref Ref -// ________|__________________ ________\________________________/_________________________\_________________________________________ -// | | unique_ptr | | | | | | | -// | ShaderResourceLayoutD3D12 |--------------->| SRV_CBV_UAV[0] | SRV_CBV_UAV[1] | ... | Sampler[0] | Sampler[1] | ... | -// |___________________________| |___________________|_________________|_______________|__________________|_________________|__________| -// | | | A | / -// | Raw ptr | |___________________SamplerId________________________| | / -// | | / / -// | \ / / -// ________V_________________ ________V_______________________________________________________V____V__ -// | | | | -// | ShaderResourceCacheD3D12 |---------------->| Resources | -// |__________________________| |________________________________________________________________________| +// ________|__________________ ________\________________________/_________________________\________________________________________________ +// | | unique_ptr | | | | | | | +// | ShaderResourceLayoutD3D12 |--------------->| D3D12Resource[0] | D3D12Resource[1] | ... | D3D12Resource[smd] | D3D12Resource[smd+1] | ... | +// |___________________________| |__________________|__________________|_______________|____________________|______________________|__________| +// A A | A A +// | \ |______________\____SamplerId________________________| +// | \ \ +// | Ref Ref +// | \ \_____ +// | \ \ +// ____________|_______________ ________\_______________________\__________________________________________ +// | | | | | | +// | ShaderVariableManagerD3D12 |---------------->| ShaderVariableD3D12Impl[0] | ShaderVariableD3D12Impl[1] | ... | +// |____________________________| |____________________________|____________________________|_________________| + // // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Figure2 // Resources in the resource cache are identified by the root index and offset in the descriptor table @@ -85,58 +83,34 @@ // // ShaderResourceLayoutD3D12 is used as follows: // * Every pipeline state object (PipelineStateD3D12Impl) maintains shader resource layout for every active shader stage -// ** These resource layouts are not bound to a resource cache and are used as reference layouts for shader resource binding objects +// ** These resource layouts are used as reference layouts for shader resource binding objects // ** All variable types are preserved // ** Root indices and descriptor table offsets are assigned during the initialization -// ** Resource cache is not assigned // * Every shader object (ShaderD3D12Impl) contains shader resource layout that facilitates management of static shader resources -// ** The resource layout defines artificial layout and is bound to a resource cache that actually holds references to resources -// ** Resource cache is assigned and initialized -// * Every shader resource binding object (ShaderResourceBindingD3D12Impl) encompasses shader resource layout for every active shader -// stage in the parent pipeline state -// ** Resource layouts are initialized by clonning reference layouts from the pipeline state object and are bound to the resource -// cache that holds references to resources set by the application -// ** All shader variable types are clonned -// ** Resource cache is assigned, but not initialized; Initialization is performed by the root signature +// ** The resource layout defines artificial layout where root index matches the resource type (CBV/SRV/UAV/SAM) +// ** Only static variables are referenced // +// * Every shader resource binding object (ShaderResourceBindingD3D12Impl) encompasses shader variable +// manager (ShaderVariableManagerD3D12) for every active shader stage in the parent pipeline state that +// handles mutable and dynamic resources +// * Every shader object (ShaderD3D12Impl) constains shader variable manager that handles static resources -// Set this define to 1 to use unordered_map to store shader variables. -// Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64). -#define USE_VARIABLE_HASH_MAP 0 - -#include <unordered_map> #include <array> -#include "ShaderD3DBase.h" #include "ShaderBase.h" -#include "HashUtils.h" #include "ShaderResourcesD3D12.h" #include "ShaderResourceCacheD3D12.h" -#include "ShaderVariableD3DBase.h" - -#ifdef _DEBUG -# define VERIFY_SHADER_BINDINGS -#endif namespace Diligent { /// Diligent::ShaderResourceLayoutD3D12 class -// sizeof(ShaderResourceLayoutD3D12)==80 (MS compiler, x64) -class ShaderResourceLayoutD3D12 +// sizeof(ShaderResourceLayoutD3D12) == 64 (MS compiler, x64) +class ShaderResourceLayoutD3D12 final { public: ShaderResourceLayoutD3D12(IObject& Owner, IMemoryAllocator& ResourceLayoutDataAllocator); - // This constructor is used by ShaderResourceBindingD3D12Impl to clone layout from the reference layout in PipelineStateD3D12Impl. - // Root indices and descriptor table offsets must be correct. Resource cache is assigned, but not initialized. - ShaderResourceLayoutD3D12(IObject& Owner, - const ShaderResourceLayoutD3D12& SrcLayout, - IMemoryAllocator& ResourceLayoutDataAllocator, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12& ResourceCache); - ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete; ShaderResourceLayoutD3D12 (ShaderResourceLayoutD3D12&&) = delete; ShaderResourceLayoutD3D12& operator =(const ShaderResourceLayoutD3D12&) = delete; @@ -144,123 +118,85 @@ public: ~ShaderResourceLayoutD3D12(); - static size_t GetRequiredMemorySize(const ShaderResourceLayoutD3D12& SrcLayout, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes); - // The method is called by // - ShaderD3D12Impl class instance to initialize static resource layout and initialize shader resource cache // to hold static resources // - PipelineStateD3D12Impl class instance to reference all types of resources (static, mutable, dynamic). // Root indices and descriptor table offsets are assigned during the initialization; // no shader resource cache is provided - void Initialize(ID3D12Device* pd3d12Device, - const std::shared_ptr<const ShaderResourcesD3D12>& pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_VARIABLE_TYPE* VarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - class RootSignature* pRootSig); - - using ShaderVariableD3D12Base = ShaderVariableD3DBase<ShaderResourceLayoutD3D12>; - - // sizeof(SRV_CBV_UAV) == 32 (x64) - struct SRV_CBV_UAV : ShaderVariableD3D12Base + void Initialize(ID3D12Device* pd3d12Device, + std::shared_ptr<const ShaderResourcesD3D12> pSrcResources, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_VARIABLE_TYPE* VarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + class RootSignature* pRootSig); + + // sizeof(D3D12Resource) == 24 (x64) + struct D3D12Resource final { - SRV_CBV_UAV (const SRV_CBV_UAV&) = delete; - SRV_CBV_UAV (SRV_CBV_UAV&&) = delete; - SRV_CBV_UAV& operator = (const SRV_CBV_UAV&) = delete; - SRV_CBV_UAV& operator = (SRV_CBV_UAV&&) = delete; - - static constexpr Uint32 ResTypeBits = 3; - static constexpr Uint32 RootIndBits = 16-ResTypeBits; - static constexpr Uint32 RootIndMask = (1 << RootIndBits)-1; - static constexpr Uint32 ResTypeMask = (1 << ResTypeBits)-1; - - static constexpr Uint16 InvalidRootIndex = RootIndMask; - static constexpr Uint16 MaxRootIndex = RootIndMask-1; - - static constexpr Uint32 InvalidSamplerId = 0xFFFF; - static constexpr Uint32 MaxSamplerId = InvalidSamplerId-1; - static constexpr Uint32 InvalidOffset = static_cast<Uint32>(-1); - - static_assert( static_cast<int>(CachedResourceType::NumTypes) <= ResTypeMask, "3 bits is not enough to store CachedResourceType"); - - const Uint32 OffsetFromTableStart; - - // Special copy constructor. Note that sampler ID refers to the ID of the sampler - // within THIS layout, and may not be the same as in original layout - SRV_CBV_UAV(ShaderResourceLayoutD3D12& ParentLayout, - const SRV_CBV_UAV& rhs, - Uint32 SamId)noexcept : - ShaderVariableD3DBase<ShaderResourceLayoutD3D12>(ParentLayout, rhs.Attribs), - ResType_RootIndex (rhs.ResType_RootIndex), - SamplerId (static_cast<Uint16>(SamId)), - OffsetFromTableStart(rhs.OffsetFromTableStart) - { - VERIFY(SamId == InvalidSamplerId || SamId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" ); - VERIFY(rhs.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references"); - VERIFY(IsValidOffset(), "Offset must be valid" ); - VERIFY(IsValidRootIndex(), "Root index must be valid" ); - } + D3D12Resource (const D3D12Resource&) = delete; + D3D12Resource (D3D12Resource&&) = delete; + D3D12Resource& operator = (const D3D12Resource&) = delete; + D3D12Resource& operator = (D3D12Resource&&) = delete; - SRV_CBV_UAV(ShaderResourceLayoutD3D12& ParentLayout, - const D3DShaderResourceAttribs& _Attribs, - CachedResourceType ResType, - Uint32 RootIndex, - Uint32 _OffsetFromTableStart, - Uint32 _SamplerId)noexcept : - ShaderVariableD3DBase<ShaderResourceLayoutD3D12>(ParentLayout, _Attribs), - ResType_RootIndex ( (static_cast<Uint16>(ResType) << RootIndBits) | (RootIndex & RootIndMask)), - SamplerId ( static_cast<Uint16>(_SamplerId) ), - OffsetFromTableStart( _OffsetFromTableStart ) - { - VERIFY(RootIndex == InvalidRootIndex || RootIndex <= MaxRootIndex, "Root index exceeds max allowed value (", MaxRootIndex, ")" ); - VERIFY(IsValidOffset(), "Offset must be valid" ); - VERIFY(SamplerId == InvalidSamplerId || SamplerId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" ); - } + static constexpr const Uint32 ResourceTypeBits = 3; + static constexpr const Uint32 RootIndexBits = 16 - ResourceTypeBits; - bool IsBound(Uint32 ArrayIndex)const; + static constexpr const Uint32 InvalidRootIndex = (1 << RootIndexBits) - 1; + static constexpr const Uint32 MaxRootIndex = InvalidRootIndex - 1; - // Non-virtual function - void BindResource(IDeviceObject *pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D12 *dbgResLayout); - virtual void Set(IDeviceObject *pObject)override final{ BindResource(pObject, 0, nullptr); } + static constexpr const Uint32 InvalidSamplerId = 0xFFFF; + static constexpr const Uint32 MaxSamplerId = InvalidSamplerId-1; + static constexpr const Uint32 InvalidOffset = static_cast<Uint32>(-1); - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final + static_assert( static_cast<int>(CachedResourceType::NumTypes) < (1 << ResourceTypeBits), "3 bits is not enough to store CachedResourceType"); + + const ShaderResourceLayoutD3D12& ParentResLayout; + const D3DShaderResourceAttribs& Attribs; + const Uint32 OffsetFromTableStart; + const Uint16 ResourceType : ResourceTypeBits; // | 0 1 2 | + const Uint16 RootIndex : RootIndexBits; // | 3 4 5 ... 15 | + const Uint16 SamplerId; + + D3D12Resource(const ShaderResourceLayoutD3D12& _ParentLayout, + const D3DShaderResourceAttribs& _Attribs, + CachedResourceType _ResType, + Uint32 _RootIndex, + Uint32 _OffsetFromTableStart, + Uint32 _SamplerId)noexcept : + ParentResLayout (_ParentLayout), + Attribs (_Attribs), + ResourceType (static_cast<Uint16>(_ResType)), + RootIndex (static_cast<Uint16>(_RootIndex)), + SamplerId (static_cast<Uint16>(_SamplerId)), + OffsetFromTableStart( _OffsetFromTableStart ) { - for(Uint32 Elem = 0; Elem < NumElements; ++Elem) - BindResource(ppObjects[Elem], FirstElement+Elem, nullptr); + VERIFY(IsValidOffset(), "Offset must be valid"); + VERIFY(IsValidRootIndex(), "Root index must be valid"); + VERIFY(_RootIndex <= MaxRootIndex, "Root index (", _RootIndex, ") exceeds max allowed value (", MaxRootIndex, ")" ); + VERIFY(_SamplerId == InvalidSamplerId || _SamplerId <= MaxSamplerId, "Sampler id (", _SamplerId, ") exceeds max allowed value (", MaxSamplerId, ")" ); + VERIFY(_SamplerId == InvalidSamplerId || GetResType() == CachedResourceType::TexSRV, "A sampler can only be assigned to a Texture SRV"); } - bool IsValidSampler() const { return GetSamplerId() != InvalidSamplerId; } - bool IsValidRootIndex()const { return GetRootIndex() != InvalidRootIndex; } - bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; } + bool IsBound(Uint32 ArrayIndex, + const ShaderResourceCacheD3D12& ResourceCache)const; - CachedResourceType GetResType()const - { - return static_cast<CachedResourceType>( (ResType_RootIndex >> RootIndBits) & ResTypeMask ); - } - Uint32 GetRootIndex()const - { - return ResType_RootIndex & RootIndMask; - } + void BindResource(IDeviceObject* pObject, + Uint32 ArrayIndex, + ShaderResourceCacheD3D12& ResourceCache)const; - Uint32 GetSamplerId()const - { - return SamplerId; - } + bool IsValidSampler() const { return SamplerId != InvalidSamplerId; } + bool IsValidRootIndex()const { return RootIndex != InvalidRootIndex; } + bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; } - private: - const Uint16 ResType_RootIndex; // bit - // | 0 1 .... 12 | 13 14 15 | - // | | | - // | Root index | ResType | - const Uint16 SamplerId; + CachedResourceType GetResType() const { return static_cast<CachedResourceType>( ResourceType ); } + private: void CacheCB(IDeviceObject* pBuffer, ShaderResourceCacheD3D12::Resource& DstRes, Uint32 ArrayInd, - D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle); + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)const; template<typename TResourceViewType, typename TViewTypeEnum, @@ -270,98 +206,24 @@ public: Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, TViewTypeEnum dbgExpectedViewType, - TBindSamplerProcType BindSamplerProc); - }; + TBindSamplerProcType BindSamplerProc)const; - // sizeof(Sampler) == 24 (x64) - struct Sampler - { - Sampler (const Sampler&) = delete; - Sampler (Sampler&&) = delete; - Sampler& operator = (const Sampler&) = delete; - Sampler& operator = (Sampler&&) = delete; - - const D3DShaderResourceAttribs& Attribs; - ShaderResourceLayoutD3D12& m_ParentResLayout; - - static constexpr Uint32 InvalidRootIndex = static_cast<Uint32>(-1); - static constexpr Uint32 InvalidOffset = static_cast<Uint32>(-1); - - const Uint32 RootIndex; - const Uint32 OffsetFromTableStart; - - Sampler(ShaderResourceLayoutD3D12 &ParentLayout, const Sampler& Sam)noexcept : - Attribs (Sam.Attribs), - m_ParentResLayout (ParentLayout), - RootIndex (Sam.RootIndex), - OffsetFromTableStart(Sam.OffsetFromTableStart) - { - VERIFY(Sam.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references"); - VERIFY(IsValidRootIndex(), "Root index must be valid" ); - VERIFY(IsValidOffset(), "Offset must be valid" ); - } - - Sampler(ShaderResourceLayoutD3D12& ParentResLayout, - const D3DShaderResourceAttribs& _Attribs, - Uint32 _RootIndex, - Uint32 _OffsetFromTableStart)noexcept : - RootIndex (_RootIndex), - OffsetFromTableStart(_OffsetFromTableStart), - Attribs (_Attribs), - m_ParentResLayout (ParentResLayout) - { - VERIFY(IsValidRootIndex(), "Root index must be valid" ); - VERIFY(IsValidOffset(), "Offset must be valid" ); - } - - bool IsValidRootIndex()const { return RootIndex != InvalidRootIndex; } - bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; } - - void CacheSampler(class ITextureViewD3D12 *pTexViewD3D12, Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle); + void CacheSampler(class ITextureViewD3D12* pTexViewD3D12, + ShaderResourceCacheD3D12::Resource& DstSam, + Uint32 ArrayIndex, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)const; }; + void CopyStaticResourceDesriptorHandles(const ShaderResourceCacheD3D12& SrcCache, + const ShaderResourceLayoutD3D12& DstLayout, + ShaderResourceCacheD3D12& DstCache)const; - void CopyStaticResourceDesriptorHandles(const ShaderResourceLayoutD3D12 &DstLayout, ShaderResourceCacheD3D12& DstCache)const; - - // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive - // while Layout is alive - void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D12 *dbgResourceCache ); - - IShaderVariable* GetShaderVariable( const Char* Name ); - IShaderVariable* GetShaderVariable( Uint32 Index ); - -#ifdef VERIFY_SHADER_BINDINGS - void dbgVerifyBindings(ShaderResourceCacheD3D12& ResourceCache)const; +#ifdef DEVELOPMENT + void dvpVerifyBindings(ShaderResourceCacheD3D12& ResourceCache)const; #endif IObject& GetOwner(){return m_Owner;} - const ShaderResourcesD3D12& GetShaderResources(){return *m_pResources;} - - Uint32 GetVariableIndex(const ShaderVariableD3D12Base& Variable)const; - - Uint32 GetVariableCount()const - { - return GetTotalSrvCbvUavCount(); - } - -private: - void InitVariablesHashMap(); - - const Sampler& GetAssignedSampler(const SRV_CBV_UAV &TexSrv)const; - Sampler& GetAssignedSampler(const SRV_CBV_UAV &TexSrv); - - const Char* GetShaderName()const; - - // There is no need to use shared ptr as referenced resource cache is either part of the - // parent ShaderD3D12Impl object or ShaderResourceBindingD3D12Impl object - ShaderResourceCacheD3D12* m_pResourceCache; - - std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer; - Sampler* m_Samplers = nullptr; - std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES + 1> m_CbvSrvUavOffsets = {}; - std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES + 1> m_SamplersOffsets = {}; - Uint32 GetCbvSrvUavCount(SHADER_VARIABLE_TYPE VarType)const { return m_CbvSrvUavOffsets[VarType + 1] - m_CbvSrvUavOffsets[VarType]; @@ -370,38 +232,61 @@ private: { return m_SamplersOffsets[VarType + 1] - m_SamplersOffsets[VarType]; } + + const D3D12Resource& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r)const + { + VERIFY_EXPR( r < GetCbvSrvUavCount(VarType) ); + return GetResource(GetSrvCbvUavOffset(VarType,r)); + } + const D3D12Resource& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s)const + { + VERIFY_EXPR( s < GetSamplerCount(VarType) ); + return GetResource(GetSamplerOffset(VarType,s)); + } + +private: + const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv)const; + D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv); + + const Char* GetShaderName()const; + Uint32 GetTotalSrvCbvUavCount()const { + VERIFY_EXPR(m_CbvSrvUavOffsets[0] == 0); return m_CbvSrvUavOffsets[SHADER_VARIABLE_TYPE_NUM_TYPES]; } Uint32 GetTotalSamplerCount()const { + return m_SamplersOffsets[SHADER_VARIABLE_TYPE_NUM_TYPES] - m_SamplersOffsets[0]; + } + Uint32 GetTotalResourceCount()const + { return m_SamplersOffsets[SHADER_VARIABLE_TYPE_NUM_TYPES]; } + D3D12Resource& GetResource(Uint32 r) + { + VERIFY_EXPR(r < GetTotalResourceCount()); + auto* Resource = reinterpret_cast<D3D12Resource*>(m_ResourceBuffer.get()); + return Resource[r]; + } + const D3D12Resource& GetResource(Uint32 r)const + { + VERIFY_EXPR(r < GetTotalResourceCount()); + auto* Resource = reinterpret_cast<const D3D12Resource*>(m_ResourceBuffer.get()); + return Resource[r]; + } + Uint32 GetSrvCbvUavOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const { Uint32 Offset = m_CbvSrvUavOffsets[VarType] + r; VERIFY_EXPR( Offset < m_CbvSrvUavOffsets[VarType+1] ); return Offset; } - SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r) + D3D12Resource& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r) { VERIFY_EXPR( r < GetCbvSrvUavCount(VarType) ); - auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get()); - return CbvSrvUav[ GetSrvCbvUavOffset(VarType,r) ]; - } - const SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r)const - { - VERIFY_EXPR( r < GetCbvSrvUavCount(VarType) ); - auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get()); - return CbvSrvUav[GetSrvCbvUavOffset(VarType,r)]; - } - SRV_CBV_UAV& GetSrvCbvUav(Uint32 r) - { - VERIFY_EXPR( r < GetTotalSrvCbvUavCount() ); - auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get()); - return CbvSrvUav[r]; + return GetResource(GetSrvCbvUavOffset(VarType,r)); } Uint32 GetSamplerOffset(SHADER_VARIABLE_TYPE VarType, Uint32 s)const @@ -410,30 +295,22 @@ private: VERIFY_EXPR( Offset < m_SamplersOffsets[VarType+1] ); return Offset; } - Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s) + D3D12Resource& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s) { VERIFY_EXPR( s < GetSamplerCount(VarType) ); - return m_Samplers[GetSamplerOffset(VarType,s)]; - } - const Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s)const - { - VERIFY_EXPR( s < GetSamplerCount(VarType) ); - return m_Samplers[GetSamplerOffset(VarType,s)]; + return GetResource(GetSamplerOffset(VarType,s)); } void AllocateMemory(IMemoryAllocator& Allocator, const std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES>& CbvSrvUavCount, const std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES>& SamplerCount); -#if USE_VARIABLE_HASH_MAP - // Hash map to look up shader variables by name. - // Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64). - typedef std::pair<HashMapStringKey, IShaderVariable*> VariableHashElemType; - std::unordered_map<HashMapStringKey, IShaderVariable*, std::hash<HashMapStringKey>, std::equal_to<HashMapStringKey>, STDAllocatorRawMem<VariableHashElemType> > m_VariableHash; -#endif + std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer; + std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES + 1> m_CbvSrvUavOffsets = {}; + std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES + 1> m_SamplersOffsets = {}; - CComPtr<ID3D12Device> m_pd3d12Device; - IObject &m_Owner; + CComPtr<ID3D12Device> m_pd3d12Device; + IObject& m_Owner; // We must use shared_ptr to reference ShaderResources instance, because // there may be multiple objects referencing the same set of resources std::shared_ptr<const ShaderResourcesD3D12> m_pResources; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h index fe3dba66..c5b2e0d9 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h @@ -27,7 +27,7 @@ /// Declaration of Diligent::ShaderResourcesD3D12 class // ShaderResourcesD3D12 are created by ShaderD3D12Impl instances. They are then referenced by ShaderResourceLayoutD3D12 objects, which are in turn -// created by instances of PipelineStatesD3D12Impl and ShaderResourceBindingsD3D12Impl (and ShaderD3D12Impl too) +// created by instances of PipelineStatesD3D12Impl and ShaderD3D12Impl // // _________________ // | | @@ -55,28 +55,28 @@ // |________________________| // // -// One ShaderResources instance can be referenced by multiple objects // -// -// ________________________ _<m_ShaderResourceLayouts>_ ____<m_pResourceLayouts>___ ________________________________ -// | | | | | | | | -// | PipelineStateD3D12Impl |-------->| ShaderResourceLayoutD3D12 | ----| ShaderResourceLayoutD3D12 |<-----| ShaderResourceBindingD3D12Impl | -// |________________________| |___________________________| | |___________________________| |________________________________| -// | | -// | shared_ptr | -// _________________ ___________V__________ | ____<m_pResourceLayouts>___ ________________________________ -// | | shared_ptr | | shared_ptr| | | | | -// | ShaderD3D12Impl |--------------->| ShaderResourcesD3D12 |<---------------| ShaderResourceLayoutD3D12 |<-----| ShaderResourceBindingD3D12Impl | -// |_________________| |______________________| | |___________________________| |________________________________| -// | A | -// V | | -// ____<m_StaticResLayout>____ | | ____<m_pResourceLayouts>___ ________________________________ -// | | shared_ptr | | | | | | -// | ShaderResourceLayoutD3D12 |------------------- ----| ShaderResourceLayoutD3D12 |<-----| ShaderResourceBindingD3D12Impl | -// |___________________________| |___________________________| |________________________________| -// -// - +// One ShaderResourcesD3D12 instance can be referenced by multiple objects +// +// +// ________________________ _<m_pShaderResourceLayouts>_ _____<m_pShaderVarMgrs>_____ ________________________________ +// | | | | | | | | +// | PipelineStateD3D12Impl |========>| ShaderResourceLayoutD3D12 |<-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl | +// |________________________| |____________________________| |____________________________| |________________________________| +// | A +// |shared_ptr \ +// _________________ ___________V__________ \ _____<m_pShaderVarMgrs>_____ ________________________________ +// | | shared_ptr | | \ | | | | +// | ShaderD3D12Impl |---------------->| ShaderResourcesD3D12 | '-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl | +// |_________________| |______________________| |____________________________| |________________________________| +// | |___________________ A +// | | | +// V V |shared_ptr +// _______<m_StaticVarsMgr>____ ___<m_StaticResLayout>_|___ +// | | | | +// | ShaderVariableManagerD3D12 |------>| ShaderResourceLayoutD3D12 | +// |____________________________| |___________________________| +// #include "ShaderResources.h" @@ -84,7 +84,7 @@ namespace Diligent { /// Diligent::ShaderResources class -class ShaderResourcesD3D12 : public ShaderResources +class ShaderResourcesD3D12 final : public ShaderResources { public: // Loads shader resources from the compiled shader bytecode diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.h new file mode 100644 index 00000000..ff2c3b9a --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.h @@ -0,0 +1,209 @@ +/* Copyright 2015-2018 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Declaration of Diligent::ShaderVariableManagerD3D12 and Diligent::ShaderVariableD3D12Impl classes + +// +// * ShaderVariableManagerD3D12 keeps list of variables of specific types +// * Every ShaderVariableD3D12Impl references D3D12Resource from ShaderResourceLayoutD3D12 +// * ShaderVariableManagerD3D12 keeps pointer to ShaderResourceCacheD3D12 +// * ShaderVariableManagerD3D12 is used by ShaderD3D12Impl to manage static resources and by +// ShaderResourceBindingD3D12Impl to manage mutable and dynamic resources +// +// _____________________________ ________________________________________________________________________________ +// | | | | | | +// .----| ShaderVariableManagerD3D12 |---------------->| ShaderVariableD3D12Impl[0] | ShaderVariableD3D12Impl[1] | ... | +// | |_____________________________| |______________________________|_______________________________|_________________| +// | | \ | +// | | Ref Ref +// | | \ | +// | ___________V_______________ ______________________V_______________________V_____________________________ +// | | | unique_ptr | | | | | +// | | ShaderResourceLayoutD3D12 |--------------->| D3D12Resource[0] | D3D12Resource[1] | ... | D3D12Resource[s+m+d-1] | +// | |___________________________| |__________________|__________________|_____________|________________________| +// | | | +// | | | +// | | (RootTable, Offset) / (RootTable, Offset) +// | \ / +// | __________________________ ________V_______________________________________________________V_______ +// | | | | | +// '--->| ShaderResourceCacheD3D12 |---------------->| Resources | +// |__________________________| |________________________________________________________________________| +// +// Memory buffer is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block +// memory allocator is used. This ensures that all resources from different shader resource bindings reside in +// continuous memory. If allocation granularity == 1, raw allocator is used. + +#include <memory> + +#include "ShaderResourceLayoutD3D12.h" + +namespace Diligent +{ + +class ShaderVariableD3D12Impl; + +// sizeof(ShaderVariableManagerD3D12) == 40 (x64, msvc, Release) +class ShaderVariableManagerD3D12 +{ +public: + ShaderVariableManagerD3D12(IObject &Owner) : + m_Owner(Owner) + {} + ~ShaderVariableManagerD3D12(); + + void Initialize(const ShaderResourceLayoutD3D12& Layout, + IMemoryAllocator& Allocator, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12& ResourceCache); + void Destroy(IMemoryAllocator& Allocator); + + ShaderVariableD3D12Impl* GetVariable(const Char* Name); + ShaderVariableD3D12Impl* GetVariable(Uint32 Index); + + void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags); + + static size_t GetRequiredMemorySize(const ShaderResourceLayoutD3D12& Layout, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumVariables); + + Uint32 GetVariableCount()const { return m_NumVariables; } + +private: + friend ShaderVariableD3D12Impl; + + Uint32 GetVariableIndex(const ShaderVariableD3D12Impl& Variable); + + IObject& m_Owner; + // Variable mgr is owned by either Shader object (in which case m_pResourceLayout points to + // static resource layout owned by the same shader object), or by SRB object (in which case + // m_pResourceLayout points to corresponding layout in pipeline state). Since SRB keeps strong + // reference to PSO, the layout is guaranteed be alive while SRB is alive + const ShaderResourceLayoutD3D12* m_pResourceLayout= nullptr; + ShaderResourceCacheD3D12* m_pResourceCache = nullptr; + + // Memory is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block + // memory allocator is used. This ensures that all resources from different shader resource bindings reside in + // continuous memory. If allocation granularity == 1, raw allocator is used. + ShaderVariableD3D12Impl* m_pVariables = nullptr; + Uint32 m_NumVariables = 0; + +#ifdef _DEBUG + IMemoryAllocator* m_pDbgAllocator = nullptr; +#endif +}; + +// sizeof(ShaderVariableD3D12Impl) == 24 (x64) +class ShaderVariableD3D12Impl final : public IShaderVariable +{ +public: + ShaderVariableD3D12Impl(ShaderVariableManagerD3D12& ParentManager, + const ShaderResourceLayoutD3D12::D3D12Resource& Resource) : + m_ParentManager(ParentManager), + m_Resource(Resource) + {} + + ShaderVariableD3D12Impl (const ShaderVariableD3D12Impl&) = delete; + ShaderVariableD3D12Impl (ShaderVariableD3D12Impl&&) = delete; + ShaderVariableD3D12Impl& operator= (const ShaderVariableD3D12Impl&) = delete; + ShaderVariableD3D12Impl& operator= (ShaderVariableD3D12Impl&&) = delete; + + virtual IReferenceCounters* GetReferenceCounters()const override final + { + return m_ParentManager.m_Owner.GetReferenceCounters(); + } + + virtual Atomics::Long AddRef()override final + { + return m_ParentManager.m_Owner.AddRef(); + } + + virtual Atomics::Long Release()override final + { + return m_ParentManager.m_Owner.Release(); + } + + void QueryInterface(const INTERFACE_ID &IID, IObject **ppInterface)override final + { + if (ppInterface == nullptr) + return; + + *ppInterface = nullptr; + if (IID == IID_ShaderVariable || IID == IID_Unknown) + { + *ppInterface = this; + (*ppInterface)->AddRef(); + } + } + + virtual SHADER_VARIABLE_TYPE GetType()const override final + { + return m_Resource.Attribs.VariableType; + } + + virtual void Set(IDeviceObject *pObject)override final + { + VERIFY_EXPR(m_ParentManager.m_pResourceCache != nullptr); + m_Resource.BindResource(pObject, 0, *m_ParentManager.m_pResourceCache); + } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final + { + VERIFY_EXPR(m_ParentManager.m_pResourceCache != nullptr); + for (Uint32 Elem = 0; Elem < NumElements; ++Elem) + m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, *m_ParentManager.m_pResourceCache); + } + + virtual Uint32 GetArraySize()const override final + { + return m_Resource.Attribs.BindCount; + } + + virtual const Char* GetName()const override final + { + return m_Resource.Attribs.Name; + } + + virtual Uint32 GetIndex()const override final + { + return m_ParentManager.GetVariableIndex(*this); + } + + const ShaderResourceLayoutD3D12::D3D12Resource& GetResource()const + { + return m_Resource; + } + +private: + friend ShaderVariableManagerD3D12; + + ShaderVariableManagerD3D12& m_ParentManager; + const ShaderResourceLayoutD3D12::D3D12Resource& m_Resource; +}; + +} diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 55771a03..9e7774ea 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -32,6 +32,7 @@ #include "CommandContext.h" #include "EngineMemory.h" #include "StringTools.h" +#include "ShaderVariableD3D12.h" namespace Diligent { @@ -201,15 +202,16 @@ PipelineStateD3D12Impl :: PipelineStateD3D12Impl(IReferenceCounters* pRefCo if(PipelineDesc.SRBAllocationGranularity > 1) { - std::array<size_t, MaxShadersInPipeline> ShaderResLayoutDataSizes = {}; + std::array<size_t, MaxShadersInPipeline> ShaderVarMgrDataSizes = {}; for (Uint32 s = 0; s < m_NumShaders; ++s) { std::array<SHADER_VARIABLE_TYPE, 2> AllowedVarTypes = { SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC }; - ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D12::GetRequiredMemorySize(m_pShaderResourceLayouts[s], AllowedVarTypes.data(), static_cast<Uint32>(AllowedVarTypes.size())); + Uint32 NumVariablesUnused = 0; + ShaderVarMgrDataSizes[s] = ShaderVariableManagerD3D12::GetRequiredMemorySize(m_pShaderResourceLayouts[s], AllowedVarTypes.data(), static_cast<Uint32>(AllowedVarTypes.size()), NumVariablesUnused); } auto CacheMemorySize = m_RootSig.GetResourceCacheRequiredMemSize(); - m_SRBMemAllocator.Initialize(PipelineDesc.SRBAllocationGranularity, m_NumShaders, ShaderResLayoutDataSizes.data(), 1, &CacheMemorySize); + m_SRBMemAllocator.Initialize(PipelineDesc.SRBAllocationGranularity, m_NumShaders, ShaderVarMgrDataSizes.data(), 1, &CacheMemorySize); } // If pipeline state contains only static resources, create default SRB @@ -303,7 +305,7 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou bool CommitResources, bool TransitionResources)const { -#ifdef VERIFY_SHADER_BINDINGS +#ifdef DEVELOPMENT if (pShaderResourceBinding == nullptr && (m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_MUTABLE) != 0 || m_RootSig.GetTotalSrvCbvUavSlots(SHADER_VARIABLE_TYPE_DYNAMIC) != 0 || @@ -330,7 +332,7 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou return nullptr; } -#ifdef VERIFY_SHADER_BINDINGS +#ifdef DEVELOPMENT { auto* pRefPSO = pResBindingD3D12Impl->GetPipelineState(); if ( IsIncompatibleWith(pRefPSO) ) @@ -345,8 +347,8 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou if(!pResBindingD3D12Impl->StaticResourcesInitialized()) pResBindingD3D12Impl->InitializeStaticResources(this); -#ifdef VERIFY_SHADER_BINDINGS - pResBindingD3D12Impl->dbgVerifyResourceBindings(this); +#ifdef DEVELOPMENT + pResBindingD3D12Impl->dvpVerifyResourceBindings(this); #endif auto& ResourceCache = pResBindingD3D12Impl->GetResourceCache(); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp index f03d194d..1a5e03dc 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp @@ -30,41 +30,42 @@ #include "DataBlobImpl.h" #include "D3DShaderResourceLoader.h" -using namespace Diligent; - namespace Diligent { - ShaderD3D12Impl::ShaderD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pRenderDeviceD3D12, const ShaderCreationAttribs& ShaderCreationAttribs) : TShaderBase(pRefCounters, pRenderDeviceD3D12, ShaderCreationAttribs.Desc), ShaderD3DBase(ShaderCreationAttribs), m_StaticResLayout(*this, GetRawAllocator()), - m_StaticResCache(ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) + m_StaticResCache(ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources), + m_StaticVarsMgr(*this) { // Load shader resources - auto &Allocator = GetRawAllocator(); - auto *pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", sizeof(ShaderResourcesD3D12)); - auto *pResources = new (pRawMem) ShaderResourcesD3D12(m_pShaderByteCode, m_Desc); + auto& Allocator = GetRawAllocator(); + auto* pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", sizeof(ShaderResourcesD3D12)); + auto* pResources = new (pRawMem) ShaderResourcesD3D12(m_pShaderByteCode, m_Desc); m_pShaderResources.reset(pResources, STDDeleterRawMem<ShaderResourcesD3D12>(Allocator)); // Clone only static resources that will be set directly in the shader // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Special-Resource-Layout-for-Managing-Static-Shader-Resources SHADER_VARIABLE_TYPE VarTypes[] = {SHADER_VARIABLE_TYPE_STATIC}; m_StaticResLayout.Initialize(pRenderDeviceD3D12->GetD3D12Device(), m_pShaderResources, GetRawAllocator(), VarTypes, _countof(VarTypes), &m_StaticResCache, nullptr); + m_StaticVarsMgr.Initialize(m_StaticResLayout, GetRawAllocator(), nullptr, 0, m_StaticResCache); } ShaderD3D12Impl::~ShaderD3D12Impl() { + m_StaticVarsMgr.Destroy(GetRawAllocator()); } +IMPLEMENT_QUERY_INTERFACE( ShaderD3D12Impl, IID_ShaderD3D12, TShaderBase ) -#ifdef VERIFY_SHADER_BINDINGS -void ShaderD3D12Impl::DbgVerifyStaticResourceBindings() +#ifdef DEVELOPMENT +void ShaderD3D12Impl::DvpVerifyStaticResourceBindings() { - m_StaticResLayout.dbgVerifyBindings(m_StaticResCache); + m_StaticResLayout.dvpVerifyBindings(m_StaticResCache); } #endif diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 8c70ae89..a54989d2 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -35,7 +35,7 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter bool IsPSOInternal) : TBase( pRefCounters, pPSO, IsPSOInternal ), m_ShaderResourceCache(ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources), - m_NumShaders(pPSO->GetNumShaders()) + m_NumShaders(static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaders())) { auto* ppShaders = pPSO->GetShaders(); @@ -43,8 +43,8 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter auto& ResCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, ResCacheDataAllocator); - auto* pResLayoutRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12", m_NumShaders * sizeof(ShaderResourceLayoutD3D12)); - m_pResourceLayouts = reinterpret_cast<ShaderResourceLayoutD3D12*>(pResLayoutRawMem); + auto *pVarMgrsRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerD3D12", m_NumShaders * sizeof(ShaderVariableManagerD3D12)); + m_pShaderVarMgrs = reinterpret_cast<ShaderVariableManagerD3D12*>(pVarMgrsRawMem); for (Uint32 s = 0; s < m_NumShaders; ++s) { @@ -52,12 +52,15 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter auto ShaderType = pShader->GetDesc().ShaderType; auto ShaderInd = GetShaderTypeIndex(ShaderType); - auto& ShaderResLayoutDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + // Create shader variable manager in place + new (m_pShaderVarMgrs + s) ShaderVariableManagerD3D12(*this); + + auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object std::array<SHADER_VARIABLE_TYPE, 2> AllowedVarTypes = { SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC }; const auto& SrcLayout = pPSO->GetShaderResLayout(s); - new (m_pResourceLayouts + s) ShaderResourceLayoutD3D12(*this, SrcLayout, ShaderResLayoutDataAllocator, AllowedVarTypes.data(), static_cast<Uint32>(AllowedVarTypes.size()), m_ShaderResourceCache); + m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, AllowedVarTypes.data(), static_cast<Uint32>(AllowedVarTypes.size()), m_ShaderResourceCache); m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s); } @@ -65,22 +68,30 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter ShaderResourceBindingD3D12Impl::~ShaderResourceBindingD3D12Impl() { - for(Uint32 l = 0; l < m_NumShaders; ++l) - m_pResourceLayouts[l].~ShaderResourceLayoutD3D12(); + auto* pPSO = ValidatedCast<PipelineStateD3D12Impl>(m_pPSO); + for(Uint32 s = 0; s < m_NumShaders; ++s) + { + auto &VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + m_pShaderVarMgrs[s].Destroy(VarDataAllocator); + m_pShaderVarMgrs[s].~ShaderVariableManagerD3D12(); + } - GetRawAllocator().Free(m_pResourceLayouts); + GetRawAllocator().Free(m_pShaderVarMgrs); } IMPLEMENT_QUERY_INTERFACE( ShaderResourceBindingD3D12Impl, IID_ShaderResourceBindingD3D12, TBase ) void ShaderResourceBindingD3D12Impl::BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) { - for (Uint32 s = 0; s < m_NumShaders; ++s ) + for (auto ShaderInd = 0; ShaderInd <= CSInd; ++ShaderInd ) { - const auto& ShaderRes = m_pResourceLayouts[s].GetShaderResources(); - if (ShaderFlags & ShaderRes.GetShaderType()) + if (ShaderFlags & GetShaderTypeFromIndex(ShaderInd)) { - m_pResourceLayouts[s].BindResources(pResMapping, Flags, &m_ShaderResourceCache); + auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd]; + if(ResLayoutInd >= 0) + { + m_pShaderVarMgrs[ResLayoutInd].BindResources(pResMapping, Flags); + } } } } @@ -94,7 +105,7 @@ IShaderVariable *ShaderResourceBindingD3D12Impl::GetVariable(SHADER_TYPE ShaderT LOG_ERROR("Failed to find shader variable \"", Name,"\" in shader resource binding: shader type ", GetShaderTypeLiteralName(ShaderType), " is not initialized"); return nullptr; } - return m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Name); + return m_pShaderVarMgrs[ResLayoutInd].GetVariable(Name); } Uint32 ShaderResourceBindingD3D12Impl::GetVariableCount(SHADER_TYPE ShaderType) const @@ -107,7 +118,7 @@ Uint32 ShaderResourceBindingD3D12Impl::GetVariableCount(SHADER_TYPE ShaderType) return 0; } - return m_pResourceLayouts[ResLayoutInd].GetVariableCount(); + return m_pShaderVarMgrs[ResLayoutInd].GetVariableCount(); } IShaderVariable* ShaderResourceBindingD3D12Impl::GetVariable(SHADER_TYPE ShaderType, Uint32 Index) @@ -120,12 +131,12 @@ IShaderVariable* ShaderResourceBindingD3D12Impl::GetVariable(SHADER_TYPE ShaderT return nullptr; } - return m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Index); + return m_pShaderVarMgrs[ResLayoutInd].GetVariable(Index); } -#ifdef VERIFY_SHADER_BINDINGS -void ShaderResourceBindingD3D12Impl::dbgVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO) +#ifdef DEVELOPMENT +void ShaderResourceBindingD3D12Impl::dvpVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO) { auto* pRefPSO = ValidatedCast<PipelineStateD3D12Impl>(GetPipelineState()); if (pPSO->IsIncompatibleWith(pRefPSO)) @@ -137,7 +148,7 @@ void ShaderResourceBindingD3D12Impl::dbgVerifyResourceBindings(const PipelineSta { // Use reference layout from pipeline state that contains all shader resource types const auto& ShaderResLayout = pRefPSO->GetShaderResLayout(l); - ShaderResLayout.dbgVerifyBindings(m_ShaderResourceCache); + ShaderResLayout.dvpVerifyBindings(m_ShaderResourceCache); } } #endif @@ -154,12 +165,13 @@ void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const PipelineSta for (Uint32 s = 0; s < NumShaders; ++s) { auto* pShader = ValidatedCast<ShaderD3D12Impl>( ppShaders[s] ); -#ifdef VERIFY_SHADER_BINDINGS - pShader->DbgVerifyStaticResourceBindings(); +#ifdef DEVELOPMENT + pShader->DvpVerifyStaticResourceBindings(); #endif const auto& ShaderResLayout = pPSO->GetShaderResLayout(s); auto& StaticResLayout = pShader->GetStaticResLayout(); - StaticResLayout.CopyStaticResourceDesriptorHandles(ShaderResLayout, m_ShaderResourceCache); + auto& StaticResCache = pShader->GetStaticResCache(); + StaticResLayout.CopyStaticResourceDesriptorHandles(StaticResCache, ShaderResLayout, m_ShaderResourceCache); } m_bStaticResourcesInitialized = true; diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index ddba7731..59c8c221 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -50,17 +50,8 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& Owner, ShaderResourceLayoutD3D12::~ShaderResourceLayoutD3D12() { - // For some reason MS compiler generates this false warning: - // warning C4189: 'CbvSrvUav': local variable is initialized but not referenced -#pragma warning(push) -#pragma warning(disable : 4189) - auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get()); -#pragma warning(pop) - for(Uint32 r=0; r < GetTotalSrvCbvUavCount(); ++r) - CbvSrvUav[r].~SRV_CBV_UAV(); - - for(Uint32 s=0; s < GetTotalSamplerCount(); ++s) - m_Samplers[s].~Sampler(); + for(Uint32 r=0; r < GetTotalResourceCount(); ++r) + GetResource(r).~D3D12Resource(); } D3D12_DESCRIPTOR_RANGE_TYPE GetDescriptorRangeType(CachedResourceType ResType) @@ -112,129 +103,33 @@ void ShaderResourceLayoutD3D12::AllocateMemory(IMemoryAllocator& VERIFY_EXPR(GetCbvSrvUavCount(VarType) == CbvSrvUavCount[VarType]); VERIFY_EXPR(GetSamplerCount (VarType) == SamplerCount [VarType]); } + for(Uint32 VarType=0; VarType <= SHADER_VARIABLE_TYPE_NUM_TYPES; ++VarType) + { + m_SamplersOffsets[VarType] += m_CbvSrvUavOffsets[SHADER_VARIABLE_TYPE_NUM_TYPES]; + } Uint32 TotalSrvCbvUav = GetTotalSrvCbvUavCount(); Uint32 TotalSamplers = GetTotalSamplerCount(); - size_t MemSize = TotalSrvCbvUav * sizeof(SRV_CBV_UAV) + TotalSamplers * sizeof(Sampler); + size_t MemSize = (TotalSrvCbvUav + TotalSamplers) * sizeof(D3D12Resource); if(MemSize == 0) return; auto *pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader resource layout resources", MemSize); m_ResourceBuffer.reset(pRawMem); - if(TotalSamplers) - m_Samplers = reinterpret_cast<Sampler*>(reinterpret_cast<SRV_CBV_UAV*>(pRawMem) + TotalSrvCbvUav); -} - - -size_t ShaderResourceLayoutD3D12::GetRequiredMemorySize(const ShaderResourceLayoutD3D12& SrcLayout, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes) -{ - - Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - - size_t MemSize = 0; - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) - { - if( !IsAllowedType(VarType, AllowedTypeBits)) - continue; - - MemSize += SrcLayout.GetCbvSrvUavCount(VarType) * sizeof(SRV_CBV_UAV); - MemSize += SrcLayout.GetSamplerCount(VarType) * sizeof(Sampler); - } - return MemSize; -} - - -// Clones layout from the reference layout maintained by the pipeline state -// Root indices and descriptor table offsets must be correct -// Resource cache is not initialized. -// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object -ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& Owner, - const ShaderResourceLayoutD3D12& SrcLayout, - IMemoryAllocator& ResourceLayoutDataAllocator, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12& ResourceCache) : - ShaderResourceLayoutD3D12(Owner, ResourceLayoutDataAllocator) -{ - m_pd3d12Device = SrcLayout.m_pd3d12Device; - m_pResources = SrcLayout.m_pResources; - m_pResourceCache = &ResourceCache; - - Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - - std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> CbvSrvUavCount = {}; - std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> SamplerCount = {}; - - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) - { - if( !IsAllowedType(VarType, AllowedTypeBits)) - continue; - - CbvSrvUavCount[VarType] = SrcLayout.GetCbvSrvUavCount(VarType); - SamplerCount [VarType] = SrcLayout.GetSamplerCount(VarType); - } - - AllocateMemory(ResourceLayoutDataAllocator, CbvSrvUavCount, SamplerCount); - - std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> CurrCbvSrvUav = {}; - std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> CurrSampler = {}; - - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) - { - if( !IsAllowedType(VarType, AllowedTypeBits)) - continue; - - Uint32 NumSrcCbvSrvUav = SrcLayout.GetCbvSrvUavCount(VarType); - VERIFY_EXPR(NumSrcCbvSrvUav == GetCbvSrvUavCount(VarType)); - for( Uint32 r=0; r < NumSrcCbvSrvUav; ++r ) - { - const auto &SrcRes = SrcLayout.GetSrvCbvUav(VarType, r); - Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId; - if (SrcRes.IsValidSampler()) - { - const auto &SrcSamplerAttribs = SrcLayout.GetSampler(VarType, SrcRes.GetSamplerId()); - VERIFY(!SrcSamplerAttribs.Attribs.IsStaticSampler(), "Only non-static samplers can be assigned space in shader cache"); - VERIFY(SrcSamplerAttribs.Attribs.VariableType == SrcRes.Attribs.VariableType, "Inconsistent texture and sampler variable types" ); - VERIFY(SrcSamplerAttribs.IsValidRootIndex(), "Root index must be valid"); - VERIFY(SrcSamplerAttribs.IsValidOffset(), "Offset must be valid"); - VERIFY_EXPR(SrcSamplerAttribs.Attribs.BindCount == SrcRes.Attribs.BindCount || SrcSamplerAttribs.Attribs.BindCount == 1); - - SamplerId = CurrSampler[VarType]; - VERIFY(SamplerId <= SRV_CBV_UAV::MaxSamplerId, "SamplerId exceeds maximum allowed value (", SRV_CBV_UAV::MaxSamplerId, ")"); - VERIFY_EXPR(SamplerId == SrcRes.GetSamplerId()); - ::new (&GetSampler(VarType, CurrSampler[VarType]++)) Sampler( *this, SrcSamplerAttribs ); - } - - VERIFY(SrcRes.IsValidRootIndex(), "Root index must be valid"); - VERIFY(SrcRes.IsValidOffset(), "Offset must be valid"); - ::new (&GetSrvCbvUav(VarType, CurrCbvSrvUav[VarType]++)) SRV_CBV_UAV( *this, SrcRes, SamplerId ); - } - } - -#ifdef _DEBUG - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) - { - VERIFY_EXPR( CurrCbvSrvUav[VarType] == CbvSrvUavCount[VarType] ); - VERIFY_EXPR( CurrSampler[VarType] == SamplerCount[VarType] ); - } -#endif } // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Shader-Resource-Layouts-and-Root-Signature-in-a-Pipeline-State-Object // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Resource-Layouts-in-a-Pipeline-State -void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device, - const std::shared_ptr<const ShaderResourcesD3D12>& pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - RootSignature* pRootSig) +void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device, + std::shared_ptr<const ShaderResourcesD3D12> pSrcResources, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + RootSignature* pRootSig) { - m_pResources = pSrcResources; - m_pResourceCache = pResourceCache; + m_pResources = std::move(pSrcResources); m_pd3d12Device = pd3d12Device; VERIFY_EXPR( (pResourceCache != nullptr) ^ (pRootSig != nullptr) ); @@ -260,7 +155,7 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* ++CbvSrvUavCount[VarType]; if(TexSRV.IsValidSampler()) { - auto SamplerId = TexSRV.GetSamplerId(); + auto SamplerId = TexSRV.SamplerId; const auto &SamplerAttribs = m_pResources->GetSampler(SamplerId); VERIFY(SamplerAttribs.VariableType == VarType, "Texture and sampler variable types are not conistent"); if(!SamplerAttribs.IsStaticSampler()) @@ -292,15 +187,15 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> CurrSampler = {}; Uint32 StaticResCacheTblSizes[4] = {0, 0, 0, 0}; - auto AddResource = [&](const D3DShaderResourceAttribs &Attribs, CachedResourceType ResType, Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId) + auto AddResource = [&](const D3DShaderResourceAttribs &Attribs, CachedResourceType ResType, Uint32 SamplerId = D3D12Resource::InvalidSamplerId) { - Uint32 RootIndex = SRV_CBV_UAV::InvalidRootIndex; - Uint32 Offset = SRV_CBV_UAV::InvalidOffset; + Uint32 RootIndex = D3D12Resource::InvalidRootIndex; + Uint32 Offset = D3D12Resource::InvalidOffset; D3D12_DESCRIPTOR_RANGE_TYPE DescriptorRangeType = GetDescriptorRangeType(ResType); if (pRootSig) { pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), Attribs, DescriptorRangeType, RootIndex, Offset ); - VERIFY(RootIndex <= SRV_CBV_UAV::MaxRootIndex, "Root index excceeds allowed limit"); + VERIFY(RootIndex <= D3D12Resource::MaxRootIndex, "Root index excceeds allowed limit"); } else { @@ -313,22 +208,21 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Special-Resource-Layout-for-Managing-Static-Shader-Resources - VERIFY_EXPR(m_pResourceCache != nullptr); + VERIFY_EXPR(pResourceCache != nullptr); RootIndex = DescriptorRangeType; Offset = Attribs.BindPoint; // Resources in the static resource cache are indexed by the bind point StaticResCacheTblSizes[RootIndex] = std::max(StaticResCacheTblSizes[RootIndex], Offset + Attribs.BindCount); } - VERIFY(RootIndex != SRV_CBV_UAV::InvalidRootIndex, "Root index must be valid"); - VERIFY(Offset != SRV_CBV_UAV::InvalidOffset, "Offset must be valid"); + VERIFY(RootIndex != D3D12Resource::InvalidRootIndex, "Root index must be valid"); + VERIFY(Offset != D3D12Resource::InvalidOffset, "Offset must be valid"); // Static samplers are never copied, and SamplerId == InvalidSamplerId - ::new (&GetSrvCbvUav(Attribs.VariableType, CurrCbvSrvUav[Attribs.VariableType]++)) SRV_CBV_UAV( *this, Attribs, ResType, RootIndex, Offset, SamplerId); + ::new (&GetSrvCbvUav(Attribs.VariableType, CurrCbvSrvUav[Attribs.VariableType]++)) D3D12Resource( *this, Attribs, ResType, RootIndex, Offset, SamplerId); }; - - + m_pResources->ProcessResources( AllowedVarTypes, NumAllowedTypes, @@ -342,10 +236,10 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* auto VarType = TexSRV.VariableType; VERIFY_EXPR(IsAllowedType(VarType, AllowedTypeBits) ); - Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId; + Uint32 SamplerId = D3D12Resource::InvalidSamplerId; if(TexSRV.IsValidSampler()) { - const auto &SrcSamplerAttribs = m_pResources->GetSampler(TexSRV.GetSamplerId()); + const auto &SrcSamplerAttribs = m_pResources->GetSampler(TexSRV.SamplerId); VERIFY(SrcSamplerAttribs.VariableType == VarType, "Inconsistent texture and sampler variable types" ); if (SrcSamplerAttribs.IsStaticSampler()) @@ -357,8 +251,8 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* } else { - Uint32 SamplerRootIndex = Sampler::InvalidRootIndex; - Uint32 SamplerOffset = Sampler::InvalidOffset; + Uint32 SamplerRootIndex = D3D12Resource::InvalidRootIndex; + Uint32 SamplerOffset = D3D12Resource::InvalidOffset; if (pRootSig) { pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), SrcSamplerAttribs, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, SamplerRootIndex, SamplerOffset ); @@ -367,7 +261,7 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* { // If root signature is not provided, we are initializing resource cache to store // static shader resources. - VERIFY_EXPR(m_pResourceCache != nullptr); + VERIFY_EXPR(pResourceCache != nullptr); // We use the following artifial root signature: // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV (0) @@ -380,12 +274,12 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* // Resources in the static resource cache are indexed by the bind point StaticResCacheTblSizes[SamplerRootIndex] = std::max(StaticResCacheTblSizes[SamplerRootIndex], SamplerOffset + SrcSamplerAttribs.BindCount); } - VERIFY(SamplerRootIndex != Sampler::InvalidRootIndex, "Sampler root index must be valid"); - VERIFY(SamplerOffset != Sampler::InvalidOffset, "Sampler offset must be valid"); + VERIFY(SamplerRootIndex != D3D12Resource::InvalidRootIndex, "Sampler root index must be valid"); + VERIFY(SamplerOffset != D3D12Resource::InvalidOffset, "Sampler offset must be valid"); SamplerId = CurrSampler[VarType]; - VERIFY(SamplerId <= SRV_CBV_UAV::MaxSamplerId, "Sampler index excceeds allowed limit"); - ::new (&GetSampler(VarType, CurrSampler[VarType]++)) Sampler( *this, SrcSamplerAttribs, SamplerRootIndex, SamplerOffset ); + VERIFY(SamplerId <= D3D12Resource::MaxSamplerId, "Sampler index excceeds allowed limit"); + ::new (&GetSampler(VarType, CurrSampler[VarType]++)) D3D12Resource( *this, SrcSamplerAttribs, CachedResourceType::Sampler, SamplerRootIndex, SamplerOffset, D3D12Resource::InvalidSamplerId); } } AddResource(TexSRV, CachedResourceType::TexSRV, SamplerId); @@ -415,38 +309,23 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* } #endif - if(m_pResourceCache) + if(pResourceCache) { // Initialize resource cache to store static resources // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-the-Cache-for-Static-Shader-Resources // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Objects VERIFY_EXPR(pRootSig == nullptr); - m_pResourceCache->Initialize(GetRawAllocator(), _countof(StaticResCacheTblSizes), StaticResCacheTblSizes); + pResourceCache->Initialize(GetRawAllocator(), _countof(StaticResCacheTblSizes), StaticResCacheTblSizes); #ifdef _DEBUG - m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SRV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_UAV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_UAV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_CBV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_CBV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SRV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_UAV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_UAV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_CBV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_CBV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); #endif } - - InitVariablesHashMap(); } -void ShaderResourceLayoutD3D12::InitVariablesHashMap() -{ -#if USE_VARIABLE_HASH_MAP - Uint32 TotalResources = GetTotalSrvCbvUavCount(); - for(Uint32 r=0; r < TotalResources; ++r) - { - auto &Res = GetSrvCbvUav(r); - /* HashMapStringKey will make a copy of the string*/ - m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(Res.Name, true), &Res ) ); - } -#endif -} - #define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, VarName, ShaderName, ...)\ { \ @@ -457,10 +336,10 @@ void ShaderResourceLayoutD3D12::InitVariablesHashMap() -void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheCB(IDeviceObject* pBuffer, - ShaderResourceCacheD3D12::Resource& DstRes, - Uint32 ArrayInd, - D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) +void ShaderResourceLayoutD3D12::D3D12Resource::CacheCB(IDeviceObject* pBuffer, + ShaderResourceCacheD3D12::Resource& DstRes, + Uint32 ArrayInd, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)const { // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Binding-Objects-to-Shader-Variables @@ -476,7 +355,7 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheCB(IDeviceObject* if(DstRes.pObject != pBuffD3D12) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.VariableType); - LOG_ERROR_MESSAGE( "Non-null constant buffer is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayInd), "\" in shader \"", m_ParentResLayout.GetShaderName(), "\". Attempring to bind another constant buffer is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null constant buffer is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayInd), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempring to bind another constant buffer is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); } // Do not update resource if one is already bound unless it is dynamic. This may be @@ -494,7 +373,7 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheCB(IDeviceObject* // the descriptor is copied by the RootSignature when resources are committed VERIFY(DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); - ID3D12Device *pd3d12Device = m_ParentResLayout.m_pd3d12Device; + ID3D12Device *pd3d12Device = ParentResLayout.m_pd3d12Device; pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } @@ -502,12 +381,12 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheCB(IDeviceObject* } else { - LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, Attribs.GetPrintName(ArrayInd), m_ParentResLayout.GetShaderName(), "Buffer was not created with BIND_UNIFORM_BUFFER flag.") + LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, Attribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "Buffer was not created with BIND_UNIFORM_BUFFER flag.") } } else { - LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, Attribs.GetPrintName(ArrayInd), m_ParentResLayout.GetShaderName(), "Incorrect resource type: buffer is expected.") + LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, Attribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "Incorrect resource type: buffer is expected.") } } @@ -536,26 +415,26 @@ const INTERFACE_ID& ResourceViewTraits<IBufferViewD3D12>::IID = IID_BufferViewD3 template<typename TResourceViewType, ///< ResType of the view (ITextureViewD3D12 or IBufferViewD3D12) typename TViewTypeEnum, ///< ResType of the expected view type enum (TEXTURE_VIEW_TYPE or BUFFER_VIEW_TYPE) typename TBindSamplerProcType> ///< ResType of the procedure to set sampler -void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheResourceView(IDeviceObject* pView, - ShaderResourceCacheD3D12::Resource& DstRes, - Uint32 ArrayIndex, - D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, - TViewTypeEnum dbgExpectedViewType, - TBindSamplerProcType BindSamplerProc) +void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject* pView, + ShaderResourceCacheD3D12::Resource& DstRes, + Uint32 ArrayIndex, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, + TViewTypeEnum dbgExpectedViewType, + TBindSamplerProcType BindSamplerProc)const { // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type RefCntAutoPtr<TResourceViewType> pViewD3D12(pView, ResourceViewTraits<TResourceViewType>::IID); if( pViewD3D12 ) { -#ifdef VERIFY_SHADER_BINDINGS +#ifdef DEVELOPMENT const auto& ViewDesc = pViewD3D12->GetDesc(); auto ViewType = ViewDesc.ViewType; if( ViewType != dbgExpectedViewType ) { const auto *ExpectedViewTypeName = GetViewTypeLiteralName( dbgExpectedViewType ); const auto *ActualViewTypeName = GetViewTypeLiteralName( ViewType ); - LOG_RESOURCE_BINDING_ERROR(ResourceViewTraits<TResourceViewType>::Name, pViewD3D12, Attribs.GetPrintName(ArrayIndex), m_ParentResLayout.GetShaderName(), + LOG_RESOURCE_BINDING_ERROR(ResourceViewTraits<TResourceViewType>::Name, pViewD3D12, Attribs.GetPrintName(ArrayIndex), ParentResLayout.GetShaderName(), "Incorrect view type: ", ExpectedViewTypeName, " is expected, ", ActualViewTypeName, " provided." ); return; } @@ -565,7 +444,7 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheResourceView(IDeviceObject* if(DstRes.pObject != pViewD3D12) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.VariableType); - LOG_ERROR_MESSAGE( "Non-null resource is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", m_ParentResLayout.GetShaderName(), "\". Attempting to bind another resource or null is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null resource is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempting to bind another resource or null is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); } // Do not update resource if one is already bound unless it is dynamic. This may be @@ -583,7 +462,7 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheResourceView(IDeviceObject* // the descriptor is copied by the RootSignature when resources are committed VERIFY(DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); - ID3D12Device *pd3d12Device = m_ParentResLayout.m_pd3d12Device; + ID3D12Device *pd3d12Device = ParentResLayout.m_pd3d12Device; pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } DstRes.pObject = pViewD3D12; @@ -592,41 +471,18 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::CacheResourceView(IDeviceObject* } else { - LOG_RESOURCE_BINDING_ERROR("resource", pView, Attribs.GetPrintName(ArrayIndex), m_ParentResLayout.GetShaderName(), "Incorect resource type: ", ResourceViewTraits<TResourceViewType>::Name, " is expected.") + LOG_RESOURCE_BINDING_ERROR("resource", pView, Attribs.GetPrintName(ArrayIndex), ParentResLayout.GetShaderName(), "Incorect resource type: ", ResourceViewTraits<TResourceViewType>::Name, " is expected.") } } -void ShaderResourceLayoutD3D12::Sampler::CacheSampler(ITextureViewD3D12* pTexViewD3D12, - Uint32 ArrayIndex, - D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) +void ShaderResourceLayoutD3D12::D3D12Resource::CacheSampler(ITextureViewD3D12* pTexViewD3D12, + ShaderResourceCacheD3D12::Resource& DstSam, + Uint32 ArrayIndex, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)const { - auto *pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); VERIFY(Attribs.IsValidBindPoint(), "Invalid bind point"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); - auto &DstSam = pResourceCache->GetRootTable(RootIndex).GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_ParentResLayout.m_pResources->GetShaderType()); - -#ifdef _DEBUG - { - if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) - { - VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space"); - } - else if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources) - { - if(Attribs.VariableType == SHADER_VARIABLE_TYPE_DYNAMIC) - VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Dynamic resources of a shader resource binding should be assigned shader visible descriptor space at every draw call"); - else - VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0 || pTexViewD3D12 == nullptr, "Non-dynamics resources of a shader resource binding must be assigned shader visible descriptor space"); - } - else - { - UNEXPECTED("Unknown content type"); - } - } -#endif - if( pTexViewD3D12 ) { auto pSampler = pTexViewD3D12->GetSampler(); @@ -637,7 +493,7 @@ void ShaderResourceLayoutD3D12::Sampler::CacheSampler(ITextureViewD3D12* if(DstSam.pObject != pSampler) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.VariableType); - LOG_ERROR_MESSAGE( "Non-null sampler is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", m_ParentResLayout.GetShaderName(), "\". Attempting to bind another sampler is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null sampler is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempting to bind another sampler is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); } // Do not update resource if one is already bound unless it is dynamic. This may be @@ -657,7 +513,7 @@ void ShaderResourceLayoutD3D12::Sampler::CacheSampler(ITextureViewD3D12* // the descriptor is copied by the RootSignature when resources are committed VERIFY(DstSam.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); - ID3D12Device *pd3d12Device = m_ParentResLayout.m_pd3d12Device; + ID3D12Device *pd3d12Device = ParentResLayout.m_pd3d12Device; pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstSam.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } @@ -674,41 +530,38 @@ void ShaderResourceLayoutD3D12::Sampler::CacheSampler(ITextureViewD3D12* } } -const ShaderResourceLayoutD3D12::Sampler& ShaderResourceLayoutD3D12::GetAssignedSampler(const SRV_CBV_UAV& TexSrv)const -{ - return const_cast<ShaderResourceLayoutD3D12*>(this)->GetAssignedSampler(TexSrv); -} - -ShaderResourceLayoutD3D12::Sampler& ShaderResourceLayoutD3D12::GetAssignedSampler(const SRV_CBV_UAV& TexSrv) +const ShaderResourceLayoutD3D12::D3D12Resource& ShaderResourceLayoutD3D12::GetAssignedSampler(const D3D12Resource& TexSrv)const { VERIFY(TexSrv.GetResType() == CachedResourceType::TexSRV, "Unexpected resource type: texture SRV is expected"); VERIFY(TexSrv.IsValidSampler(), "Texture SRV has no associated sampler"); - auto &SamInfo = GetSampler(TexSrv.Attribs.VariableType, TexSrv.GetSamplerId()); + auto &SamInfo = GetSampler(TexSrv.Attribs.VariableType, TexSrv.SamplerId); VERIFY(SamInfo.Attribs.VariableType == TexSrv.Attribs.VariableType, "Inconsistent texture and sampler variable types"); VERIFY(StrCmpSuff(SamInfo.Attribs.Name, TexSrv.Attribs.Name, D3DSamplerSuffix), "Sampler name \"", SamInfo.Attribs.Name, "\" does not match texture name \"", TexSrv.Attribs.Name, '\"'); return SamInfo; } +ShaderResourceLayoutD3D12::D3D12Resource& ShaderResourceLayoutD3D12::GetAssignedSampler(const D3D12Resource& TexSrv) +{ + return const_cast<D3D12Resource&>(const_cast<const ShaderResourceLayoutD3D12*>(this)->GetAssignedSampler(TexSrv)); +} + -void ShaderResourceLayoutD3D12::SRV_CBV_UAV::BindResource(IDeviceObject* pObj, - Uint32 ArrayIndex, - const ShaderResourceLayoutD3D12* dbgResLayout) +void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* pObj, + Uint32 ArrayIndex, + ShaderResourceCacheD3D12& ResourceCache)const { - auto *pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); - VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); - auto &DstRes = pResourceCache->GetRootTable(GetRootIndex()).GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_ParentResLayout.m_pResources->GetShaderType()); - auto ShdrVisibleHeapCPUDescriptorHandle = pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(GetRootIndex(), OffsetFromTableStart+ArrayIndex); + auto &DstRes = ResourceCache.GetRootTable(RootIndex).GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, ParentResLayout.m_pResources->GetShaderType()); + auto ShdrVisibleHeapCPUDescriptorHandle = ResourceCache.GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(RootIndex, OffsetFromTableStart+ArrayIndex); #ifdef _DEBUG { - if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) + if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) { VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space"); } - else if (pResourceCache->DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources) + else if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources) { if (GetResType() == CachedResourceType::CBV) { @@ -742,12 +595,32 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::BindResource(IDeviceObject* { if(IsValidSampler()) { - auto &Sam = m_ParentResLayout.GetAssignedSampler(*this); + auto &Sam = ParentResLayout.GetAssignedSampler(*this); VERIFY( !Sam.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" ); VERIFY_EXPR(Attribs.BindCount == Sam.Attribs.BindCount || Sam.Attribs.BindCount == 1); auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0; - auto ShdrVisibleSamplerHeapCPUDescriptorHandle = pResourceCache->GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER>(Sam.RootIndex, Sam.OffsetFromTableStart + SamplerArrInd); - Sam.CacheSampler(pTexView, SamplerArrInd, ShdrVisibleSamplerHeapCPUDescriptorHandle); + auto ShdrVisibleSamplerHeapCPUDescriptorHandle = ResourceCache.GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER>(Sam.RootIndex, Sam.OffsetFromTableStart + SamplerArrInd); + auto& DstSam = ResourceCache.GetRootTable(Sam.RootIndex).GetResource(Sam.OffsetFromTableStart + SamplerArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, ParentResLayout.m_pResources->GetShaderType()); +#ifdef _DEBUG + { + if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) + { + VERIFY(ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space"); + } + else if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources) + { + if(Attribs.VariableType == SHADER_VARIABLE_TYPE_DYNAMIC) + VERIFY(ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr == 0, "Dynamic resources of a shader resource binding should be assigned shader visible descriptor space at every draw call"); + else + VERIFY(ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr != 0 || pTexView == nullptr, "Non-dynamics resources of a shader resource binding must be assigned shader visible descriptor space"); + } + else + { + UNEXPECTED("Unknown content type"); + } + } +#endif + Sam.CacheSampler(pTexView, DstSam, SamplerArrInd, ShdrVisibleSamplerHeapCPUDescriptorHandle); } }); break; @@ -771,33 +644,31 @@ void ShaderResourceLayoutD3D12::SRV_CBV_UAV::BindResource(IDeviceObject* { if (DstRes.pObject && Attribs.VariableType != SHADER_VARIABLE_TYPE_DYNAMIC) { - LOG_ERROR_MESSAGE( "Shader variable \"", Attribs.Name, "\" in shader \"", m_ParentResLayout.GetShaderName(), "\" is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic if you need to bind another resource." ); + LOG_ERROR_MESSAGE( "Shader variable \"", Attribs.Name, "\" in shader \"", ParentResLayout.GetShaderName(), "\" is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic if you need to bind another resource." ); } DstRes = ShaderResourceCacheD3D12::Resource(); if(IsValidSampler()) { - auto &Sam = m_ParentResLayout.GetAssignedSampler(*this); + auto &Sam = ParentResLayout.GetAssignedSampler(*this); D3D12_CPU_DESCRIPTOR_HANDLE NullHandle = {0}; auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0; - Sam.CacheSampler(nullptr, SamplerArrInd, NullHandle); + auto& DstSam = ResourceCache.GetRootTable(Sam.RootIndex).GetResource(Sam.OffsetFromTableStart + SamplerArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, ParentResLayout.m_pResources->GetShaderType()); + Sam.CacheSampler(nullptr, DstSam, SamplerArrInd, NullHandle); } } } -bool ShaderResourceLayoutD3D12::SRV_CBV_UAV::IsBound(Uint32 ArrayIndex)const +bool ShaderResourceLayoutD3D12::D3D12Resource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheD3D12& ResourceCache)const { - auto *pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); - auto RootIndex = GetRootIndex(); - if( RootIndex < pResourceCache->GetNumRootTables() ) + if( RootIndex < ResourceCache.GetNumRootTables() ) { - auto &RootTable = pResourceCache->GetRootTable(RootIndex); + auto& RootTable = ResourceCache.GetRootTable(RootIndex); if(OffsetFromTableStart + ArrayIndex < RootTable.GetSize()) { - auto &CachedRes = RootTable.GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_ParentResLayout.m_pResources->GetShaderType()); + auto& CachedRes = RootTable.GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, ParentResLayout.m_pResources->GetShaderType()); if( CachedRes.pObject != nullptr ) { VERIFY(CachedRes.CPUDescriptorHandle.ptr != 0 || CachedRes.pObject.RawPtr<BufferD3D12Impl>()->GetDesc().Usage == USAGE_DYNAMIC, "No relevant descriptor handle"); @@ -810,107 +681,8 @@ bool ShaderResourceLayoutD3D12::SRV_CBV_UAV::IsBound(Uint32 ArrayIndex)const } - -void ShaderResourceLayoutD3D12::BindResources(IResourceMapping* pResourceMapping, - Uint32 Flags, - const ShaderResourceCacheD3D12* dbgResourceCache ) +void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderResourceCacheD3D12& SrcCache, const ShaderResourceLayoutD3D12& DstLayout, ShaderResourceCacheD3D12& DstCache)const { - VERIFY(dbgResourceCache == m_pResourceCache, "Resource cache does not match the cache provided at initialization"); - - if( !pResourceMapping ) - { - LOG_ERROR_MESSAGE( "Failed to bind resources in shader \"", GetShaderName(), "\": resource mapping is null" ); - return; - } - - Uint32 TotalResources = GetTotalSrvCbvUavCount(); - for(Uint32 r=0; r < TotalResources; ++r) - { - auto &Res = GetSrvCbvUav(r); - for(Uint32 ArrInd = 0; ArrInd < Res.Attribs.BindCount; ++ArrInd) - { - if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS ) - Res.BindResource(nullptr, ArrInd, this); - - if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(ArrInd) ) - return; - - RefCntAutoPtr<IDeviceObject> pObj; - VERIFY_EXPR(pResourceMapping != nullptr); - pResourceMapping->GetResource( Res.Attribs.Name, &pObj, ArrInd ); - if( pObj ) - { - // Call non-virtual function - Res.BindResource(pObj, ArrInd, this); - } - else - { - if( (Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED) && !Res.IsBound(ArrInd) ) - LOG_ERROR_MESSAGE( "Cannot bind resource to shader variable \"", Res.Attribs.GetPrintName(ArrInd), "\": resource view not found in the resource mapping" ); - } - } - } -} - - -IShaderVariable* ShaderResourceLayoutD3D12::GetShaderVariable(const Char* Name) -{ -#if USE_VARIABLE_HASH_MAP - // Name will be implicitly converted to HashMapStringKey without making a copy - auto it = m_VariableHash.find( Name ); - if( it != m_VariableHash.end() ) - return it->second; -#else - Uint32 TotalResources = GetTotalSrvCbvUavCount(); - for (Uint32 r=0; r < TotalResources; ++r) - { - auto &Res = GetSrvCbvUav(r); - if (strcmp(Res.Attribs.Name, Name) == 0) - return &Res; - } -#endif - - return nullptr; -} - -IShaderVariable* ShaderResourceLayoutD3D12::GetShaderVariable( Uint32 Index ) -{ - auto TotalSrvCbvUav = GetTotalSrvCbvUavCount(); - if (Index < TotalSrvCbvUav) - return &GetSrvCbvUav(Index); - else - Index -= TotalSrvCbvUav; - - //auto TotalSamplerCount = GetTotalSamplerCount(); - //if (Index < TotalSamplerCount) - // return &GetSampler(Index); - LOG_ERROR("Invalid resource index ", Index); - return nullptr; -} - -Uint32 ShaderResourceLayoutD3D12::GetVariableIndex(const ShaderVariableD3D12Base& Variable)const -{ - auto Offset = reinterpret_cast<const Uint8*>(&Variable) - reinterpret_cast<Uint8*>(m_ResourceBuffer.get()); - VERIFY_EXPR(Offset % sizeof(SRV_CBV_UAV) == 0); - auto Index = static_cast<Uint32>(Offset / sizeof(SRV_CBV_UAV)); - if (Index < GetTotalSrvCbvUavCount()) - return Index; - else - { - LOG_ERROR("Failed to get variable index. The variable ", &Variable, " does not belong to this shader resource layout"); - return static_cast<Uint32>(-1); - } -} - - -void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderResourceLayoutD3D12& DstLayout, ShaderResourceCacheD3D12& DstCache)const -{ - if (!m_pResourceCache) - { - LOG_ERROR("Resource layout has no resource cache"); - return; - } - // Static shader resources are stored as follows: // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV, // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV, @@ -933,11 +705,11 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR // D3D12_DESCRIPTOR_RANGE_TYPE_SRV = 0, // D3D12_DESCRIPTOR_RANGE_TYPE_UAV = 1 // D3D12_DESCRIPTOR_RANGE_TYPE_CBV = 2 - const auto& SrcRes = m_pResourceCache->GetRootTable(RangeType).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + const auto& SrcRes = SrcCache.GetRootTable(RangeType).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); if( !SrcRes.pObject ) LOG_ERROR_MESSAGE( "No resource assigned to static shader variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"." ); // Destination resource is at the root index and offset defined by the resource layout - auto& DstRes = DstCache.GetRootTable(res.GetRootIndex()).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + auto& DstRes = DstCache.GetRootTable(res.RootIndex).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); if(DstRes.pObject != SrcRes.pObject) { @@ -947,7 +719,7 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR DstRes.Type = SrcRes.Type; DstRes.CPUDescriptorHandle = SrcRes.CPUDescriptorHandle; - auto ShdrVisibleHeapCPUDescriptorHandle = DstCache.GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(res.GetRootIndex(), res.OffsetFromTableStart + ArrInd); + auto ShdrVisibleHeapCPUDescriptorHandle = DstCache.GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(res.RootIndex, res.OffsetFromTableStart + ArrInd); VERIFY_EXPR(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0 || DstRes.Type == CachedResourceType::CBV); // Root views are not assigned space in the GPU-visible descriptor heap allocation if (ShdrVisibleHeapCPUDescriptorHandle.ptr != 0) @@ -977,7 +749,7 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR auto BindPoint = SamInfo.Attribs.BindPoint + ArrInd; // Source sampler in the static resource cache is in the root table at index 3 // (D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = 3), at offset BindPoint - auto& SrcSampler = m_pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + const auto& SrcSampler = SrcCache.GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); if( !SrcSampler.pObject ) LOG_ERROR_MESSAGE( "No sampler assigned to static shader variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"." ); auto &DstSampler = DstCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); @@ -1009,8 +781,8 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR } -#ifdef VERIFY_SHADER_BINDINGS -void ShaderResourceLayoutD3D12::dbgVerifyBindings(ShaderResourceCacheD3D12& ResourceCache)const +#ifdef DEVELOPMENT +void ShaderResourceLayoutD3D12::dvpVerifyBindings(ShaderResourceCacheD3D12& ResourceCache)const { for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) { @@ -1021,7 +793,7 @@ void ShaderResourceLayoutD3D12::dbgVerifyBindings(ShaderResourceCacheD3D12& Reso for(Uint32 ArrInd = 0; ArrInd < res.Attribs.BindCount; ++ArrInd) { - const auto &CachedRes = ResourceCache.GetRootTable(res.GetRootIndex()).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + const auto &CachedRes = ResourceCache.GetRootTable(res.RootIndex).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); if(CachedRes.pObject) VERIFY(CachedRes.Type == res.GetResType(), "Inconsistent cached resource types"); else @@ -1050,7 +822,7 @@ void ShaderResourceLayoutD3D12::dbgVerifyBindings(ShaderResourceCacheD3D12& Reso #ifdef _DEBUG { - auto ShdrVisibleHeapCPUDescriptorHandle = ResourceCache.GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(res.GetRootIndex(), res.OffsetFromTableStart + ArrInd); + auto ShdrVisibleHeapCPUDescriptorHandle = ResourceCache.GetShaderVisibleTableCPUDescriptorHandle<D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(res.RootIndex, res.OffsetFromTableStart + ArrInd); if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) { VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Static shader resources of a shader should not be assigned shader visible descriptor space"); @@ -1147,30 +919,11 @@ const Char* ShaderResourceLayoutD3D12::GetShaderName()const } else { - PipelineStateD3D12Impl* pPSOD3D12 = nullptr; - RefCntAutoPtr<IPipelineState> pPSO(&m_Owner, IID_PipelineState); if(pPSO) { - pPSOD3D12 = pPSO.RawPtr<PipelineStateD3D12Impl>(); - } - else - { - RefCntAutoPtr<IShaderResourceBinding> pSRB(&m_Owner, IID_ShaderResourceBinding); - if(pSRB) - { - pPSOD3D12 = ValidatedCast<PipelineStateD3D12Impl>(pSRB->GetPipelineState()); - } - else - { - UNEXPECTED("Owner is expected to be a shader, a pipeline state, or a shader resource binding"); - } - } - - - if(pPSOD3D12 != nullptr) - { - auto *ppShaders = pPSOD3D12->GetShaders(); + auto* pPSOD3D12 = pPSO.RawPtr<PipelineStateD3D12Impl>(); + auto* ppShaders = pPSOD3D12->GetShaders(); auto NumShaders = pPSOD3D12->GetNumShaders(); for (Uint32 s = 0; s < NumShaders; ++s) { @@ -1180,6 +933,10 @@ const Char* ShaderResourceLayoutD3D12::GetShaderName()const } UNEXPECTED("Shader not found"); } + else + { + UNEXPECTED("Shader resource layout owner is expected to be a shader or a pipeline state"); + } } return ""; } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp new file mode 100644 index 00000000..0b9dda11 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp @@ -0,0 +1,186 @@ +/* Copyright 2015-2018 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" + +#include "ShaderVariableD3D12.h" + +namespace Diligent +{ + +size_t ShaderVariableManagerD3D12::GetRequiredMemorySize(const ShaderResourceLayoutD3D12& Layout, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumVariables) +{ + NumVariables = 0; + Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + { + NumVariables += IsAllowedType(VarType, AllowedTypeBits) ? Layout.GetCbvSrvUavCount(VarType) : 0; + } + + return NumVariables*sizeof(ShaderVariableD3D12Impl); +} + +// Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes +void ShaderVariableManagerD3D12::Initialize(const ShaderResourceLayoutD3D12& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12& ResourceCache) +{ + m_pResourceLayout = &SrcLayout; + m_pResourceCache = &ResourceCache; +#ifdef _DEBUG + m_pDbgAllocator = &Allocator; +#endif + + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + VERIFY_EXPR(m_NumVariables == 0); + auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables); + + if(m_NumVariables == 0) + return; + + auto* pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader variables", MemSize); + m_pVariables = reinterpret_cast<ShaderVariableD3D12Impl*>(pRawMem); + + Uint32 VarInd = 0; + for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + { + if (!IsAllowedType(VarType, AllowedTypeBits)) + continue; + + Uint32 NumResources = SrcLayout.GetCbvSrvUavCount(VarType); + for( Uint32 r=0; r < NumResources; ++r ) + { + const auto& SrcRes = SrcLayout.GetSrvCbvUav(VarType, r); + ::new (m_pVariables + VarInd) ShaderVariableD3D12Impl(*this, SrcRes ); + ++VarInd; + } + } + VERIFY_EXPR(VarInd == m_NumVariables); +} + +ShaderVariableManagerD3D12::~ShaderVariableManagerD3D12() +{ + VERIFY(m_pVariables == nullptr, "Destroy() has not been called"); +} + +void ShaderVariableManagerD3D12::Destroy(IMemoryAllocator &Allocator) +{ + VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + + if(m_pVariables != nullptr) + { + for(Uint32 v=0; v < m_NumVariables; ++v) + m_pVariables[v].~ShaderVariableD3D12Impl(); + Allocator.Free(m_pVariables); + m_pVariables = nullptr; + } +} + +ShaderVariableD3D12Impl* ShaderVariableManagerD3D12::GetVariable(const Char* Name) +{ + ShaderVariableD3D12Impl* pVar = nullptr; + for (Uint32 v = 0; v < m_NumVariables; ++v) + { + auto& Var = m_pVariables[v]; + if (strcmp(Var.m_Resource.Attribs.Name, Name) == 0) + { + pVar = &Var; + break; + } + } + return pVar; +} + + +ShaderVariableD3D12Impl* ShaderVariableManagerD3D12::GetVariable(Uint32 Index) +{ + if (Index >= m_NumVariables) + { + LOG_ERROR("Index ", Index, " is out of range"); + return nullptr; + } + + return m_pVariables + Index; +} + +Uint32 ShaderVariableManagerD3D12::GetVariableIndex(const ShaderVariableD3D12Impl& Variable) +{ + if (m_pVariables == nullptr) + { + LOG_ERROR("This shader variable manager has no variables"); + return static_cast<Uint32>(-1); + } + + auto Offset = reinterpret_cast<const Uint8*>(&Variable) - reinterpret_cast<Uint8*>(m_pVariables); + VERIFY(Offset % sizeof(ShaderVariableD3D12Impl) == 0, "Offset is not multiple of ShaderVariableD3D12Impl class size"); + auto Index = static_cast<Uint32>(Offset / sizeof(ShaderVariableD3D12Impl)); + if (Index < m_NumVariables) + return Index; + else + { + LOG_ERROR("Failed to get variable index. The variable ", &Variable, " does not belong to this shader variable manager"); + return static_cast<Uint32>(-1); + } +} + +void ShaderVariableManagerD3D12::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags) +{ + VERIFY_EXPR(m_pResourceCache != nullptr); + DEV_CHECK_ERR(pResourceMapping != nullptr, "Failed to bind resources: resource mapping is null"); + + for(Uint32 v=0; v < m_NumVariables; ++v) + { + auto &Var = m_pVariables[v]; + const auto& Res = Var.m_Resource; + + for(Uint32 ArrInd = 0; ArrInd < Res.Attribs.BindCount; ++ArrInd) + { + if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS ) + Res.BindResource(nullptr, ArrInd, *m_pResourceCache); + + if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(ArrInd, *m_pResourceCache) ) + return; + + RefCntAutoPtr<IDeviceObject> pObj; + VERIFY_EXPR(pResourceMapping != nullptr); + pResourceMapping->GetResource( Res.Attribs.Name, &pObj, ArrInd ); + if( pObj ) + { + // Call non-virtual function + Res.BindResource(pObj, ArrInd, *m_pResourceCache); + } + else + { + if( (Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED) && !Res.IsBound(ArrInd, *m_pResourceCache) ) + LOG_ERROR_MESSAGE( "Cannot bind resource to shader variable \"", Res.Attribs.GetPrintName(ArrInd), "\": resource view not found in the resource mapping" ); + } + } + } +} + +} |
