From 435f70be7aebd9a669d6a276df67e8eb814a45e3 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Wed, 17 Oct 2018 09:26:27 -0700 Subject: Implemented separate samplers in D3D11 --- .../include/ShaderResourceLayoutD3D11.h | 168 ++++--- .../include/ShaderResourcesD3D11.h | 22 +- .../src/DeviceContextD3D11Impl.cpp | 4 +- .../GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp | 2 +- .../src/ShaderResourceBindingD3D11Impl.cpp | 4 +- .../src/ShaderResourceLayoutD3D11.cpp | 537 +++++++++++---------- .../src/ShaderResourcesD3D11.cpp | 149 +++--- 7 files changed, 467 insertions(+), 419 deletions(-) (limited to 'Graphics/GraphicsEngineD3D11') diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h index e0329a49..24284cec 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h @@ -26,11 +26,6 @@ /// \file /// Declaration of Diligent::ShaderResourceLayoutD3D11 class -// 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 "ShaderResources.h" #include "ShaderBase.h" #include "ShaderResourceCacheD3D11.h" @@ -49,14 +44,14 @@ class IMemoryAllocator; class ShaderResourceLayoutD3D11 { public: - ShaderResourceLayoutD3D11(IObject &Owner); + ShaderResourceLayoutD3D11(IObject& Owner); ~ShaderResourceLayoutD3D11(); // No copies or moves - ShaderResourceLayoutD3D11 (const ShaderResourceLayoutD3D11&) = delete; - ShaderResourceLayoutD3D11& operator = (const ShaderResourceLayoutD3D11&) = delete; - ShaderResourceLayoutD3D11 (ShaderResourceLayoutD3D11&&) = default; - ShaderResourceLayoutD3D11& operator = (ShaderResourceLayoutD3D11&&) = delete; + ShaderResourceLayoutD3D11 (const ShaderResourceLayoutD3D11&) = delete; + ShaderResourceLayoutD3D11& operator = (const ShaderResourceLayoutD3D11&) = delete; + ShaderResourceLayoutD3D11 ( ShaderResourceLayoutD3D11&&) = default; + ShaderResourceLayoutD3D11& operator = ( ShaderResourceLayoutD3D11&&) = delete; static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, const SHADER_VARIABLE_TYPE* VarTypes, @@ -73,52 +68,53 @@ public: using ShaderVariableD3D11Base = ShaderVariableD3DBase; - struct ConstBuffBindInfo : ShaderVariableD3D11Base + struct ConstBuffBindInfo final : ShaderVariableD3D11Base { ConstBuffBindInfo( const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11 &ParentResLayout ) : + ShaderResourceLayoutD3D11& ParentResLayout ) : ShaderVariableD3D11Base(ParentResLayout, ResourceAttribs) {} // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D11* dbgResLayout); - virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0, nullptr); } + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0); } virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final { for(Uint32 elem=0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement+elem, nullptr); + BindResource(ppObjects[elem], FirstElement+elem); } __forceinline bool IsBound(Uint32 ArrayIndex); }; - struct TexAndSamplerBindInfo : ShaderVariableD3D11Base + struct TexSRVBindInfo final : ShaderVariableD3D11Base { - TexAndSamplerBindInfo( const D3DShaderResourceAttribs& _TextureAttribs, - const D3DShaderResourceAttribs& _SamplerAttribs, - ShaderResourceLayoutD3D11& ParentResLayout) : + TexSRVBindInfo( const D3DShaderResourceAttribs& _TextureAttribs, + Uint32 _SamplerIndex, + ShaderResourceLayoutD3D11& ParentResLayout) : ShaderVariableD3D11Base(ParentResLayout, _TextureAttribs), - SamplerAttribs(_SamplerAttribs) + SamplerIndex(_SamplerIndex) {} // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D11* dbgResLayout); - virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0, nullptr); } + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0); } virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final { for(Uint32 elem=0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement+elem, nullptr); + BindResource(ppObjects[elem], FirstElement+elem); } - __forceinline bool IsBound(Uint32 ArrayIndex); + __forceinline bool IsBound(Uint32 ArrayIndex)const; - static const D3DShaderResourceAttribs InvalidSamplerAttribs; + bool ValidSamplerAssigned() const {return SamplerIndex != InvalidSamplerIndex;} - const D3DShaderResourceAttribs &SamplerAttribs; + static constexpr Uint32 InvalidSamplerIndex = static_cast(-1); + const Uint32 SamplerIndex; }; - struct TexUAVBindInfo : ShaderVariableD3D11Base + struct TexUAVBindInfo final : ShaderVariableD3D11Base { TexUAVBindInfo( const D3DShaderResourceAttribs& ResourceAttribs, ShaderResourceLayoutD3D11& ParentResLayout ) : @@ -126,19 +122,19 @@ public: {} // Provide non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D11* dbgResLayout); - virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0, nullptr); } + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0); } virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final { for(Uint32 elem=0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement+elem, nullptr); + BindResource(ppObjects[elem], FirstElement+elem); } - __forceinline bool IsBound(Uint32 ArrayIndex); + __forceinline bool IsBound(Uint32 ArrayIndex)const; }; - struct BuffUAVBindInfo : ShaderVariableD3D11Base + struct BuffUAVBindInfo final : ShaderVariableD3D11Base { BuffUAVBindInfo( const D3DShaderResourceAttribs& ResourceAttribs, ShaderResourceLayoutD3D11& ParentResLayout ) : @@ -146,19 +142,19 @@ public: {} // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D11* dbgResLayout); - virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0, nullptr); } + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0); } virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final { for(Uint32 elem=0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement+elem, nullptr); + BindResource(ppObjects[elem], FirstElement+elem); } - __forceinline bool IsBound(Uint32 ArrayIndex); + __forceinline bool IsBound(Uint32 ArrayIndex)const; }; - struct BuffSRVBindInfo : ShaderVariableD3D11Base + struct BuffSRVBindInfo final : ShaderVariableD3D11Base { BuffSRVBindInfo( const D3DShaderResourceAttribs& ResourceAttribs, ShaderResourceLayoutD3D11& ParentResLayout ) : @@ -166,24 +162,44 @@ public: {} // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D11* dbgResLayout); - virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0, nullptr); } + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0); } virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final { for(Uint32 elem=0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement+elem, nullptr); + BindResource(ppObjects[elem], FirstElement+elem); } - __forceinline bool IsBound(Uint32 ArrayIndex); + __forceinline bool IsBound(Uint32 ArrayIndex)const; + }; + + struct SamplerBindInfo final : ShaderVariableD3D11Base + { + SamplerBindInfo( const D3DShaderResourceAttribs& ResourceAttribs, + ShaderResourceLayoutD3D11& ParentResLayout ) : + ShaderVariableD3D11Base(ParentResLayout, ResourceAttribs) + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + virtual void Set(IDeviceObject* pObject)override final{ BindResource(pObject, 0); } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final + { + for(Uint32 elem=0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement+elem); + } + + __forceinline bool IsBound(Uint32 ArrayIndex)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 ShaderResourceCacheD3D11& dbgResourceCache ); -#ifdef VERIFY_SHADER_BINDINGS - void dbgVerifyBindings()const; +#ifdef DEVELOPMENT + void dvpVerifyBindings()const; #endif IShaderVariable* GetShaderVariable( const Char* Name ); @@ -195,32 +211,36 @@ public: Uint32 GetVariableIndex(const ShaderVariableD3D11Base& Variable)const; Uint32 GetTotalResourceCount()const { - return m_NumCBs + m_NumTexSRVs + m_NumTexUAVs + m_NumBufUAVs + m_NumBufSRVs; + auto ResourceCount = m_NumCBs + m_NumTexSRVs + m_NumTexUAVs + m_NumBufUAVs + m_NumBufSRVs; + // Do not expose sampler variables when using combined texture samplers + if (!m_pResources->IsUsingCombinedTextureSamplers()) + ResourceCount += m_NumSamplers; + return ResourceCount; } private: - void InitVariablesHashMap(); - const Char* GetShaderName()const; // No need to use shared pointer, as the resource cache is either part of the same // ShaderD3D11Impl object, or ShaderResourceBindingD3D11Impl object - ShaderResourceCacheD3D11 *m_pResourceCache = nullptr; + ShaderResourceCacheD3D11* m_pResourceCache = nullptr; std::unique_ptr > m_ResourceBuffer; // Offsets in bytes - Uint16 m_TexAndSamplersOffset = 0; + Uint16 m_TexSRVsOffset = 0; Uint16 m_TexUAVsOffset = 0; Uint16 m_BuffUAVsOffset = 0; Uint16 m_BuffSRVsOffset = 0; + Uint16 m_SamplerOffset = 0; - Uint8 m_NumCBs = 0; // Max == 14 - Uint8 m_NumTexSRVs = 0; // Max == 128 - Uint8 m_NumTexUAVs = 0; // Max == 8 - Uint8 m_NumBufUAVs = 0; // Max == 8 - Uint8 m_NumBufSRVs = 0; // Max == 128 + Uint8 m_NumCBs = 0; // Max == 14 + Uint8 m_NumTexSRVs = 0; // Max == 128 + Uint8 m_NumTexUAVs = 0; // Max == 8 + Uint8 m_NumBufUAVs = 0; // Max == 8 + Uint8 m_NumBufSRVs = 0; // Max == 128 + Uint8 m_NumSamplers = 0; // Max == 16 ConstBuffBindInfo& GetCB(Uint32 cb) { @@ -233,15 +253,15 @@ private: return reinterpret_cast(m_ResourceBuffer.get())[cb]; } - TexAndSamplerBindInfo& GetTexSRV(Uint32 t) + TexSRVBindInfo& GetTexSRV(Uint32 t) { VERIFY_EXPR(t( reinterpret_cast(m_ResourceBuffer.get()) + m_TexAndSamplersOffset )[t]; + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_TexSRVsOffset)[t]; } - const TexAndSamplerBindInfo& GetTexSRV(Uint32 t)const + const TexSRVBindInfo& GetTexSRV(Uint32 t)const { VERIFY_EXPR(t( reinterpret_cast(m_ResourceBuffer.get()) + m_TexAndSamplersOffset )[t]; + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_TexSRVsOffset)[t]; } TexUAVBindInfo& GetTexUAV(Uint32 u) @@ -277,16 +297,29 @@ private: return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_BuffSRVsOffset)[s]; } + SamplerBindInfo& GetSampler(Uint32 s) + { + VERIFY_EXPR(s < m_NumSamplers); + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_SamplerOffset)[s]; + } + const SamplerBindInfo& GetSampler(Uint32 s)const + { + VERIFY_EXPR(s < m_NumSamplers); + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_SamplerOffset)[s]; + } + template - void HandleResources(THandleCB HandleCB, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV) + typename THandleBufUAV, + typename THandleSampler> + void HandleResources(THandleCB HandleCB, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV, + THandleSampler HandleSampler) { for (Uint32 cb = 0; cb < m_NumCBs; ++cb) HandleCB(GetCB(cb)); @@ -298,15 +331,10 @@ private: HandleBufSRV(GetBufSRV(s)); for (Uint32 u = 0; u < m_NumBufUAVs; ++u) HandleBufUAV(GetBufUAV(u)); + for (Uint32 s = 0; s < m_NumSamplers; ++s) + HandleSampler(GetSampler(s)); } -#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 VariableHashData; - std::unordered_map, std::equal_to, STDAllocatorRawMem > m_VariableHash; -#endif - std::shared_ptr m_pResources; IObject& m_Owner; }; diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h index ce8cb8ad..7aee3bb9 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h @@ -40,15 +40,15 @@ // | | unique_ptr | | | | | | | // | ShaderResourcesD3D11 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | // |______________________| |________|___________|___________|___________|___________|____________| -// A A A A A A A -// | \ \ \ \ \ | -// |shared_ptr Ref Ref Ref Ref Ref | -// ________|__________________ ____\_________\__________\__________\___________\_______ | -// | | unique_ptr | | | | | | | -// | ShaderResourceLayoutD3D11 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | | -// |___________________________| |________|___________|___________|___________|___________| | -// | Ref -// |______________________________________________| +// A A A A A A A +// | \ \ \ \ \ \ +// |shared_ptr Ref Ref Ref Ref Ref Ref +// ________|__________________ ____\_________\__________\__________\___________\_______ ___\______ +// | | unique_ptr | | | | | | | +// | ShaderResourceLayoutD3D11 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | +// |___________________________| |________|___________|___________|___________|___________|__________| +// | A +// |_________________SamplerIndex_________________| // // // One ShaderResources instance can be referenced by multiple objects @@ -95,8 +95,8 @@ public: __forceinline Int32 GetMaxSamplerBindPoint()const{return m_MaxSamplerBindPoint; } __forceinline Int32 GetMaxUAVBindPoint() const{return m_MaxUAVBindPoint; } -#ifdef VERIFY_SHADER_BINDINGS - void dbgVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[], +#ifdef DEVELOPMENT + void dvpVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[], ID3D11ShaderResourceView* CommittedD3D11SRVs[], ID3D11Resource* CommittedD3D11SRVResources[], ID3D11SamplerState* CommittedD3D11Samplers[], diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index da225356..ee1e5f2d 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -201,7 +201,7 @@ namespace Diligent #ifdef DEVELOPMENT for (Uint32 s = 0; s < NumShaders; ++s) { - pShaderResBindingD3D11->GetResourceLayout(s).dbgVerifyBindings(); + pShaderResBindingD3D11->GetResourceLayout(s).dvpVerifyBindings(); // Static resource bindings are verified in BindStaticShaderResources() } #endif @@ -597,7 +597,7 @@ namespace Diligent if( CommitResources && m_DebugFlags & (Uint32)EngineD3D11DebugFlags::VerifyCommittedShaderResources ) { // Use full resource layout to verify that all required resources are committed - pShaderD3D11->GetResources()->dbgVerifyCommittedResources( + pShaderD3D11->GetResources()->dvpVerifyCommittedResources( m_CommittedD3D11CBs[ShaderTypeInd], m_CommittedD3D11SRVs[ShaderTypeInd], m_CommittedD3D11SRVResources[ShaderTypeInd], diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp index 1549c962..e8e9d8fd 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp @@ -78,7 +78,7 @@ ShaderD3D11Impl::ShaderD3D11Impl(IReferenceCounters* pRefCounters, // Load shader resources auto &Allocator = GetRawAllocator(); auto *pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", sizeof(ShaderResourcesD3D11)); - auto *pResources = new (pRawMem) ShaderResourcesD3D11(pRenderDeviceD3D11, m_pShaderByteCode, m_Desc, CreationAttribs.CombinedSamplerSuffix); + auto *pResources = new (pRawMem) ShaderResourcesD3D11(pRenderDeviceD3D11, m_pShaderByteCode, m_Desc, CreationAttribs.UseCombinedTextureSamplers ? CreationAttribs.CombinedSamplerSuffix : nullptr); m_pShaderResources.reset(pResources, STDDeleterRawMem(Allocator)); // Clone only static resources that will be set directly in the shader diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 201cf0e4..021743e4 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -127,8 +127,8 @@ void ShaderResourceBindingD3D11Impl::BindStaticShaderResources() for (Uint32 shader = 0; shader < NumShaders; ++shader) { auto *pShaderD3D11 = ValidatedCast( ppShaders[shader] ); -#ifdef VERIFY_SHADER_BINDINGS - pShaderD3D11->GetStaticResourceLayout().dbgVerifyBindings(); +#ifdef DEVELOPMENT + pShaderD3D11->GetStaticResourceLayout().dvpVerifyBindings(); #endif #ifdef _DEBUG diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index 66f7a11b..67affc45 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -40,9 +40,6 @@ namespace Diligent ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& Owner) : m_Owner(Owner) -#if USE_VARIABLE_HASH_MAP - , m_VariableHash(STD_ALLOCATOR_RAW_MEM(VariableHashData, GetRawAllocator(), "Allocator for vector")) -#endif { } @@ -54,9 +51,9 @@ ShaderResourceLayoutD3D11::~ShaderResourceLayoutD3D11() cb.~ConstBuffBindInfo(); }, - [&](TexAndSamplerBindInfo& ts) + [&](TexSRVBindInfo& ts) { - ts.~TexAndSamplerBindInfo(); + ts.~TexSRVBindInfo(); }, [&](TexUAVBindInfo& uav) @@ -72,23 +69,27 @@ ShaderResourceLayoutD3D11::~ShaderResourceLayoutD3D11() [&](BuffUAVBindInfo& uav) { uav.~BuffUAVBindInfo(); + }, + + [&](SamplerBindInfo& sam) + { + sam.~SamplerBindInfo(); } ); } -const D3DShaderResourceAttribs ShaderResourceLayoutD3D11::TexAndSamplerBindInfo::InvalidSamplerAttribs("Invalid sampler", D3DShaderResourceAttribs::InvalidBindPoint, 0, D3D_SIT_SAMPLER, SHADER_VARIABLE_TYPE_NUM_TYPES, D3D_SRV_DIMENSION_UNKNOWN, D3DShaderResourceAttribs::InvalidSamplerId, false); - size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, const SHADER_VARIABLE_TYPE* VarTypes, Uint32 NumVarTypes) { Uint32 NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers; SrcResources.CountResources(VarTypes, NumVarTypes, NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers); - auto MemSize = NumCBs * sizeof(ConstBuffBindInfo) + - NumTexSRVs * sizeof(TexAndSamplerBindInfo) + - NumTexUAVs * sizeof(TexUAVBindInfo) + - NumBufUAVs * sizeof(BuffUAVBindInfo) + - NumBufSRVs * sizeof(BuffSRVBindInfo); + auto MemSize = NumCBs * sizeof(ConstBuffBindInfo) + + NumTexSRVs * sizeof(TexSRVBindInfo) + + NumTexUAVs * sizeof(TexUAVBindInfo) + + NumBufUAVs * sizeof(BuffUAVBindInfo) + + NumBufSRVs * sizeof(BuffSRVBindInfo) + + NumSamplers * sizeof(SamplerBindInfo); return MemSize; } @@ -104,24 +105,19 @@ void ShaderResourceLayoutD3D11::Initialize(const std::shared_ptrCountResources(VarTypes, NumVarTypes, NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers); // Initialize offsets - m_TexAndSamplersOffset = 0 + static_cast( NumCBs * sizeof(ConstBuffBindInfo) ); - m_TexUAVsOffset = m_TexAndSamplersOffset + static_cast( NumTexSRVs * sizeof(TexAndSamplerBindInfo) ); - m_BuffUAVsOffset = m_TexUAVsOffset + static_cast( NumTexUAVs * sizeof(TexUAVBindInfo) ); - m_BuffSRVsOffset = m_BuffUAVsOffset + static_cast( NumBufUAVs * sizeof(BuffUAVBindInfo) ); - auto MemorySize = m_BuffSRVsOffset + NumBufSRVs * sizeof(BuffSRVBindInfo); + m_TexSRVsOffset = 0 + static_cast( NumCBs * sizeof(ConstBuffBindInfo)); + m_TexUAVsOffset = m_TexSRVsOffset + static_cast( NumTexSRVs * sizeof(TexSRVBindInfo) ); + m_BuffUAVsOffset = m_TexUAVsOffset + static_cast( NumTexUAVs * sizeof(TexUAVBindInfo) ); + m_BuffSRVsOffset = m_BuffUAVsOffset + static_cast( NumBufUAVs * sizeof(BuffUAVBindInfo) ); + m_SamplerOffset = m_BuffSRVsOffset + static_cast( NumBufSRVs * sizeof(BuffSRVBindInfo) ); + auto MemorySize = m_SamplerOffset + NumSamplers * sizeof(SamplerBindInfo) ; VERIFY_EXPR(MemorySize == GetRequiredMemorySize(*pSrcResources, VarTypes, NumVarTypes)); @@ -131,23 +127,26 @@ void ShaderResourceLayoutD3D11::Initialize(const std::shared_ptr >(pRawMem, ResLayoutDataAllocator); } - VERIFY_EXPR(NumCBs < 255); + VERIFY_EXPR(NumCBs < 255); VERIFY_EXPR(NumTexSRVs < 255); VERIFY_EXPR(NumTexUAVs < 255); VERIFY_EXPR(NumBufSRVs < 255); VERIFY_EXPR(NumBufUAVs < 255); - m_NumCBs = static_cast(NumCBs); - m_NumTexSRVs = static_cast(NumTexSRVs); - m_NumTexUAVs = static_cast(NumTexUAVs); - m_NumBufSRVs = static_cast(NumBufSRVs); - m_NumBufUAVs = static_cast(NumBufUAVs); + VERIFY_EXPR(NumSamplers< 255); + m_NumCBs = static_cast(NumCBs); + m_NumTexSRVs = static_cast(NumTexSRVs); + m_NumTexUAVs = static_cast(NumTexUAVs); + m_NumBufSRVs = static_cast(NumBufSRVs); + m_NumBufUAVs = static_cast(NumBufUAVs); + m_NumSamplers = static_cast(NumSamplers); // Current resource index for every resource type - Uint32 cb = 0; + Uint32 cb = 0; Uint32 texSrv = 0; Uint32 texUav = 0; Uint32 bufSrv = 0; Uint32 bufUav = 0; + Uint32 sam = 0; Uint32 NumCBSlots = 0; Uint32 NumSRVSlots = 0; @@ -156,29 +155,56 @@ void ShaderResourceLayoutD3D11::Initialize(const std::shared_ptrProcessResources( VarTypes, NumVarTypes, - [&](const D3DShaderResourceAttribs &CB, Uint32) + [&](const D3DShaderResourceAttribs& CB, Uint32) { VERIFY_EXPR( CB.IsAllowedType(AllowedTypeBits) ); + // Initialize current CB in place, increment CB counter new (&GetCB(cb++)) ConstBuffBindInfo( CB, *this ); NumCBSlots = std::max(NumCBSlots, static_cast(CB.BindPoint + CB.BindCount)); }, + [&](const D3DShaderResourceAttribs& Sampler, Uint32) + { + VERIFY_EXPR(Sampler.IsAllowedType(AllowedTypeBits)); + + // Skip static samplers as they are initialized in the resource cache + if (!Sampler.IsStaticSampler()) + { + // Initialize current sampler in place, increment sampler counter + new (&GetSampler(sam++)) SamplerBindInfo( Sampler, *this ); + NumSamplerSlots = std::max(NumSamplerSlots, static_cast(Sampler.BindPoint + Sampler.BindCount)); + } + }, + [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { VERIFY_EXPR( TexSRV.IsAllowedType(AllowedTypeBits) ); - // Set reference to a special static instance representing invalid sampler - // if no sampler is assigned to texture SRV - const D3DShaderResourceAttribs& SamplerAttribs = TexSRV.IsValidSampler() ? - pSrcResources->GetSampler(TexSRV.GetSamplerId()) : TexAndSamplerBindInfo::InvalidSamplerAttribs; + VERIFY(sam == m_NumSamplers, "All samplers must be initialized before texture SRVs"); + + Uint32 AssignedSamplerIndex = TexSRVBindInfo::InvalidSamplerIndex; + if (TexSRV.ValidSamplerAssigned()) + { + const auto& AssignedSamplerAttribs = m_pResources->GetSampler(TexSRV.GetSamplerId()); + // Do not assign static sampler to texture SRV as it is initialized directly in the shader resource cache + if (!AssignedSamplerAttribs.IsStaticSampler()) + { + for (AssignedSamplerIndex = 0; AssignedSamplerIndex < m_NumSamplers; ++AssignedSamplerIndex) + { + const auto& Sampler = GetSampler(AssignedSamplerIndex); + if (strcmp(Sampler.Attribs.Name, AssignedSamplerAttribs.Name) == 0) + break; + } + VERIFY(AssignedSamplerIndex < m_NumSamplers, "Unable to find assigned sampler"); + } + } + // Initialize tex SRV in place, increment counter of tex SRVs - new (&GetTexSRV(texSrv++)) TexAndSamplerBindInfo( TexSRV, SamplerAttribs, *this ); + new (&GetTexSRV(texSrv++)) TexSRVBindInfo( TexSRV, AssignedSamplerIndex, *this ); NumSRVSlots = std::max(NumSRVSlots, static_cast(TexSRV.BindPoint + TexSRV.BindCount)); - if( SamplerAttribs.IsValidBindPoint() ) - NumSamplerSlots = std::max(NumSamplerSlots, static_cast(SamplerAttribs.BindPoint + SamplerAttribs.BindCount)); }, - [&](const D3DShaderResourceAttribs &TexUAV, Uint32) + [&](const D3DShaderResourceAttribs& TexUAV, Uint32) { VERIFY_EXPR( TexUAV.IsAllowedType(AllowedTypeBits) ); @@ -187,7 +213,7 @@ void ShaderResourceLayoutD3D11::Initialize(const std::shared_ptr(TexUAV.BindPoint + TexUAV.BindCount)); }, - [&](const D3DShaderResourceAttribs &BuffSRV, Uint32) + [&](const D3DShaderResourceAttribs& BuffSRV, Uint32) { VERIFY_EXPR(BuffSRV.IsAllowedType(AllowedTypeBits)); @@ -196,7 +222,7 @@ void ShaderResourceLayoutD3D11::Initialize(const std::shared_ptr(BuffSRV.BindPoint + BuffSRV.BindCount)); }, - [&](const D3DShaderResourceAttribs &BuffUAV, Uint32) + [&](const D3DShaderResourceAttribs& BuffUAV, Uint32) { VERIFY_EXPR(BuffUAV.IsAllowedType(AllowedTypeBits)); @@ -216,23 +242,22 @@ void ShaderResourceLayoutD3D11::Initialize(const std::shared_ptrInitialize(NumCBSlots, NumSRVSlots, NumSamplerSlots, NumUAVSlots, ResCacheDataAllocator); } - VERIFY(cb == m_NumCBs, "Not all CBs are initialized, which will result in a crash when dtor is called"); - VERIFY(texSrv == m_NumTexSRVs, "Not all Tex SRVs are initialized, which will result in a crash when dtor is called"); - VERIFY(texUav == m_NumTexUAVs, "Not all Tex UAVs are initialized, which will result in a crash when dtor is called"); - VERIFY(bufSrv == m_NumBufSRVs, "Not all Buf SRVs are initialized, which will result in a crash when dtor is called"); - VERIFY(bufUav == m_NumBufUAVs, "Not all Buf UAVs are initialized, which will result in a crash when dtor is called"); - - InitVariablesHashMap(); + VERIFY(cb == m_NumCBs, "Not all CBs are initialized which will cause a crash when dtor is called"); + VERIFY(texSrv == m_NumTexSRVs, "Not all Tex SRVs are initialized which will cause a crash when dtor is called"); + VERIFY(texUav == m_NumTexUAVs, "Not all Tex UAVs are initialized which will cause a crash when dtor is called"); + VERIFY(bufSrv == m_NumBufSRVs, "Not all Buf SRVs are initialized which will cause a crash when dtor is called"); + VERIFY(bufUav == m_NumBufUAVs, "Not all Buf UAVs are initialized which will cause a crash when dtor is called"); + VERIFY(sam == m_NumSamplers, "Not all samplers are initialized which will cause a crash when dtor is called"); } void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache) { VERIFY(m_pResourceCache, "Resource cache must not be null"); - VERIFY( DstCache.GetCBCount() >= m_pResourceCache->GetCBCount(), "Dst cache is not large enough to contain all CBs" ); - VERIFY( DstCache.GetSRVCount() >= m_pResourceCache->GetSRVCount(), "Dst cache is not large enough to contain all SRVs" ); + VERIFY( DstCache.GetCBCount() >= m_pResourceCache->GetCBCount(), "Dst cache is not large enough to contain all CBs" ); + VERIFY( DstCache.GetSRVCount() >= m_pResourceCache->GetSRVCount(), "Dst cache is not large enough to contain all SRVs" ); VERIFY( DstCache.GetSamplerCount() >= m_pResourceCache->GetSamplerCount(), "Dst cache is not large enough to contain all samplers" ); - VERIFY( DstCache.GetUAVCount() >= m_pResourceCache->GetUAVCount(), "Dst cache is not large enough to contain all UAVs" ); + VERIFY( DstCache.GetUAVCount() >= m_pResourceCache->GetUAVCount(), "Dst cache is not large enough to contain all UAVs" ); ShaderResourceCacheD3D11::CachedCB* CachedCBs = nullptr; ID3D11Buffer** d3d11CBs = nullptr; @@ -262,38 +287,23 @@ void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache DstCache.GetUAVArrays (DstUAVResources, DstD3D11UAVs); HandleResources( - [&](const ConstBuffBindInfo&cb) + [&](const ConstBuffBindInfo& cb) { for(auto CBSlot = cb.Attribs.BindPoint; CBSlot < cb.Attribs.BindPoint+cb.Attribs.BindCount; ++CBSlot) { VERIFY_EXPR(CBSlot < m_pResourceCache->GetCBCount() && CBSlot < DstCache.GetCBCount()); - DstCBs[CBSlot] = CachedCBs[CBSlot]; - DstD3D11CBs[CBSlot] = d3d11CBs[CBSlot]; + DstCBs [CBSlot] = CachedCBs[CBSlot]; + DstD3D11CBs[CBSlot] = d3d11CBs [CBSlot]; } }, - [&](const TexAndSamplerBindInfo& ts) + [&](const TexSRVBindInfo& ts) { for(auto SRVSlot = ts.Attribs.BindPoint; SRVSlot < ts.Attribs.BindPoint + ts.Attribs.BindCount; ++SRVSlot) { VERIFY_EXPR(SRVSlot < m_pResourceCache->GetSRVCount() && SRVSlot < DstCache.GetSRVCount()); DstSRVResources[SRVSlot] = CachedSRVResources[SRVSlot]; - DstD3D11SRVs[SRVSlot] = d3d11SRVs[SRVSlot]; - if( ts.SamplerAttribs.IsValidBindPoint() ) - { - VERIFY_EXPR(ts.SamplerAttribs.BindCount == ts.Attribs.BindCount || ts.SamplerAttribs.BindCount == 1); - Uint32 SamplerSlot = ts.SamplerAttribs.BindPoint + (ts.SamplerAttribs.BindCount == 1 ? 0 : (SRVSlot - ts.Attribs.BindPoint)); - if( !ts.SamplerAttribs.IsStaticSampler() ) - { - VERIFY_EXPR( SamplerSlot < m_pResourceCache->GetSamplerCount() && SamplerSlot < DstCache.GetSamplerCount() ); - DstSamplers[SamplerSlot] = CachedSamplers[SamplerSlot]; - DstD3D11Samplers[SamplerSlot] = d3d11Samplers[SamplerSlot]; - } - else - { - VERIFY(DstSamplers[SamplerSlot].pSampler != nullptr && DstD3D11Samplers[SamplerSlot] != nullptr, "Static samplers must be initialized when shader resource cache is created"); - } - } + DstD3D11SRVs [SRVSlot] = d3d11SRVs [SRVSlot]; } }, @@ -303,7 +313,7 @@ void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache { VERIFY_EXPR(UAVSlot < m_pResourceCache->GetUAVCount() && UAVSlot < DstCache.GetUAVCount()); DstUAVResources[UAVSlot] = CachedUAVResources[UAVSlot]; - DstD3D11UAVs[UAVSlot] = d3d11UAVs[UAVSlot]; + DstD3D11UAVs [UAVSlot] = d3d11UAVs [UAVSlot]; } }, @@ -313,7 +323,7 @@ void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache { VERIFY_EXPR(SRVSlot < m_pResourceCache->GetSRVCount() && SRVSlot < DstCache.GetSRVCount()); DstSRVResources[SRVSlot] = CachedSRVResources[SRVSlot]; - DstD3D11SRVs[SRVSlot] = d3d11SRVs[SRVSlot]; + DstD3D11SRVs [SRVSlot] = d3d11SRVs [SRVSlot]; } }, @@ -323,44 +333,21 @@ void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache { VERIFY_EXPR(UAVSlot < m_pResourceCache->GetUAVCount() && UAVSlot < DstCache.GetUAVCount()); DstUAVResources[UAVSlot] = CachedUAVResources[UAVSlot]; - DstD3D11UAVs[UAVSlot] = d3d11UAVs[UAVSlot]; + DstD3D11UAVs [UAVSlot] = d3d11UAVs [UAVSlot]; } - } - ); -} - -void ShaderResourceLayoutD3D11::InitVariablesHashMap() -{ -#if USE_VARIABLE_HASH_MAP - // After all resources are loaded, we can populate shader variable hash map. - // The map contains raw pointers, but none of the arrays will ever change. - HandleResources( - [&](ConstBuffBindInfo&cb) - { - m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(cb.Attribs.Name, true), &cb ) ); }, - [&](TexAndSamplerBindInfo& ts) + [&](const SamplerBindInfo& sam) { - m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(ts.Attribs.Name, true), &ts ) ); - }, - - [&](TexUAVBindInfo& uav) - { - m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(uav.Attribs.Name, true), &uav ) ); - }, - - [&](BuffSRVBindInfo& srv) - { - m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(srv.Attribs.Name, true), &srv ) ); - }, - - [&](BuffUAVBindInfo& uav) - { - m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(uav.Attribs.Name, true), &uav ) ); + VERIFY(!sam.Attribs.IsStaticSampler(), "Variables are not created for static samplers"); + for(auto SamSlot = sam.Attribs.BindPoint; SamSlot < sam.Attribs.BindPoint + sam.Attribs.BindCount; ++SamSlot) + { + VERIFY_EXPR(SamSlot < m_pResourceCache->GetSamplerCount() && SamSlot < DstCache.GetSamplerCount()); + DstSamplers [SamSlot] = CachedSamplers[SamSlot]; + DstD3D11Samplers[SamSlot] = d3d11Samplers [SamSlot]; + } } ); -#endif } #define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, Attribs, ArrayInd, ShaderName, ...)\ @@ -374,13 +361,11 @@ do{ "\" in shader \"", ShaderName, "\". ", __VA_ARGS__ ); \ }while(false) -void ShaderResourceLayoutD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* pBuffer, - Uint32 ArrayIndex, - const ShaderResourceLayoutD3D11* dbgResLayout) +void ShaderResourceLayoutD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* pBuffer, + Uint32 ArrayIndex) { 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); RefCntAutoPtr pBuffD3D11Impl; @@ -405,14 +390,14 @@ void ShaderResourceLayoutD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* } } -#ifdef VERIFY_SHADER_BINDINGS +#ifdef DEVELOPMENT if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) { auto &CachedCB = pResourceCache->GetCB(Attribs.BindPoint + ArrayIndex); if( CachedCB.pBuff != nullptr && CachedCB.pBuff != pBuffD3D11Impl) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null constant buffer 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 may cause unpredicted behavior. 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(ArrayIndex), "\" in shader \"", m_ParentResLayout.GetShaderName(), "\". Attempting to bind another resource or null is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic." ); } } #endif @@ -432,9 +417,9 @@ bool ShaderResourceLayoutD3D11::ConstBuffBindInfo::IsBound(Uint32 ArrayIndex) -#ifdef VERIFY_SHADER_BINDINGS -template ///< Type of the expected view enum +#ifdef DEVELOPMENT +template ///< Type of the expected view enum bool dbgVerifyViewType( const char *ViewTypeName, TResourceViewType pViewD3D11, const D3DShaderResourceAttribs& Attribs, @@ -459,218 +444,245 @@ bool dbgVerifyViewType( const char *ViewTypeName, } #endif -void ShaderResourceLayoutD3D11::TexAndSamplerBindInfo::BindResource( IDeviceObject* pView, - Uint32 ArrayIndex, - const ShaderResourceLayoutD3D11* dbgResLayout ) +void ShaderResourceLayoutD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pView, + Uint32 ArrayIndex) { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); - VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache"); + VERIFY(m_ParentResLayout.m_pResourceCache, "Resource cache is null"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type RefCntAutoPtr pViewD3D11(pView, IID_TextureViewD3D11); -#ifdef VERIFY_SHADER_BINDINGS - if(pView && !pViewD3D11) +#ifdef DEVELOPMENT + if (pView && !pViewD3D11) LOG_RESOURCE_BINDING_ERROR("resource", pView, Attribs, ArrayIndex, "", "Incorect resource type: texture view is expected."); - if(pViewD3D11 && !dbgVerifyViewType("texture view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, TEXTURE_VIEW_SHADER_RESOURCE, m_ParentResLayout.GetShaderName())) + if (pViewD3D11 && !dbgVerifyViewType("texture view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, TEXTURE_VIEW_SHADER_RESOURCE, m_ParentResLayout.GetShaderName())) pViewD3D11.Release(); if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) { - auto &CachedSRV = pResourceCache->GetSRV(Attribs.BindPoint + ArrayIndex); + auto &CachedSRV = ResourceCache.GetSRV(Attribs.BindPoint + ArrayIndex); if( CachedSRV.pView != nullptr && CachedSRV.pView != pViewD3D11) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null texture SRV 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 may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null texture SRV 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 may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic." ); } } #endif - if( SamplerAttribs.IsValidBindPoint() ) + if (ValidSamplerAssigned()) { - VERIFY_EXPR(SamplerAttribs.BindCount == Attribs.BindCount || SamplerAttribs.BindCount == 1); - auto SamplerBindPoint = SamplerAttribs.BindPoint + (SamplerAttribs.BindCount != 1 ? ArrayIndex : 0); - if( !SamplerAttribs.IsStaticSampler() ) + auto& Sampler = m_ParentResLayout.GetSampler(SamplerIndex); + VERIFY(!Sampler.Attribs.IsStaticSampler(), "Static samplers are not assigned to texture SRVs as they are initialized directly in the shader resource cache"); + VERIFY_EXPR(Sampler.Attribs.BindCount == Attribs.BindCount || Sampler.Attribs.BindCount == 1); + auto SamplerBindPoint = Sampler.Attribs.BindPoint + (Sampler.Attribs.BindCount != 1 ? ArrayIndex : 0); + + SamplerD3D11Impl *pSamplerD3D11Impl = nullptr; + if( pViewD3D11 ) { - SamplerD3D11Impl *pSamplerD3D11Impl = nullptr; - if( pViewD3D11 ) + pSamplerD3D11Impl = ValidatedCast(pViewD3D11->GetSampler()); +#ifdef DEVELOPMENT + if (pSamplerD3D11Impl == nullptr) { - pSamplerD3D11Impl = ValidatedCast(pViewD3D11->GetSampler()); -#ifdef VERIFY_SHADER_BINDINGS - if(pSamplerD3D11Impl==nullptr) - { - if(SamplerAttribs.BindCount > 1) - LOG_ERROR_MESSAGE( "Failed to bind sampler to variable \"", SamplerAttribs.Name, "[", ArrayIndex,"]\". Sampler is not set in the texture view \"", pViewD3D11->GetDesc().Name, "\"" ); - else - LOG_ERROR_MESSAGE( "Failed to bind sampler to variable \"", SamplerAttribs.Name, "\". Sampler is not set in the texture view \"", pViewD3D11->GetDesc().Name, "\"" ); - } -#endif + if(Sampler.Attribs.BindCount > 1) + LOG_ERROR_MESSAGE( "Failed to bind sampler to variable \"", Sampler.Attribs.Name, "[", ArrayIndex,"]\". Sampler is not set in the texture view \"", pViewD3D11->GetDesc().Name, "\"" ); + else + LOG_ERROR_MESSAGE( "Failed to bind sampler to variable \"", Sampler.Attribs.Name, "\". Sampler is not set in the texture view \"", pViewD3D11->GetDesc().Name, "\"" ); } - - pResourceCache->SetSampler(SamplerBindPoint, pSamplerD3D11Impl); - } - else - { - VERIFY_EXPR(SamplerAttribs.BindCount == Attribs.BindCount || SamplerAttribs.BindCount == 1); - VERIFY( pResourceCache->IsSamplerBound(SamplerBindPoint), "Static samplers must be bound once when shader cache is created" ); +#endif } + ResourceCache.SetSampler(SamplerBindPoint, pSamplerD3D11Impl); } - pResourceCache->SetTexSRV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); + ResourceCache.SetTexSRV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); } +void ShaderResourceLayoutD3D11::SamplerBindInfo::BindResource(IDeviceObject* pSampler, + Uint32 ArrayIndex) +{ + VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); + VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; + VERIFY(!Attribs.IsStaticSampler(), "Cannot bind sampler to a static sampler"); + + // We cannot use ValidatedCast<> here as the resource retrieved from the + // resource mapping can be of wrong type + RefCntAutoPtr pSamplerD3D11(pSampler, IID_SamplerD3D11); -void ShaderResourceLayoutD3D11::BuffSRVBindInfo::BindResource( IDeviceObject* pView, - Uint32 ArrayIndex, - const ShaderResourceLayoutD3D11* dbgResLayout ) +#ifdef DEVELOPMENT + if (pSampler && !pSamplerD3D11) + LOG_RESOURCE_BINDING_ERROR("sampler", pSampler, Attribs, ArrayIndex, "", "Incorect resource type: sampler is expected."); + + if (Attribs.ValidTexSRVAssigned()) + { + auto* TexSRVName = m_ParentResLayout.m_pResources->GetTexSRV(Attribs.GetTexSRVId()).Name; + LOG_WARNING_MESSAGE("Texture sampler sampler '", Attribs.Name, "' is assigned to texture SRV '", TexSRVName, "' and should not be accessed directly. The sampler is initialized when texture SRV is set to '", TexSRVName, "' variable."); + } + + if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) + { + auto &CachedSampler = ResourceCache.GetSampler(Attribs.BindPoint + ArrayIndex); + if( CachedSampler.pSampler != nullptr && CachedSampler.pSampler != pSamplerD3D11) + { + auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); + 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 or null is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic." ); + } + } +#endif + + ResourceCache.SetSampler(Attribs.BindPoint + ArrayIndex, std::move(pSamplerD3D11)); +} + +void ShaderResourceLayoutD3D11::BuffSRVBindInfo::BindResource(IDeviceObject* pView, + Uint32 ArrayIndex) { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); - VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache"); + VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); VERIFY(ArrayIndex < Attribs.BindCount, "Array index is out of range"); + auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type RefCntAutoPtr pViewD3D11(pView, IID_BufferViewD3D11); -#ifdef VERIFY_SHADER_BINDINGS - if(pView && !pViewD3D11) +#ifdef DEVELOPMENT + if (pView && !pViewD3D11) LOG_RESOURCE_BINDING_ERROR("resource", pView, Attribs, ArrayIndex, "", "Incorect resource type: buffer view is expected."); - if(pViewD3D11 && !dbgVerifyViewType("buffer view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, BUFFER_VIEW_SHADER_RESOURCE, m_ParentResLayout.GetShaderName())) + if (pViewD3D11 && !dbgVerifyViewType("buffer view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, BUFFER_VIEW_SHADER_RESOURCE, m_ParentResLayout.GetShaderName())) pViewD3D11.Release(); - if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) + if (Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) { - auto &CachedSRV = pResourceCache->GetSRV(Attribs.BindPoint + ArrayIndex); + auto &CachedSRV = ResourceCache.GetSRV(Attribs.BindPoint + ArrayIndex); if( CachedSRV.pView != nullptr && CachedSRV.pView != pViewD3D11) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null buffer SRV 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 may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null buffer SRV 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 may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic." ); } } #endif - pResourceCache->SetBufSRV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); + ResourceCache.SetBufSRV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); } -void ShaderResourceLayoutD3D11::TexUAVBindInfo::BindResource( IDeviceObject* pView, - Uint32 ArrayIndex, - const ShaderResourceLayoutD3D11* dbgResLayout ) +void ShaderResourceLayoutD3D11::TexUAVBindInfo::BindResource(IDeviceObject* pView, + Uint32 ArrayIndex) { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); - VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache"); + VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); VERIFY(ArrayIndex < Attribs.BindCount, "Array index is out of range"); + auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type RefCntAutoPtr pViewD3D11(pView, IID_TextureViewD3D11); -#ifdef VERIFY_SHADER_BINDINGS - if(pView && !pViewD3D11) +#ifdef DEVELOPMENT + if (pView && !pViewD3D11) LOG_RESOURCE_BINDING_ERROR("resource", pView, Attribs, ArrayIndex, "", "Incorect resource type: texture view is expected."); - if(pViewD3D11 && !dbgVerifyViewType("texture view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, TEXTURE_VIEW_UNORDERED_ACCESS, m_ParentResLayout.GetShaderName())) + if (pViewD3D11 && !dbgVerifyViewType("texture view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, TEXTURE_VIEW_UNORDERED_ACCESS, m_ParentResLayout.GetShaderName())) pViewD3D11.Release(); - if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) + if (Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) { - auto &CachedUAV = pResourceCache->GetUAV(Attribs.BindPoint + ArrayIndex); + auto &CachedUAV = ResourceCache.GetUAV(Attribs.BindPoint + ArrayIndex); if( CachedUAV.pView != nullptr && CachedUAV.pView != pViewD3D11) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null texture UAV 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 may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null texture UAV 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 may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic." ); } } #endif - pResourceCache->SetTexUAV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); + ResourceCache.SetTexUAV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); } -void ShaderResourceLayoutD3D11::BuffUAVBindInfo::BindResource( IDeviceObject* pView, - Uint32 ArrayIndex, - const ShaderResourceLayoutD3D11* dbgResLayout ) +void ShaderResourceLayoutD3D11::BuffUAVBindInfo::BindResource(IDeviceObject* pView, + Uint32 ArrayIndex) { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); - VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache"); + VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); VERIFY(ArrayIndex < Attribs.BindCount, "Array index is out of range"); + auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type RefCntAutoPtr pViewD3D11(pView, IID_BufferViewD3D11); -#ifdef VERIFY_SHADER_BINDINGS - if(pView && !pViewD3D11) +#ifdef DEVELOPMENT + if (pView && !pViewD3D11) LOG_RESOURCE_BINDING_ERROR("resource", pView, Attribs, ArrayIndex, "", "Incorect resource type: buffer view is expected."); - if(pViewD3D11 && !dbgVerifyViewType("buffer view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, BUFFER_VIEW_UNORDERED_ACCESS, m_ParentResLayout.GetShaderName()) ) + if (pViewD3D11 && !dbgVerifyViewType("buffer view", pViewD3D11.RawPtr(), Attribs, ArrayIndex, BUFFER_VIEW_UNORDERED_ACCESS, m_ParentResLayout.GetShaderName()) ) pViewD3D11.Release(); - if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) + if (Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) { - auto &CachedUAV = pResourceCache->GetUAV(Attribs.BindPoint + ArrayIndex); + auto &CachedUAV = ResourceCache.GetUAV(Attribs.BindPoint + ArrayIndex); if( CachedUAV.pView != nullptr && CachedUAV.pView != pViewD3D11) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null buffer UAV 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 may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null buffer UAV 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 may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic." ); } } #endif - pResourceCache->SetBufUAV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); + ResourceCache.SetBufUAV(Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); } -bool ShaderResourceLayoutD3D11::TexAndSamplerBindInfo::IsBound(Uint32 ArrayIndex) +bool ShaderResourceLayoutD3D11::TexSRVBindInfo::IsBound(Uint32 ArrayIndex)const { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; - VERIFY(pResourceCache, "Resource cache is null"); + auto* pResourceCache = m_ParentResLayout.m_pResourceCache; + VERIFY(pResourceCache != nullptr, "Resource cache is null"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); return pResourceCache->IsSRVBound(Attribs.BindPoint + ArrayIndex, true); } -bool ShaderResourceLayoutD3D11::BuffSRVBindInfo::IsBound(Uint32 ArrayIndex) +bool ShaderResourceLayoutD3D11::BuffSRVBindInfo::IsBound(Uint32 ArrayIndex)const { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; + auto* pResourceCache = m_ParentResLayout.m_pResourceCache; VERIFY(pResourceCache, "Resource cache is null"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); return pResourceCache->IsSRVBound(Attribs.BindPoint + ArrayIndex, false); } -bool ShaderResourceLayoutD3D11::TexUAVBindInfo::IsBound(Uint32 ArrayIndex) +bool ShaderResourceLayoutD3D11::TexUAVBindInfo::IsBound(Uint32 ArrayIndex)const { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; + auto* pResourceCache = m_ParentResLayout.m_pResourceCache; VERIFY(pResourceCache, "Resource cache is null"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); return pResourceCache->IsUAVBound(Attribs.BindPoint + ArrayIndex, true); } -bool ShaderResourceLayoutD3D11::BuffUAVBindInfo::IsBound(Uint32 ArrayIndex) +bool ShaderResourceLayoutD3D11::BuffUAVBindInfo::IsBound(Uint32 ArrayIndex)const { - auto &pResourceCache = m_ParentResLayout.m_pResourceCache; + auto* pResourceCache = m_ParentResLayout.m_pResourceCache; VERIFY(pResourceCache, "Resource cache is null"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); return pResourceCache->IsUAVBound(Attribs.BindPoint + ArrayIndex, false); } +bool ShaderResourceLayoutD3D11::SamplerBindInfo::IsBound(Uint32 ArrayIndex)const +{ + auto* pResourceCache = m_ParentResLayout.m_pResourceCache; + VERIFY(pResourceCache, "Resource cache is null"); + VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + + return pResourceCache->IsSamplerBound(Attribs.BindPoint + ArrayIndex); +} + // Helper template class that facilitates binding CBs, SRVs, and UAVs class BindResourceHelper { public: - BindResourceHelper(IResourceMapping* pRM, Uint32 Fl, const ShaderResourceLayoutD3D11* pSRL) : - pResourceMapping(pRM), - Flags(Fl), - pShaderResLayout(pSRL) + BindResourceHelper(IResourceMapping& RM, Uint32 Fl) : + ResourceMapping(RM), + Flags(Fl) { - VERIFY(pResourceMapping != nullptr, "Resource mapping is null"); - VERIFY(pSRL != nullptr, "Shader resource layout is null"); } template @@ -679,19 +691,18 @@ public: for(Uint16 elem=0; elem < Res.Attribs.BindCount; ++elem) { if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS ) - Res.BindResource(nullptr, elem, pShaderResLayout); + Res.BindResource(nullptr, elem); if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(elem) ) return; const auto* VarName = Res.Attribs.Name; RefCntAutoPtr pRes; - VERIFY_EXPR(pResourceMapping != nullptr); - pResourceMapping->GetResource( VarName, &pRes, elem ); + ResourceMapping.GetResource( VarName, &pRes, elem ); if( pRes ) { // Call non-virtual function - Res.BindResource(pRes, elem, pShaderResLayout); + Res.BindResource(pRes, elem); } else { @@ -702,30 +713,29 @@ public: } private: - IResourceMapping* const pResourceMapping; - const Uint32 Flags; - const ShaderResourceLayoutD3D11 *pShaderResLayout; + IResourceMapping& ResourceMapping; + const Uint32 Flags; }; void ShaderResourceLayoutD3D11::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D11& dbgResourceCache ) { VERIFY(&dbgResourceCache == m_pResourceCache, "Resource cache does not match the cache provided at initialization"); - if( !pResourceMapping ) + if (pResourceMapping == nullptr) { LOG_ERROR_MESSAGE( "Failed to bind resources in shader \"", GetShaderName(), "\": resource mapping is null" ); return; } - BindResourceHelper BindResHelper(pResourceMapping, Flags, this); + BindResourceHelper BindResHelper(*pResourceMapping, Flags); HandleResources( - [&](ConstBuffBindInfo&cb) + [&](ConstBuffBindInfo& cb) { BindResHelper.Bind(cb); }, - [&](TexAndSamplerBindInfo& ts) + [&](TexSRVBindInfo& ts) { BindResHelper.Bind(ts); }, @@ -743,18 +753,18 @@ void ShaderResourceLayoutD3D11::BindResources( IResourceMapping* pResourceMappin [&](BuffUAVBindInfo& uav) { BindResHelper.Bind(uav); + }, + + [&](SamplerBindInfo& sam) + { + if (!m_pResources->IsUsingCombinedTextureSamplers()) + BindResHelper.Bind(sam); } ); } IShaderVariable* ShaderResourceLayoutD3D11::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 for (Uint32 cb = 0; cb < m_NumCBs; ++cb) if (strcmp(GetCB(cb).Attribs.Name, Name) == 0) return &GetCB(cb); @@ -770,7 +780,9 @@ IShaderVariable* ShaderResourceLayoutD3D11::GetShaderVariable(const Char* Name) for (Uint32 u = 0; u < m_NumBufUAVs; ++u) if (strcmp(GetBufUAV(u).Attribs.Name, Name) == 0 ) return &GetBufUAV(u); -#endif + for (Uint32 s = 0; s < m_NumSamplers; ++s) + if (strcmp(GetSampler(s).Attribs.Name, Name) == 0 ) + return &GetSampler(s); return nullptr; } @@ -785,7 +797,7 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base auto Offset = reinterpret_cast(&Variable) - reinterpret_cast(m_ResourceBuffer.get()); Uint32 Index = 0; - if (Offset < m_TexAndSamplersOffset) + if (Offset < m_TexSRVsOffset) { VERIFY(Offset % sizeof(ConstBuffBindInfo) == 0, "Offset is not multiple of sizeof(ConstBuffBindInfo)"); return Index + static_cast(Offset / sizeof(ConstBuffBindInfo)); @@ -795,8 +807,8 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base if (Offset < m_TexUAVsOffset) { - VERIFY( (Offset - m_TexAndSamplersOffset) % sizeof(TexAndSamplerBindInfo) == 0, "Offset is not multiple of sizeof(TexAndSamplerBindInfo)"); - return Index + static_cast((Offset - m_TexAndSamplersOffset) / sizeof(TexAndSamplerBindInfo)); + VERIFY( (Offset - m_TexSRVsOffset) % sizeof(TexSRVBindInfo) == 0, "Offset is not multiple of sizeof(TexSRVBindInfo)"); + return Index + static_cast((Offset - m_TexSRVsOffset) / sizeof(TexSRVBindInfo)); } else Index += m_NumTexSRVs; @@ -822,6 +834,14 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base VERIFY( (Offset - m_BuffSRVsOffset) % sizeof(BuffSRVBindInfo) == 0, "Offset is not multiple of sizeof(BuffSRVBindInfo)" ); return Index + static_cast((Offset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo)); } + else + Index += m_NumBufSRVs; + + if (Offset < static_cast(m_SamplerOffset + m_NumSamplers * sizeof(SamplerBindInfo))) + { + VERIFY( (Offset - m_SamplerOffset) % sizeof(SamplerBindInfo) == 0, "Offset is not multiple of sizeof(SamplerBindInfo)" ); + return Index + static_cast((Offset - m_SamplerOffset) / sizeof(SamplerBindInfo)); + } else { LOG_ERROR("Failed to get variable index. The variable ", &Variable, " does not belong to this shader resource layout"); @@ -860,10 +880,18 @@ IShaderVariable* ShaderResourceLayoutD3D11::GetShaderVariable( Uint32 Index ) if (Index < m_NumBufSRVs) return &GetBufSRV(Index); else + Index -= m_NumBufSRVs; + + if (!m_pResources->IsUsingCombinedTextureSamplers()) { - LOG_ERROR(Index + m_NumCBs + m_NumTexSRVs + m_NumTexUAVs + m_NumBufUAVs," is not a valid variable index"); + if (Index < m_NumSamplers) + return &GetSampler(Index); + else + Index -= m_NumSamplers; } + auto TotalResCount = GetTotalResourceCount(); + LOG_ERROR(Index + TotalResCount, " is not a valid variable index. Maximum allowed index: ", TotalResCount); return nullptr; } @@ -872,8 +900,8 @@ const Char* ShaderResourceLayoutD3D11::GetShaderName()const return m_pResources->GetShaderName(); } -#ifdef VERIFY_SHADER_BINDINGS -void ShaderResourceLayoutD3D11::dbgVerifyBindings()const +#ifdef DEVELOPMENT +void ShaderResourceLayoutD3D11::dvpVerifyBindings()const { #define LOG_MISSING_BINDING(VarType, Attrs, BindPt)\ @@ -891,46 +919,44 @@ do{ \ const_cast(this)->HandleResources( [&](const ConstBuffBindInfo&cb) { - for(auto BindPoint = cb.Attribs.BindPoint; BindPoint < cb.Attribs.BindPoint + cb.Attribs.BindCount; ++BindPoint) + for (auto BindPoint = cb.Attribs.BindPoint; BindPoint < cb.Attribs.BindPoint + cb.Attribs.BindCount; ++BindPoint) { - if( !m_pResourceCache->IsCBBound(BindPoint) ) + if (!m_pResourceCache->IsCBBound(BindPoint)) LOG_MISSING_BINDING("constant buffer", cb.Attribs, BindPoint); } }, - [&](const TexAndSamplerBindInfo& ts) + [&](const TexSRVBindInfo& ts) { - for(auto BindPoint = ts.Attribs.BindPoint; BindPoint < ts.Attribs.BindPoint + ts.Attribs.BindCount; ++BindPoint) + for (auto BindPoint = ts.Attribs.BindPoint; BindPoint < ts.Attribs.BindPoint + ts.Attribs.BindCount; ++BindPoint) { - if( !m_pResourceCache->IsSRVBound(BindPoint, true) ) + if (!m_pResourceCache->IsSRVBound(BindPoint, true)) LOG_MISSING_BINDING("texture", ts.Attribs, BindPoint); - if( ts.SamplerAttribs.IsValidBindPoint() ) + if (ts.ValidSamplerAssigned()) { - VERIFY_EXPR(ts.SamplerAttribs.BindCount == ts.Attribs.BindCount || ts.SamplerAttribs.BindCount == 1); - auto SamBindPoint = ts.SamplerAttribs.BindPoint + ((ts.SamplerAttribs.BindCount == 1) ? 0 : (BindPoint - ts.Attribs.BindPoint) ); - if(!m_pResourceCache->IsSamplerBound(SamBindPoint) ) - LOG_MISSING_BINDING("sampler", ts.SamplerAttribs, SamBindPoint); + const auto& Sampler = GetSampler(ts.SamplerIndex); + VERIFY_EXPR(Sampler.Attribs.BindCount == ts.Attribs.BindCount || Sampler.Attribs.BindCount == 1); // Verify that if single sampler is used for all texture array elements, all samplers set in the resource views are consistent - if (ts.Attribs.BindCount > 1 && ts.SamplerAttribs.BindCount == 1) + if (ts.Attribs.BindCount > 1 && Sampler.Attribs.BindCount == 1) { ShaderResourceCacheD3D11::CachedSampler *pCachedSamplers = nullptr; ID3D11SamplerState **ppCachedD3D11Samplers = nullptr; m_pResourceCache->GetSamplerArrays(pCachedSamplers, ppCachedD3D11Samplers); - VERIFY_EXPR(ts.SamplerAttribs.BindPoint < m_pResourceCache->GetSamplerCount()); - const auto &Sampler = pCachedSamplers[ts.SamplerAttribs.BindPoint]; + VERIFY_EXPR(Sampler.Attribs.BindPoint < m_pResourceCache->GetSamplerCount()); + const auto& CachedSampler = pCachedSamplers[Sampler.Attribs.BindPoint]; ShaderResourceCacheD3D11::CachedResource *pCachedResources = nullptr; ID3D11ShaderResourceView **ppCachedD3D11Resources = nullptr; m_pResourceCache->GetSRVArrays(pCachedResources, ppCachedD3D11Resources); VERIFY_EXPR(BindPoint < m_pResourceCache->GetSRVCount()); - auto &CachedResource = pCachedResources[BindPoint]; + auto& CachedResource = pCachedResources[BindPoint]; if(CachedResource.pView) { - auto *pTexView = CachedResource.pView.RawPtr(); - auto *pSampler = pTexView->GetSampler(); - if(pSampler != nullptr && pSampler != Sampler.pSampler.RawPtr()) + auto* pTexView = CachedResource.pView.RawPtr(); + auto* pSampler = pTexView->GetSampler(); + if(pSampler != nullptr && pSampler != CachedSampler.pSampler.RawPtr()) LOG_ERROR_MESSAGE( "All elements of texture array \"", ts.Attribs.Name, "\" in shader \"", GetShaderName(), "\" share the same sampler. However, the sampler set in view for element ", BindPoint - ts.Attribs.BindPoint, " does not match bound sampler. This may cause incorrect behavior on GL platform." ); } } @@ -940,29 +966,38 @@ do{ \ [&](const TexUAVBindInfo& uav) { - for(auto BindPoint = uav.Attribs.BindPoint; BindPoint < uav.Attribs.BindPoint + uav.Attribs.BindCount; ++BindPoint) + for (auto BindPoint = uav.Attribs.BindPoint; BindPoint < uav.Attribs.BindPoint + uav.Attribs.BindCount; ++BindPoint) { - if( !m_pResourceCache->IsUAVBound(BindPoint, true) ) + if (!m_pResourceCache->IsUAVBound(BindPoint, true)) LOG_MISSING_BINDING("texture UAV", uav.Attribs, BindPoint); } }, [&](const BuffSRVBindInfo& buf) { - for(auto BindPoint = buf.Attribs.BindPoint; BindPoint < buf.Attribs.BindPoint + buf.Attribs.BindCount; ++BindPoint) + for (auto BindPoint = buf.Attribs.BindPoint; BindPoint < buf.Attribs.BindPoint + buf.Attribs.BindCount; ++BindPoint) { - if( !m_pResourceCache->IsSRVBound(BindPoint, false) ) + if (!m_pResourceCache->IsSRVBound(BindPoint, false)) LOG_MISSING_BINDING("buffer", buf.Attribs, BindPoint); } }, [&](const BuffUAVBindInfo& uav) { - for(auto BindPoint = uav.Attribs.BindPoint; BindPoint < uav.Attribs.BindPoint + uav.Attribs.BindCount; ++BindPoint) + for (auto BindPoint = uav.Attribs.BindPoint; BindPoint < uav.Attribs.BindPoint + uav.Attribs.BindCount; ++BindPoint) { - if( !m_pResourceCache->IsUAVBound(BindPoint, false) ) + if (!m_pResourceCache->IsUAVBound(BindPoint, false)) LOG_MISSING_BINDING("buffer UAV", uav.Attribs, BindPoint); } + }, + + [&](const SamplerBindInfo& sam) + { + for (auto BindPoint = sam.Attribs.BindPoint; BindPoint < sam.Attribs.BindPoint + sam.Attribs.BindCount; ++BindPoint) + { + if (!m_pResourceCache->IsSamplerBound(BindPoint)) + LOG_MISSING_BINDING("sampler", sam.Attribs, BindPoint); + } } ); #undef LOG_MISSING_BINDING diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp index 562dc54d..b92c16fe 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp @@ -42,78 +42,60 @@ ShaderResourcesD3D11::ShaderResourcesD3D11(RenderDeviceD3D11Impl* pDeviceD3D11Im m_ShaderName(ShdrDesc.Name), m_StaticSamplers(nullptr, STDDeleterRawMem< void >(GetRawAllocator())) { - Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0; - LoadD3DShaderResources( - pShaderBytecode, - - [&](Uint32 NumCBs, Uint32 NumTexSRVs, Uint32 NumTexUAVs, Uint32 NumBufSRVs, Uint32 NumBufUAVs, Uint32 NumSamplers, size_t ResourceNamesPoolSize) - { - Initialize(GetRawAllocator(), NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers, ResourceNamesPoolSize); - }, + class NewResourceHandler + { + public: + NewResourceHandler(ShaderResourcesD3D11& ResourcesD3D11) : + Res(ResourcesD3D11) + {} - [&](const D3DShaderResourceAttribs& CBAttribs) + void OnNewCB(const D3DShaderResourceAttribs& CBAttribs) { VERIFY( CBAttribs.BindPoint + CBAttribs.BindCount-1 <= MaxAllowedBindPoint, "CB bind point exceeds supported range" ); - m_MaxCBBindPoint = std::max(m_MaxCBBindPoint, static_cast(CBAttribs.BindPoint + CBAttribs.BindCount-1)); - - new (&GetCB(CurrCB++)) D3DShaderResourceAttribs(m_ResourceNames, CBAttribs); - }, + Res.m_MaxCBBindPoint = std::max(Res.m_MaxCBBindPoint, static_cast(CBAttribs.BindPoint + CBAttribs.BindCount-1)); + } - [&](const D3DShaderResourceAttribs& TexUAV) + void OnNewTexUAV (const D3DShaderResourceAttribs& TexUAV) { VERIFY( TexUAV.BindPoint + TexUAV.BindCount-1 <= MaxAllowedBindPoint, "Tex UAV bind point exceeds supported range" ); - m_MaxUAVBindPoint = std::max(m_MaxUAVBindPoint, static_cast(TexUAV.BindPoint + TexUAV.BindCount-1)); - - new (&GetTexUAV(CurrTexUAV++)) D3DShaderResourceAttribs(m_ResourceNames, TexUAV); - }, + Res.m_MaxUAVBindPoint = std::max(Res.m_MaxUAVBindPoint, static_cast(TexUAV.BindPoint + TexUAV.BindCount-1)); + } - [&](const D3DShaderResourceAttribs& BuffUAV) + void OnNewBuffUAV(const D3DShaderResourceAttribs& BuffUAV) { VERIFY( BuffUAV.BindPoint + BuffUAV.BindCount-1 <= MaxAllowedBindPoint, "Buff UAV bind point exceeds supported range" ); - m_MaxUAVBindPoint = std::max(m_MaxUAVBindPoint, static_cast(BuffUAV.BindPoint + BuffUAV.BindCount-1)); - - new (&GetBufUAV(CurrBufUAV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffUAV); - }, + Res.m_MaxUAVBindPoint = std::max(Res.m_MaxUAVBindPoint, static_cast(BuffUAV.BindPoint + BuffUAV.BindCount-1)); + } - [&](const D3DShaderResourceAttribs& BuffSRV) + void OnNewBuffSRV(const D3DShaderResourceAttribs& BuffSRV) { VERIFY( BuffSRV.BindPoint + BuffSRV.BindCount-1 <= MaxAllowedBindPoint, "Buff SRV bind point exceeds supported range" ); - m_MaxSRVBindPoint = std::max(m_MaxSRVBindPoint, static_cast(BuffSRV.BindPoint + BuffSRV.BindCount-1)); - - new (&GetBufSRV(CurrBufSRV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffSRV); - }, + Res.m_MaxSRVBindPoint = std::max(Res.m_MaxSRVBindPoint, static_cast(BuffSRV.BindPoint + BuffSRV.BindCount-1)); + } - [&](const D3DShaderResourceAttribs& SamplerAttribs) + void OnNewSampler(const D3DShaderResourceAttribs& SamplerAttribs) { VERIFY( SamplerAttribs.BindPoint + SamplerAttribs.BindCount-1 <= MaxAllowedBindPoint, "Sampler bind point exceeds supported range" ); - m_MaxSamplerBindPoint = std::max(m_MaxSamplerBindPoint, static_cast(SamplerAttribs.BindPoint + SamplerAttribs.BindCount-1)); - m_NumStaticSamplers += SamplerAttribs.IsStaticSampler() ? 1 : 0; - - new (&GetSampler(CurrSampler++)) D3DShaderResourceAttribs(m_ResourceNames, SamplerAttribs); - }, - - [&](const D3DShaderResourceAttribs& TexAttribs) + Res.m_MaxSamplerBindPoint = std::max(Res.m_MaxSamplerBindPoint, static_cast(SamplerAttribs.BindPoint + SamplerAttribs.BindCount-1)); + Res.m_NumStaticSamplers += SamplerAttribs.IsStaticSampler() ? 1 : 0; + } + + void OnNewTexSRV(const D3DShaderResourceAttribs& TexAttribs) { - VERIFY(CurrSampler == GetNumSamplers(), "All samplers must be initialized before texture SRVs" ); - VERIFY( TexAttribs.BindPoint + TexAttribs.BindCount-1 <= MaxAllowedBindPoint, "Tex SRV bind point exceeds supported range" ); - m_MaxSRVBindPoint = std::max(m_MaxSRVBindPoint, static_cast(TexAttribs.BindPoint + TexAttribs.BindCount-1)); + Res.m_MaxSRVBindPoint = std::max(Res.m_MaxSRVBindPoint, static_cast(TexAttribs.BindPoint + TexAttribs.BindCount-1)); + } - auto SamplerId = CombinedSamplerSuffix != nullptr ? FindAssignedSamplerId(TexAttribs, CombinedSamplerSuffix) : D3DShaderResourceAttribs::InvalidSamplerId; - new (&GetTexSRV(CurrTexSRV++)) D3DShaderResourceAttribs(m_ResourceNames, TexAttribs, SamplerId); - }, + private: + ShaderResourcesD3D11& Res; + }; + Initialize( + pShaderBytecode, + NewResourceHandler{*this}, ShdrDesc, CombinedSamplerSuffix); - VERIFY_EXPR(m_ResourceNames.GetRemainingSize() == 0); - VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called"); - VERIFY(CurrTexSRV == GetNumTexSRV(), "Not all Tex SRVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrTexUAV == GetNumTexUAV(), "Not all Tex UAVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrBufSRV == GetNumBufSRV(), "Not all Buf SRVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrBufUAV == GetNumBufUAV(), "Not all Buf UAVs are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrSampler == GetNumSamplers(), "Not all Samplers are initialized, which will result in a crash when ~D3DShaderResourceAttribs() is called" ); - // Create static samplers if (m_NumStaticSamplers > 0) { @@ -134,7 +116,7 @@ ShaderResourcesD3D11::ShaderResourcesD3D11(RenderDeviceD3D11Impl* pDeviceD3D11Im for (; ssd < ShdrDesc.NumStaticSamplers; ++ssd) { const auto& StaticSamplerDesc = ShdrDesc.StaticSamplers[ssd]; - if (StrCmpSuff(Sam.Name, StaticSamplerDesc.TextureName, CombinedSamplerSuffix)) + if (StrCmpSuff(Sam.Name, StaticSamplerDesc.SamplerOrTextureName, CombinedSamplerSuffix)) { auto &StaticSamplerAttrs = GetStaticSampler(CurrStaticSam++); StaticSamplerAttrs.first = &Sam; @@ -168,7 +150,7 @@ void ShaderResourcesD3D11::InitStaticSamplers(ShaderResourceCacheD3D11 &Resource } } -#ifdef VERIFY_SHADER_BINDINGS +#ifdef DEVELOPMENT static String DbgMakeResourceName(const D3DShaderResourceAttribs &Attr, Uint32 BindPoint) { VERIFY( BindPoint >= (Uint32)Attr.BindPoint && BindPoint < (Uint32)Attr.BindPoint + Attr.BindCount, "Bind point is out of allowed range"); @@ -178,7 +160,7 @@ static String DbgMakeResourceName(const D3DShaderResourceAttribs &Attr, Uint32 B return String(Attr.Name) + '[' + std::to_string(BindPoint - Attr.BindPoint) + ']'; } -void ShaderResourcesD3D11::dbgVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[], +void ShaderResourcesD3D11::dvpVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[], ID3D11ShaderResourceView* CommittedD3D11SRVs[], ID3D11Resource* CommittedD3D11SRVResources[], ID3D11SamplerState* CommittedD3D11Samplers[], @@ -240,6 +222,37 @@ void ShaderResourcesD3D11::dbgVerifyCommittedResources(ID3D11Buffer* } }, + [&](const D3DShaderResourceAttribs &sam, Uint32) + { + for(auto BindPoint = sam.BindPoint; BindPoint < sam.BindPoint + sam.BindCount; ++BindPoint) + { + if (BindPoint >= ResourceCache.GetSamplerCount()) + { + LOG_ERROR_MESSAGE( "Unable to find sampler \"", DbgMakeResourceName(sam,BindPoint), "\" (slot ", BindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetSamplerCount()," Sampler slots only. This should never happen and may be the result of using wrong resource cache." ); + continue; + } + auto &Sam = CachedSamplers[BindPoint]; + if(Sam.pSampler == nullptr) + { + LOG_ERROR_MESSAGE( "Sampler \"", DbgMakeResourceName(sam,BindPoint), "\" (slot ", BindPoint, ") is not initialized in the resource cache." ); + continue; + } + VERIFY_EXPR(d3d11Samplers[BindPoint] == Sam.pSampler->GetD3D11SamplerState()); + + if(CommittedD3D11Samplers[BindPoint] == nullptr ) + { + LOG_ERROR_MESSAGE( "No D3D11 sampler committed to variable \"", DbgMakeResourceName(sam,BindPoint), "\" (slot ", BindPoint ,") in shader \"", GetShaderName(), "\"" ); + continue; + } + + if(CommittedD3D11Samplers[BindPoint] != d3d11Samplers[BindPoint]) + { + LOG_ERROR_MESSAGE( "D3D11 sampler committed to variable \"", DbgMakeResourceName(sam,BindPoint), "\" (slot ", BindPoint ,") in shader \"", GetShaderName(), "\" does not match the resource in the resource cache" ); + continue; + } + } + }, + [&](const D3DShaderResourceAttribs& tex, Uint32) { for(auto BindPoint = tex.BindPoint; BindPoint < tex.BindPoint + tex.BindCount; ++BindPoint) @@ -279,39 +292,11 @@ void ShaderResourcesD3D11::dbgVerifyCommittedResources(ID3D11Buffer* } } - if( tex.IsValidSampler() ) + if( tex.ValidSamplerAssigned() ) { const auto& SamAttribs = GetSampler( tex.GetSamplerId() ); VERIFY_EXPR(SamAttribs.IsValidBindPoint()); VERIFY_EXPR(SamAttribs.BindCount == 1 || SamAttribs.BindCount == tex.BindCount); - - for(auto SamBindPoint = SamAttribs.BindPoint; SamBindPoint < SamAttribs.BindPoint + SamAttribs.BindCount; ++SamBindPoint) - { - if (SamBindPoint >= ResourceCache.GetSamplerCount()) - { - LOG_ERROR_MESSAGE( "Unable to find sampler \"", DbgMakeResourceName(SamAttribs,SamBindPoint), "\" (slot ", SamBindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetSamplerCount()," Sampler slots only. This should never happen and may be the result of using wrong resource cache." ); - continue; - } - auto &Sam = CachedSamplers[SamBindPoint]; - if(Sam.pSampler == nullptr) - { - LOG_ERROR_MESSAGE( "Sampler \"", DbgMakeResourceName(SamAttribs,SamBindPoint), "\" (slot ", SamBindPoint, ") is not initialized in the resource cache." ); - continue; - } - VERIFY_EXPR(d3d11Samplers[SamBindPoint] == Sam.pSampler->GetD3D11SamplerState()); - - if(CommittedD3D11Samplers[SamBindPoint] == nullptr ) - { - LOG_ERROR_MESSAGE( "No D3D11 sampler committed to variable \"", DbgMakeResourceName(SamAttribs,SamBindPoint), "\" (slot ", SamBindPoint ,") in shader \"", GetShaderName(), "\"" ); - continue; - } - - if(CommittedD3D11Samplers[SamBindPoint] != d3d11Samplers[SamBindPoint]) - { - LOG_ERROR_MESSAGE( "D3D11 sampler committed to variable \"", DbgMakeResourceName(SamAttribs,SamBindPoint), "\" (slot ", SamBindPoint ,") in shader \"", GetShaderName(), "\" does not match the resource in the resource cache" ); - continue; - } - } } }, -- cgit v1.2.3