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 --- Graphics/GLSLTools/src/GLSLSourceBuilder.cpp | 4 + Graphics/GLSLTools/src/SPIRVShaderResources.cpp | 4 +- Graphics/GraphicsEngine/include/ShaderBase.h | 6 +- Graphics/GraphicsEngine/interface/Shader.h | 29 +- .../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 +++--- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 2 +- .../GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp | 2 +- .../src/ShaderResourceLayoutD3D12.cpp | 14 +- .../src/ShaderResourcesD3D12.cpp | 67 +-- .../include/D3DShaderResourceLoader.h | 36 +- .../include/ShaderResources.h | 293 ++++++++--- .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 78 +-- .../src/GLProgramResources.cpp | 2 +- 19 files changed, 810 insertions(+), 613 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp b/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp index d08eafb8..b8c4a95d 100644 --- a/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp +++ b/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp @@ -230,6 +230,10 @@ String BuildGLSLSourceString(const ShaderCreationAttribs& CreationAttribs, Targe if (CreationAttribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL) { + if (!CreationAttribs.UseCombinedTextureSamplers) + { + LOG_ERROR_AND_THROW("Combined texture samplers are required to convert HLSL source to GLSL"); + } // Convert HLSL to GLSL const auto &Converter = HLSL2GLSLConverterImpl::GetInstance(); HLSL2GLSLConverterImpl::ConversionAttribs Attribs; diff --git a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp index eda4a18f..45a63b07 100644 --- a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp +++ b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp @@ -80,7 +80,7 @@ static Int32 FindStaticSampler(const ShaderDesc& shaderDesc, const std::string& for(Uint32 s=0; s < shaderDesc.NumStaticSamplers; ++s) { const auto& StSam = shaderDesc.StaticSamplers[s]; - if(SamplerName.compare(StSam.TextureName) == 0) + if (SamplerName.compare(StSam.SamplerOrTextureName) == 0) return s; } @@ -282,7 +282,7 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, for (Uint32 s = 0; s < shaderDesc.NumStaticSamplers; ++s) { bool SamplerFound = false; - const auto *SamName = shaderDesc.StaticSamplers[s].TextureName; + const auto* SamName = shaderDesc.StaticSamplers[s].SamplerOrTextureName; for (Uint32 i = 0; i < GetNumSmplImgs(); ++i) { const auto &SmplImg = GetSmplImg(i); diff --git a/Graphics/GraphicsEngine/include/ShaderBase.h b/Graphics/GraphicsEngine/include/ShaderBase.h index 9b2d634b..de772250 100644 --- a/Graphics/GraphicsEngine/include/ShaderBase.h +++ b/Graphics/GraphicsEngine/include/ShaderBase.h @@ -205,9 +205,9 @@ public: for (Uint32 s = 0; s < this->m_Desc.NumStaticSamplers; ++s, ++Str) { m_StaticSamplers[s] = this->m_Desc.StaticSamplers[s]; - VERIFY(m_StaticSamplers[s].TextureName != nullptr, "Static sampler texture name not provided"); - *Str = m_StaticSamplers[s].TextureName; - m_StaticSamplers[s].TextureName = Str->c_str(); + VERIFY(m_StaticSamplers[s].SamplerOrTextureName != nullptr, "Static sampler or texture name is not provided"); + *Str = m_StaticSamplers[s].SamplerOrTextureName; + m_StaticSamplers[s].SamplerOrTextureName = Str->c_str(); #ifdef DEVELOPMENT const auto &BorderColor = m_StaticSamplers[s].Desc.BorderColor; if( !( (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) || diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index 06914040..01d7155b 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -135,16 +135,17 @@ struct ShaderVariableDesc /// Static sampler description struct StaticSamplerDesc { - /// Name of the texture variable that static sampler will be assigned to - const Char* TextureName = nullptr; + /// The name of the sampler itself or the name of the texture variable that + /// this static sampler is assigned to if combined texture samplers are used. + const Char* SamplerOrTextureName = nullptr; /// Sampler description SamplerDesc Desc; - StaticSamplerDesc(){}; - StaticSamplerDesc(const Char* _TexName, const SamplerDesc &_Desc) : - TextureName(_TexName), - Desc(_Desc) + StaticSamplerDesc(){} + StaticSamplerDesc(const Char* _SamplerOrTextureName, const SamplerDesc& _Desc) : + SamplerOrTextureName(_SamplerOrTextureName), + Desc (_Desc) {} }; @@ -256,9 +257,19 @@ struct ShaderCreationAttribs /// This member is ignored if ByteCode is not null const ShaderMacro *Macros = nullptr; - /// Defines the suffix added to the texture variable name to get corresponding - /// sampler name. For example, for default value "_sampler", a texture named - /// "tex" will be combined with sampler named "tex_sampler". + /// If set to true, textures will be combined with texture samplers. + /// The CombinedSamplerSuffix member defines the suffix added to the texture variable + /// name to get corresponding sampler name. When using combined samplers, + /// the sampler assigned to the shader resource view is automatically set when + /// the view is bound. Otherwise samplers need to be explicitly set similar to other + /// shader variables. + bool UseCombinedTextureSamplers = false; + + /// If UseCombinedTextureSamplers is true, defines the suffix added to the + /// texture variable name to get corresponding sampler name. For example, + /// for default value "_sampler", a texture named "tex" will be combined + /// with sampler named "tex_sampler". + /// If UseCombinedTextureSamplers is false, this member is ignored. const Char* CombinedSamplerSuffix = "_sampler"; /// Shader description. See Diligent::ShaderDesc. 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; - } - } } }, diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index c172ea95..565fc958 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -262,7 +262,7 @@ void RootSignature::InitStaticSampler(SHADER_TYPE ShaderType, const String& Text for (auto& StSmplr : m_StaticSamplers) { if (StSmplr.ShaderVisibility == ShaderVisibility && - TextureName.compare(StSmplr.SamplerDesc.TextureName) == 0) + TextureName.compare(StSmplr.SamplerDesc.SamplerOrTextureName) == 0) { StSmplr.ShaderRegister = SamplerAttribs.BindPoint; StSmplr.ArraySize = SamplerAttribs.BindCount; diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp index 0c98369c..9169230b 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp @@ -45,7 +45,7 @@ ShaderD3D12Impl::ShaderD3D12Impl(IReferenceCounters* pRefCounters, // Load shader resources auto& Allocator = GetRawAllocator(); auto* pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", sizeof(ShaderResourcesD3D12)); - auto* pResources = new (pRawMem) ShaderResourcesD3D12(m_pShaderByteCode, m_Desc, ShaderCreationAttribs.CombinedSamplerSuffix); + auto* pResources = new (pRawMem) ShaderResourcesD3D12(m_pShaderByteCode, m_Desc, ShaderCreationAttribs.UseCombinedTextureSamplers ? ShaderCreationAttribs.CombinedSamplerSuffix : nullptr); m_pShaderResources.reset(pResources, STDDeleterRawMem(Allocator)); // Clone only static resources that will be set directly in the shader diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 9c48cb76..708d971b 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -137,12 +137,17 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* VERIFY_EXPR(CB.IsAllowedType(AllowedTypeBits)); ++CbvSrvUavCount[CB.GetVariableType()]; }, + [&](const D3DShaderResourceAttribs& Sam, Uint32) + { + VERIFY_EXPR(Sam.IsAllowedType(AllowedTypeBits)); + + }, [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { VERIFY_EXPR(TexSRV.IsAllowedType(AllowedTypeBits)); auto VarType = TexSRV.GetVariableType(); ++CbvSrvUavCount[VarType]; - if(TexSRV.IsValidSampler()) + if(TexSRV.ValidSamplerAssigned()) { auto SamplerId = TexSRV.GetSamplerId(); const auto& SamplerAttribs = m_pResources->GetSampler(SamplerId); @@ -220,13 +225,18 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* VERIFY_EXPR( CB.IsAllowedType(AllowedTypeBits) ); AddResource(CB, CachedResourceType::CBV); }, + [&](const D3DShaderResourceAttribs& Sam, Uint32) + { + VERIFY_EXPR( Sam.IsAllowedType(AllowedTypeBits) ); + + }, [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { VERIFY_EXPR(TexSRV.IsAllowedType(AllowedTypeBits) ); auto VarType = TexSRV.GetVariableType(); Uint32 SamplerId = D3D12Resource::InvalidSamplerId; - if(TexSRV.IsValidSampler()) + if(TexSRV.ValidSamplerAssigned()) { const auto& SrcSamplerAttribs = m_pResources->GetSampler(TexSRV.GetSamplerId()); VERIFY(SrcSamplerAttribs.GetVariableType() == VarType, "Inconsistent texture and sampler variable types" ); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp index d61668bf..8922d379 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp @@ -37,61 +37,22 @@ namespace Diligent ShaderResourcesD3D12::ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, const ShaderDesc& ShdrDesc, const char* CombinedSamplerSuffix) : ShaderResources(ShdrDesc.ShaderType) { - Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0; - LoadD3DShaderResources( + class NewResourceHandler + { + public: + void OnNewCB (const D3DShaderResourceAttribs& CBAttribs) {} + void OnNewTexUAV (const D3DShaderResourceAttribs& TexUAV) {} + void OnNewBuffUAV(const D3DShaderResourceAttribs& BuffUAV) {} + void OnNewBuffSRV(const D3DShaderResourceAttribs& BuffSRV) {} + void OnNewSampler(const D3DShaderResourceAttribs& SamplerAttribs){} + void OnNewTexSRV (const D3DShaderResourceAttribs& TexAttribs) {} + }; + Initialize( 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); - }, - - [&](const D3DShaderResourceAttribs& CBAttribs) - { - new (&GetCB(CurrCB++)) D3DShaderResourceAttribs(m_ResourceNames, CBAttribs); - }, - - [&](const D3DShaderResourceAttribs& TexUAV) - { - new (&GetTexUAV(CurrTexUAV++)) D3DShaderResourceAttribs(m_ResourceNames, TexUAV); - }, - - [&](const D3DShaderResourceAttribs& BuffUAV) - { - new (&GetBufUAV(CurrBufUAV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffUAV); - }, - - [&](const D3DShaderResourceAttribs& BuffSRV) - { - new (&GetBufSRV(CurrBufSRV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffSRV); - }, - - [&](const D3DShaderResourceAttribs& SamplerAttribs) - { - new (&GetSampler(CurrSampler++)) D3DShaderResourceAttribs(m_ResourceNames, SamplerAttribs); - }, - - [&](const D3DShaderResourceAttribs& TexAttribs) - { - VERIFY(CurrSampler == GetNumSamplers(), "All samplers must be initialized before texture SRVs" ); - - auto SamplerId = - CombinedSamplerSuffix != nullptr ? - FindAssignedSamplerId(TexAttribs, CombinedSamplerSuffix) : - D3DShaderResourceAttribs::InvalidSamplerId; - new (&GetTexSRV(CurrTexSRV++)) D3DShaderResourceAttribs(m_ResourceNames, TexAttribs, SamplerId); - }, - + NewResourceHandler{}, 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" ); + CombinedSamplerSuffix + ); } } diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h index 75f880c0..1a256bce 100644 --- a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h +++ b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h @@ -70,6 +70,8 @@ namespace Diligent Resources.reserve(shaderDesc.BoundResources); std::unordered_set ResourceNamesTmpPool; + const bool UseCombinedTextureSamplers = SamplerSuffix != nullptr; + Uint32 NumCBs = 0, NumTexSRVs = 0, NumTexUAVs = 0, NumBufSRVs = 0, NumBufUAVs = 0, NumSamplers = 0; size_t ResourceNamesPoolSize = 0; // Number of resources to skip (used for array resources) @@ -151,17 +153,17 @@ namespace Diligent { for (Uint32 s = 0; s < ShdrDesc.NumStaticSamplers; ++s) { - if( StrCmpSuff(Name.c_str(), ShdrDesc.StaticSamplers[s].TextureName, SamplerSuffix) ) + if (StrCmpSuff(Name.c_str(), ShdrDesc.StaticSamplers[s].SamplerOrTextureName, SamplerSuffix)) { IsStaticSampler = true; break; } } - // Use texture name to derive sampler type + // Use texture or sampler name to derive sampler type VarType = GetShaderVariableType(ShdrDesc.DefaultVariableType, ShdrDesc.VariableDesc, ShdrDesc.NumVariables, - [&](const char *TexName) + [&](const char* VarName) { - return StrCmpSuff(Name.c_str(), TexName, SamplerSuffix); + return StrCmpSuff(Name.c_str(), VarName, SamplerSuffix); }); } else @@ -201,7 +203,7 @@ namespace Diligent } -#ifdef _DEBUG +#ifdef DEVELOPMENT if(ShdrDesc.NumVariables != 0 || ShdrDesc.NumStaticSamplers != 0 ) { for (Uint32 v = 0; v < ShdrDesc.NumVariables; ++v) @@ -211,8 +213,9 @@ namespace Diligent for (const auto& Res : Resources) { - // Skip samplers as they are not handled as independent variables - if (Res.GetInputType() != D3D_SIT_SAMPLER && strcmp(Res.Name, VarName) == 0) + // Skip samplers if combined texture samplers are used as + // in this case they are not treated as independent variables + if ( !(UseCombinedTextureSamplers && Res.GetInputType() == D3D_SIT_SAMPLER) && strcmp(Res.Name, VarName) == 0) { VariableFound = true; break; @@ -226,20 +229,25 @@ namespace Diligent for (Uint32 s = 0; s < ShdrDesc.NumStaticSamplers; ++s) { - bool TextureFound = false; - const auto *TexName = ShdrDesc.StaticSamplers[s].TextureName; + const auto* TexOrSamName = ShdrDesc.StaticSamplers[s].SamplerOrTextureName; + bool TextureOrSamplerFound = false; for (const auto& Res : Resources) { - if ( Res.GetInputType() == D3D_SIT_TEXTURE && Res.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER && strcmp(Res.Name, TexName) == 0) + if( UseCombinedTextureSamplers && Res.GetInputType() == D3D_SIT_TEXTURE && Res.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER || + !UseCombinedTextureSamplers && Res.GetInputType() == D3D_SIT_SAMPLER) { - TextureFound = true; - break; + TextureOrSamplerFound = (strcmp(Res.Name, TexOrSamName) == 0); + if (TextureOrSamplerFound) + break; } } - if(!TextureFound) + if (!TextureOrSamplerFound) { - LOG_WARNING_MESSAGE("Static sampler specifies a texture \"", TexName, "\" that is not found in shader \"", ShdrDesc.Name, '\"'); + if (UseCombinedTextureSamplers) + LOG_WARNING_MESSAGE("Static sampler specifies a texture '", TexOrSamName, "' that is not found in shader '", ShdrDesc.Name, '\''); + else + LOG_WARNING_MESSAGE("Static sampler '", TexOrSamName, "' is not found in shader '", ShdrDesc.Name, '\''); } } } diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h index b49069dd..9c2278d4 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h @@ -42,13 +42,14 @@ // Nsam - number of samplers // // -// If texture SRV is assigned a sampler, it is referenced through SamplerId: +// If texture SRV is assigned a sampler, it is cross-referenced through SamplerOrTexSRVId: // -// _________________________SamplerId_______________________ +// _____________________SamplerOrTexSRVId___________________ // | | // | V // | CBs | ... TexSRV[n] ... | TexUAVs | BufSRVs | BufUAVs | Sam[0] ... Sam[SamplerId] ... | -// +// A | +// '---------------------SamplerOrTexSRVId-------------------' // #include @@ -71,11 +72,11 @@ inline bool IsAllowedType(SHADER_VARIABLE_TYPE VarType, Uint32 AllowedTypeBits)n inline Uint32 GetAllowedTypeBits(const SHADER_VARIABLE_TYPE *AllowedVarTypes, Uint32 NumAllowedTypes)noexcept { - if(AllowedVarTypes == nullptr) + if (AllowedVarTypes == nullptr) return 0xFFFFFFFF; Uint32 AllowedTypeBits = 0; - for(Uint32 i=0; i < NumAllowedTypes; ++i) + for (Uint32 i=0; i < NumAllowedTypes; ++i) AllowedTypeBits |= 1 << AllowedVarTypes[i]; return AllowedTypeBits; } @@ -89,16 +90,16 @@ struct D3DShaderResourceAttribs const Uint16 BindCount; private: - // 4 3 4 20 1 - // bit | 0 1 2 3 | 4 5 6 | 7 8 9 10 | 11 12 ... 30 | 31 | - // | | | | | | - // | InputType | VariableType | SRV Dim | SamplerId | StaticSamplerFlag | + // 4 3 4 20 1 + // bit | 0 1 2 3 | 4 5 6 | 7 8 9 10 | 11 12 13 ... 30 | 31 | + // | | | | | | + // | InputType | VariableType | SRV Dim | SamplerOrTexSRVIdBits | StaticSamplerFlag | static constexpr const Uint32 ShaderInputTypeBits = 4; static constexpr const Uint32 VariableTypeBits = 3; static constexpr const Uint32 SRVDimBits = 4; - static constexpr const Uint32 SamplerIdBits = 20; + static constexpr const Uint32 SamplerOrTexSRVIdBits = 20; static constexpr const Uint32 StaticSamplerFlagBits = 1; - static_assert(ShaderInputTypeBits + VariableTypeBits + SRVDimBits + SamplerIdBits + StaticSamplerFlagBits == 32, "Attributes are better be packed into 32 bits"); + static_assert(ShaderInputTypeBits + VariableTypeBits + SRVDimBits + SamplerOrTexSRVIdBits + StaticSamplerFlagBits == 32, "Attributes are better be packed into 32 bits"); static_assert(D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER < (1 << ShaderInputTypeBits), "Not enough bits to represent D3D_SHADER_INPUT_TYPE"); static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES < (1 << VariableTypeBits), "Not enough bits to represent SHADER_VARIABLE_TYPE"); @@ -108,15 +109,16 @@ private: // There originally was a problem when the type of InputType was D3D_SHADER_INPUT_TYPE: // the value of D3D_SIT_UAV_RWBYTEADDRESS (8) was interpreted as -8 (as the underlying enum type // is signed) causing errors - const Uint32 InputType : ShaderInputTypeBits; // Max value: D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER == 11 - const Uint32 VariableType : VariableTypeBits; // Max value: SHADER_VARIABLE_TYPE_DYNAMIC == 2 - const Uint32 SRVDimension : SRVDimBits; // Max value: D3D_SRV_DIMENSION_BUFFEREX == 11 - const Uint32 SamplerId : SamplerIdBits; // Max value: 1048575 - const Uint32 StaticSamplerFlag : StaticSamplerFlagBits; // Needs to be Uint32, otherwise sizeof(D3DShaderResourceAttribs)==24 + const Uint32 InputType : ShaderInputTypeBits; // Max value: D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER == 11 + const Uint32 VariableType : VariableTypeBits; // Max value: SHADER_VARIABLE_TYPE_DYNAMIC == 2 + const Uint32 SRVDimension : SRVDimBits; // Max value: D3D_SRV_DIMENSION_BUFFEREX == 11 + Uint32 SamplerOrTexSRVId : SamplerOrTexSRVIdBits; // Max value: 1048575 + const Uint32 StaticSamplerFlag : StaticSamplerFlagBits; // Needs to be Uint32, otherwise sizeof(D3DShaderResourceAttribs)==24 // (https://stackoverflow.com/questions/308364/c-bitfield-packing-with-bools) public: - static constexpr const Uint32 InvalidSamplerId = (1 << SamplerIdBits) - 1; + static constexpr const Uint32 InvalidSamplerId = (1 << SamplerOrTexSRVIdBits) - 1; + static constexpr const Uint32 InvalidTexSRVId = (1 << SamplerOrTexSRVIdBits) - 1; static constexpr const Uint16 InvalidBindPoint = std::numeric_limits::max(); static constexpr const Uint16 MaxBindPoint = InvalidBindPoint - 1; static constexpr const Uint16 MaxBindCount = std::numeric_limits::max(); @@ -130,31 +132,32 @@ public: D3D_SRV_DIMENSION _SRVDimension, Uint32 _SamplerId, bool _IsStaticSampler)noexcept : - Name (_Name), - BindPoint (static_cast (_BindPoint)), - BindCount (static_cast (_BindCount)), - InputType (static_cast (_InputType)), - VariableType (static_cast(_VariableType)), - SRVDimension (static_cast(_SRVDimension)), - SamplerId (_SamplerId), - StaticSamplerFlag(_IsStaticSampler ? 1 : 0) + Name (_Name), + BindPoint (static_cast (_BindPoint)), + BindCount (static_cast (_BindCount)), + InputType (static_cast (_InputType)), + VariableType (static_cast(_VariableType)), + SRVDimension (static_cast(_SRVDimension)), + SamplerOrTexSRVId (_SamplerId), + StaticSamplerFlag (_IsStaticSampler ? 1 : 0) { +#ifdef _DEBUG VERIFY(_BindPoint <= MaxBindPoint || _BindPoint == InvalidBindPoint, "Bind Point is out of allowed range"); VERIFY(_BindCount <= MaxBindCount, "Bind Count is out of allowed range"); - VERIFY(_InputType < (1 << ShaderInputTypeBits), "Shader input type is out of expected range"); - VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type is out of expected range"); - VERIFY(_SRVDimension < (1 << SRVDimBits), "SRV dimensions is out of expected range"); - VERIFY(_SamplerId < (1 << SamplerIdBits), "SamplerId is out of representable range"); -#ifdef _DEBUG + VERIFY(_InputType < (1 << ShaderInputTypeBits), "Shader input type is out of expected range"); + VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type is out of expected range"); + VERIFY(_SRVDimension < (1 << SRVDimBits), "SRV dimensions is out of expected range"); + VERIFY(_SamplerId < (1 << SamplerOrTexSRVIdBits), "SamplerOrTexSRVId is out of representable range"); + if (_InputType==D3D_SIT_SAMPLER) VERIFY_EXPR(IsStaticSampler() == _IsStaticSampler); else - VERIFY(!_IsStaticSampler, "Only samplers can be marked as static"); + VERIFY(!_IsStaticSampler, "Only samplers can be labeled as static"); - if (_InputType == D3D_SIT_TEXTURE) - VERIFY_EXPR(SamplerId == _SamplerId); + if (_InputType == D3D_SIT_TEXTURE && _SRVDimension != D3D_SRV_DIMENSION_BUFFER) + VERIFY_EXPR(GetSamplerId() == _SamplerId); else - VERIFY(SamplerId == InvalidSamplerId, "Only textures can be assigned a valid texture sampler"); + VERIFY(_SamplerId == InvalidSamplerId, "Only texture SRV can be assigned a valid texture sampler"); if (_IsStaticSampler) VERIFY( _InputType == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" ); @@ -174,7 +177,7 @@ public: false } { - VERIFY(InputType == D3D_SIT_TEXTURE, "Only textures can be assigned a texture sampler"); + VERIFY(GetInputType() == D3D_SIT_TEXTURE && GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER, "Only texture SRV can be assigned a texture sampler"); } D3DShaderResourceAttribs(StringPool& NamesPool, const D3DShaderResourceAttribs& rhs)noexcept : @@ -186,7 +189,7 @@ public: rhs.GetInputType(), rhs.GetVariableType(), rhs.GetSRVDimension(), - rhs.SamplerId, + rhs.SamplerOrTexSRVId, rhs.StaticSamplerFlag !=0 ? true : false } { @@ -214,21 +217,39 @@ public: Uint32 GetSamplerId()const { - VERIFY( InputType == D3D_SIT_TEXTURE, "Invalid input type: D3D_SIT_TEXTURE is expected" ); - return SamplerId; + VERIFY(GetInputType() == D3D_SIT_TEXTURE && GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER, "Invalid input type: D3D_SIT_TEXTURE is expected" ); + return SamplerOrTexSRVId; + } + + void SetTexSRVId(Uint32 TexSRVId) + { + VERIFY(GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" ); + VERIFY(TexSRVId < (1 << SamplerOrTexSRVIdBits), "TexSRVId (", TexSRVId, ") is out of representable range"); + SamplerOrTexSRVId = TexSRVId; + } + + Uint32 GetTexSRVId()const + { + VERIFY(GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" ); + return SamplerOrTexSRVId; } bool IsStaticSampler()const { - VERIFY( InputType == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" ); + VERIFY(GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" ); return StaticSamplerFlag != 0; } - bool IsValidSampler()const + bool ValidSamplerAssigned()const { return GetSamplerId() != InvalidSamplerId; } + bool ValidTexSRVAssigned()const + { + return GetTexSRVId() != InvalidTexSRVId; + } + bool IsValidBindPoint()const { return BindPoint != InvalidBindPoint; @@ -245,18 +266,18 @@ public: bool IsCompatibleWith(const D3DShaderResourceAttribs& Attribs)const { - return BindPoint == Attribs.BindPoint && - BindCount == Attribs.BindCount && - InputType == Attribs.InputType && - VariableType == Attribs.VariableType && - SRVDimension == Attribs.SRVDimension && - SamplerId == Attribs.SamplerId && - StaticSamplerFlag == Attribs.StaticSamplerFlag; + return BindPoint == Attribs.BindPoint && + BindCount == Attribs.BindCount && + InputType == Attribs.InputType && + VariableType == Attribs.VariableType && + SRVDimension == Attribs.SRVDimension && + SamplerOrTexSRVId == Attribs.SamplerOrTexSRVId && + StaticSamplerFlag == Attribs.StaticSamplerFlag; } size_t GetHash()const { - return ComputeHash(BindPoint, BindCount, InputType, VariableType, SRVDimension, SamplerId, StaticSamplerFlag); + return ComputeHash(BindPoint, BindCount, InputType, VariableType, SRVDimension, SamplerOrTexSRVId, StaticSamplerFlag); } bool IsAllowedType(Uint32 AllowedTypeBits)const @@ -295,25 +316,32 @@ public: const D3DShaderResourceAttribs& GetSampler(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } - void CountResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes, Uint32 NumAllowedTypes, - Uint32& NumCBs, Uint32& NumTexSRVs, Uint32& NumTexUAVs, - Uint32& NumBufSRVs, Uint32& NumBufUAVs, Uint32& NumSamplers)const noexcept; + void CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumCBs, + Uint32& NumTexSRVs, + Uint32& NumTexUAVs, + Uint32& NumBufSRVs, + Uint32& NumBufUAVs, + Uint32& NumSamplers)const noexcept; SHADER_TYPE GetShaderType()const noexcept{return m_ShaderType;} - // Process only resources listed in AllowedVarTypes + // Processes only resources listed in AllowedVarTypes template - void ProcessResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes, - Uint32 NumAllowedTypes, - THandleCB HandleCB, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV)const + void ProcessResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + THandleCB HandleCB, + THandleSampler HandleSampler, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV)const { Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); @@ -324,6 +352,13 @@ public: HandleCB(CB, n); } + for(Uint32 n=0; n < GetNumSamplers(); ++n) + { + const auto& Sampler = GetSampler(n); + if( Sampler.IsAllowedType(AllowedTypeBits) ) + HandleSampler(Sampler, n); + } + for(Uint32 n=0; n < GetNumTexSRV(); ++n) { const auto &TexSRV = GetTexSRV(n); @@ -353,19 +388,21 @@ public: } } - bool IsCompatibleWith(const ShaderResources &Resources)const; - + bool IsCompatibleWith(const ShaderResources& Resources) const; + bool IsUsingCombinedTextureSamplers() const {return m_UseCombinedTextureSamplers;} + size_t GetHash()const; protected: - void Initialize(IMemoryAllocator& Allocator, - Uint32 NumCBs, - Uint32 NumTexSRVs, - Uint32 NumTexUAVs, - Uint32 NumBufSRVs, - Uint32 NumBufUAVs, - Uint32 NumSamplers, - size_t ResourceNamesPoolSize); + template + void Initialize(ID3DBlob* pShaderByteCode, + TNewResourceHandler NewResHandler, + const ShaderDesc& ShdrDesc, + const Char* SamplerSuffix); + __forceinline D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset)noexcept { @@ -388,29 +425,133 @@ protected: D3DShaderResourceAttribs& GetBufUAV (Uint32 n)noexcept{ return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } D3DShaderResourceAttribs& GetSampler(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } +private: + void AllocateMemory(IMemoryAllocator& Allocator, + Uint32 NumCBs, + Uint32 NumTexSRVs, + Uint32 NumTexUAVs, + Uint32 NumBufSRVs, + Uint32 NumBufUAVs, + Uint32 NumSamplers, + size_t ResourceNamesPoolSize); + Uint32 FindAssignedSamplerId(const D3DShaderResourceAttribs& TexSRV, const char* SamplerSuffix)const; -private: // Memory buffer that holds all resources as continuous chunk of memory: // | CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | Resource Names | std::unique_ptr< void, STDDeleterRawMem > m_MemoryBuffer; -protected: StringPool m_ResourceNames; -private: // Offsets in elements of D3DShaderResourceAttribs typedef Uint16 OffsetType; - OffsetType m_TexSRVOffset = 0; - OffsetType m_TexUAVOffset = 0; - OffsetType m_BufSRVOffset = 0; - OffsetType m_BufUAVOffset = 0; + OffsetType m_TexSRVOffset = 0; + OffsetType m_TexUAVOffset = 0; + OffsetType m_BufSRVOffset = 0; + OffsetType m_BufUAVOffset = 0; OffsetType m_SamplersOffset = 0; OffsetType m_TotalResources = 0; + bool m_UseCombinedTextureSamplers = false; + SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; }; + +template +void ShaderResources::Initialize(ID3DBlob* pShaderByteCode, + TNewResourceHandler NewResHandler, + const ShaderDesc& ShdrDesc, + const Char* CombinedSamplerSuffix) +{ + m_UseCombinedTextureSamplers = CombinedSamplerSuffix != nullptr; + + 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) + { + AllocateMemory(GetRawAllocator(), NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers, ResourceNamesPoolSize); + }, + + [&](const D3DShaderResourceAttribs& CBAttribs) + { + VERIFY_EXPR(CBAttribs.GetInputType() == D3D_SIT_CBUFFER); + auto* pNewCB = new (&GetCB(CurrCB++)) D3DShaderResourceAttribs(m_ResourceNames, CBAttribs); + NewResHandler.OnNewCB(*pNewCB); + }, + + [&](const D3DShaderResourceAttribs& TexUAV) + { + VERIFY_EXPR(TexUAV.GetInputType() == D3D_SIT_UAV_RWTYPED && TexUAV.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER); + auto* pNewTexUAV = new (&GetTexUAV(CurrTexUAV++)) D3DShaderResourceAttribs(m_ResourceNames, TexUAV); + NewResHandler.OnNewTexUAV(*pNewTexUAV); + }, + + [&](const D3DShaderResourceAttribs& BuffUAV) + { + VERIFY_EXPR(BuffUAV.GetInputType() == D3D_SIT_UAV_RWTYPED && BuffUAV.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER || BuffUAV.GetInputType() == D3D_SIT_UAV_RWSTRUCTURED || BuffUAV.GetInputType() == D3D_SIT_UAV_RWBYTEADDRESS); + auto* pNewBufUAV = new (&GetBufUAV(CurrBufUAV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffUAV); + NewResHandler.OnNewBuffUAV(*pNewBufUAV); + }, + + [&](const D3DShaderResourceAttribs& BuffSRV) + { + VERIFY_EXPR(BuffSRV.GetInputType() == D3D_SIT_TEXTURE && BuffSRV.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER || BuffSRV.GetInputType() == D3D_SIT_STRUCTURED || BuffSRV.GetInputType() == D3D_SIT_BYTEADDRESS); + auto* pNewBuffSRV = new (&GetBufSRV(CurrBufSRV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffSRV); + NewResHandler.OnNewBuffSRV(*pNewBuffSRV); + }, + + [&](const D3DShaderResourceAttribs& SamplerAttribs) + { + VERIFY_EXPR(SamplerAttribs.GetInputType() == D3D_SIT_SAMPLER); + auto* pNewSampler = new (&GetSampler(CurrSampler++)) D3DShaderResourceAttribs(m_ResourceNames, SamplerAttribs); + NewResHandler.OnNewSampler(*pNewSampler); + }, + + [&](const D3DShaderResourceAttribs& TexAttribs) + { + VERIFY_EXPR(TexAttribs.GetInputType() == D3D_SIT_TEXTURE && TexAttribs.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER); + VERIFY(CurrSampler == GetNumSamplers(), "All samplers must be initialized before texture SRVs" ); + + auto SamplerId = CombinedSamplerSuffix != nullptr ? FindAssignedSamplerId(TexAttribs, CombinedSamplerSuffix) : D3DShaderResourceAttribs::InvalidSamplerId; + auto* pNewTexSRV = new (&GetTexSRV(CurrTexSRV)) D3DShaderResourceAttribs(m_ResourceNames, TexAttribs, SamplerId); + if (SamplerId != D3DShaderResourceAttribs::InvalidSamplerId) + { + GetSampler(SamplerId).SetTexSRVId(CurrTexSRV); + } + ++CurrTexSRV; + NewResHandler.OnNewTexSRV(*pNewTexSRV); + }, + + ShdrDesc, + CombinedSamplerSuffix); + +#ifdef DEVELOPMENT + if (CombinedSamplerSuffix != nullptr) + { + for (Uint32 n=0; n < GetNumSamplers(); ++n) + { + const auto& Sampler = GetSampler(n); + if (!Sampler.ValidTexSRVAssigned()) + LOG_ERROR_MESSAGE("Shader '", ShdrDesc.Name, "' uses combined texture samplers, but sampler '", Sampler.Name, "' is not assigned to any texture"); + } + } +#endif + + VERIFY_EXPR(m_ResourceNames.GetRemainingSize() == 0); + VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called"); + VERIFY(CurrTexSRV == GetNumTexSRV(), "Not all Tex SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrTexUAV == GetNumTexUAV(), "Not all Tex UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrBufSRV == GetNumBufSRV(), "Not all Buf SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrBufUAV == GetNumBufUAV(), "Not all Buf UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrSampler == GetNumSamplers(), "Not all Samplers are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); +} + } namespace std diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 3ad2dc76..52fc96d9 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -51,14 +51,14 @@ ShaderResources::~ShaderResources() GetSampler(n).~D3DShaderResourceAttribs(); } -void ShaderResources::Initialize(IMemoryAllocator& Allocator, - Uint32 NumCBs, - Uint32 NumTexSRVs, - Uint32 NumTexUAVs, - Uint32 NumBufSRVs, - Uint32 NumBufUAVs, - Uint32 NumSamplers, - size_t ResourceNamesPoolSize) +void ShaderResources::AllocateMemory(IMemoryAllocator& Allocator, + Uint32 NumCBs, + Uint32 NumTexSRVs, + Uint32 NumTexUAVs, + Uint32 NumBufSRVs, + Uint32 NumBufUAVs, + Uint32 NumSamplers, + size_t ResourceNamesPoolSize) { const auto MaxOffset = static_cast(std::numeric_limits::max()); VERIFY(NumCBs <= MaxOffset, "Max offset exceeded"); @@ -102,17 +102,16 @@ ShaderResources::ShaderResources(SHADER_TYPE ShaderType): { } -void ShaderResources::CountResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes, Uint32 NumAllowedTypes, - Uint32& NumCBs, Uint32& NumTexSRVs, Uint32& NumTexUAVs, - Uint32& NumBufSRVs, Uint32& NumBufUAVs, Uint32& NumSamplers)const noexcept +void ShaderResources::CountResources(const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumCBs, + Uint32& NumTexSRVs, + Uint32& NumTexUAVs, + Uint32& NumBufSRVs, + Uint32& NumBufUAVs, + Uint32& NumSamplers)const noexcept { - // In release mode, MS compiler generates this false warning: - // Warning C4189 'AllowedTypeBits': local variable is initialized but not referenced - // Most likely it somehow gets confused by the variable being eliminated during function inlining -#pragma warning(push) -#pragma warning(disable : 4189) - Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); -#pragma warning (pop) + auto AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); NumCBs = 0; NumTexSRVs = 0; @@ -123,28 +122,34 @@ void ShaderResources::CountResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes ProcessResources( AllowedVarTypes, NumAllowedTypes, - [&](const D3DShaderResourceAttribs &CB, Uint32) + [&](const D3DShaderResourceAttribs& CB, Uint32) { VERIFY_EXPR(CB.IsAllowedType(AllowedTypeBits)); ++NumCBs; }, + [&](const D3DShaderResourceAttribs& Sam, Uint32) + { + VERIFY_EXPR(Sam.IsAllowedType(AllowedTypeBits)); + // Skip static samplers + if (!Sam.IsStaticSampler()) + ++NumSamplers; + }, [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { VERIFY_EXPR(TexSRV.IsAllowedType(AllowedTypeBits)); ++NumTexSRVs; - NumSamplers += TexSRV.IsValidSampler() ? 1 : 0; }, - [&](const D3DShaderResourceAttribs &TexUAV, Uint32) + [&](const D3DShaderResourceAttribs& TexUAV, Uint32) { VERIFY_EXPR(TexUAV.IsAllowedType(AllowedTypeBits)); ++NumTexUAVs; }, - [&](const D3DShaderResourceAttribs &BufSRV, Uint32) + [&](const D3DShaderResourceAttribs& BufSRV, Uint32) { VERIFY_EXPR(BufSRV.IsAllowedType(AllowedTypeBits)); ++NumBufSRVs; }, - [&](const D3DShaderResourceAttribs &BufUAV, Uint32) + [&](const D3DShaderResourceAttribs& BufUAV, Uint32) { VERIFY_EXPR(BufUAV.IsAllowedType(AllowedTypeBits)); ++NumBufUAVs; @@ -184,27 +189,32 @@ bool ShaderResources::IsCompatibleWith(const ShaderResources &Res)const ProcessResources( nullptr, 0, - [&](const D3DShaderResourceAttribs &CB, Uint32 n) + [&](const D3DShaderResourceAttribs& CB, Uint32 n) { if(!CB.IsCompatibleWith(Res.GetCB(n))) IsCompatible = false; }, + [&](const D3DShaderResourceAttribs& Sam, Uint32 n) + { + if(!Sam.IsCompatibleWith(Res.GetSampler(n))) + IsCompatible = false; + }, [&](const D3DShaderResourceAttribs& TexSRV, Uint32 n) { if(!TexSRV.IsCompatibleWith(Res.GetTexSRV(n))) IsCompatible = false; }, - [&](const D3DShaderResourceAttribs &TexUAV, Uint32 n) + [&](const D3DShaderResourceAttribs& TexUAV, Uint32 n) { if(!TexUAV.IsCompatibleWith(Res.GetTexUAV(n))) IsCompatible = false; }, - [&](const D3DShaderResourceAttribs &BufSRV, Uint32 n) + [&](const D3DShaderResourceAttribs& BufSRV, Uint32 n) { if(!BufSRV.IsCompatibleWith(Res.GetBufSRV(n))) IsCompatible = false; }, - [&](const D3DShaderResourceAttribs &BufUAV, Uint32 n) + [&](const D3DShaderResourceAttribs& BufUAV, Uint32 n) { if(!BufUAV.IsCompatibleWith(Res.GetBufUAV(n))) IsCompatible = false; @@ -218,23 +228,27 @@ size_t ShaderResources::GetHash()const size_t hash = ComputeHash(GetNumCBs(), GetNumTexSRV(), GetNumTexUAV(), GetNumBufSRV(), GetNumBufUAV()); ProcessResources( nullptr, 0, - [&](const D3DShaderResourceAttribs &CB, Uint32) + [&](const D3DShaderResourceAttribs& CB, Uint32) { HashCombine(hash, CB); }, - [&](const D3DShaderResourceAttribs &TexSRV, Uint32) + [&](const D3DShaderResourceAttribs& Sam, Uint32) + { + HashCombine(hash, Sam); + }, + [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { HashCombine(hash, TexSRV); }, - [&](const D3DShaderResourceAttribs &TexUAV, Uint32) + [&](const D3DShaderResourceAttribs& TexUAV, Uint32) { HashCombine(hash, TexUAV); }, - [&](const D3DShaderResourceAttribs &BufSRV, Uint32) + [&](const D3DShaderResourceAttribs& BufSRV, Uint32) { HashCombine(hash, BufSRV); }, - [&](const D3DShaderResourceAttribs &BufUAV, Uint32) + [&](const D3DShaderResourceAttribs& BufUAV, Uint32) { HashCombine(hash, BufUAV); } diff --git a/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp b/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp index 0dac8ea1..a845c613 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp @@ -181,7 +181,7 @@ namespace Diligent RefCntAutoPtr pStaticSampler; for (Uint32 s = 0; s < NumStaticSamplers; ++s) { - if (strcmp(Name.data(), StaticSamplers[s].TextureName) == 0) + if (strcmp(Name.data(), StaticSamplers[s].SamplerOrTextureName) == 0) { pDeviceGLImpl->CreateSampler(StaticSamplers[s].Desc, reinterpret_cast(static_cast(&pStaticSampler)) ); break; -- cgit v1.2.3