diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-06-19 15:52:15 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-06-19 15:52:15 +0000 |
| commit | f345a63c047c7760cb5c5fe70f72a075b4f3a7df (patch) | |
| tree | 95d9ec41ff14a8b52326e9f80c807365b767c05a /Graphics/GraphicsEngineD3DBase | |
| parent | Cleaned D3D Shader Resource implementation (diff) | |
| download | DiligentCore-f345a63c047c7760cb5c5fe70f72a075b4f3a7df.tar.gz DiligentCore-f345a63c047c7760cb5c5fe70f72a075b4f3a7df.zip | |
Implemented resource names string pool for D3D backends
Diffstat (limited to 'Graphics/GraphicsEngineD3DBase')
3 files changed, 134 insertions, 84 deletions
diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h index 937d6b30..db2bd897 100644 --- a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h +++ b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h @@ -23,6 +23,10 @@ #pragma once +#include <string> +#include <vector> +#include <unordered_set> + #include "Shader.h" #include "StringTools.h" @@ -42,30 +46,32 @@ namespace Diligent typename TOnNewBuffSRV, typename TOnNewSampler, typename TOnNewTexSRV> - void LoadD3DShaderResources(ID3DBlob *pShaderByteCode, + void LoadD3DShaderResources(ID3DBlob* pShaderByteCode, TOnResourcesCounted OnResourcesCounted, - TOnNewCB OnNewCB, - TOnNewTexUAV OnNewTexUAV, - TOnNewBuffUAV OnNewBuffUAV, - TOnNewBuffSRV OnNewBuffSRV, - TOnNewSampler OnNewSampler, - TOnNewTexSRV OnNewTexSRV, - - const ShaderDesc &ShdrDesc, - const Char *SamplerSuffix) + TOnNewCB OnNewCB, + TOnNewTexUAV OnNewTexUAV, + TOnNewBuffUAV OnNewBuffUAV, + TOnNewBuffSRV OnNewBuffSRV, + TOnNewSampler OnNewSampler, + TOnNewTexSRV OnNewTexSRV, + + const ShaderDesc& ShdrDesc, + const Char* SamplerSuffix) { CComPtr<TShaderReflection> pShaderReflection; - CHECK_D3D_RESULT_THROW( D3DReflect( pShaderByteCode->GetBufferPointer(), pShaderByteCode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast<void**>(static_cast<TShaderReflection**>(&pShaderReflection)) ), - "Failed to get the shader reflection" ); + auto hr = D3DReflect( pShaderByteCode->GetBufferPointer(), pShaderByteCode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast<void**>(static_cast<TShaderReflection**>(&pShaderReflection))); + CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection" ); D3D_SHADER_DESC shaderDesc = {}; pShaderReflection->GetDesc( &shaderDesc ); std::vector<D3DShaderResourceAttribs, STDAllocatorRawMem<D3DShaderResourceAttribs> > Resources( STD_ALLOCATOR_RAW_MEM(D3DShaderResourceAttribs, GetRawAllocator(), "Allocator for vector<D3DShaderResourceAttribs>") ); Resources.reserve(shaderDesc.BoundResources); - + std::unordered_set<std::string> ResourceNamesTmpPool; + 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) UINT SkipCount = 1; for( UINT Res = 0; Res < shaderDesc.BoundResources; Res += SkipCount ) @@ -73,7 +79,7 @@ namespace Diligent D3D_SHADER_INPUT_BIND_DESC BindingDesc = {}; pShaderReflection->GetResourceBindingDesc( Res, &BindingDesc ); - String Name(BindingDesc.Name); + std::string Name(BindingDesc.Name); SkipCount = 1; @@ -107,7 +113,7 @@ namespace Diligent #ifdef _DEBUG for (const auto &ExistingRes : Resources) { - VERIFY(ExistingRes.Name != Name, "Resource with the same name has already been enumerated. All array elements are expected to be enumerated one after another"); + VERIFY(Name.compare(ExistingRes.Name) != 0, "Resource with the same name has already been enumerated. All array elements are expected to be enumerated one after another"); } #endif for( UINT ArrElem = Res+1; ArrElem < shaderDesc.BoundResources; ++ArrElem) @@ -153,15 +159,14 @@ namespace Diligent } // Use texture name to derive sampler type VarType = GetShaderVariableType(ShdrDesc.DefaultVariableType, ShdrDesc.VariableDesc, ShdrDesc.NumVariables, - [&](const char *TexName) - { - return StrCmpSuff(Name.c_str(), TexName, SamplerSuffix); - } - ); + [&](const char *TexName) + { + return StrCmpSuff(Name.c_str(), TexName, SamplerSuffix); + }); } else { - VarType = GetShaderVariableType(Name.c_str(), ShdrDesc.DefaultVariableType, ShdrDesc.VariableDesc, ShdrDesc.NumVariables); + VarType = GetShaderVariableType(Name, ShdrDesc.DefaultVariableType, ShdrDesc.VariableDesc, ShdrDesc.NumVariables); } @@ -181,7 +186,18 @@ namespace Diligent case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: UNSUPPORTED( "RW structured buffers with counter are not supported" ); break; default: UNEXPECTED("Unexpected resource type"); } - Resources.emplace_back(std::move(Name), BindingDesc.BindPoint, BindCount, BindingDesc.Type, VarType, BindingDesc.Dimension, D3DShaderResourceAttribs::InvalidSamplerId, IsStaticSampler); + ResourceNamesPoolSize += Name.length() + 1; + auto it = ResourceNamesTmpPool.emplace(std::move(Name)); + Resources.emplace_back( + it.first->c_str(), + BindingDesc.BindPoint, + BindCount, + BindingDesc.Type, + VarType, + BindingDesc.Dimension, + D3DShaderResourceAttribs::InvalidSamplerId, + IsStaticSampler + ); } @@ -191,12 +207,12 @@ namespace Diligent for (Uint32 v = 0; v < ShdrDesc.NumVariables; ++v) { bool VariableFound = false; - const auto *VarName = ShdrDesc.VariableDesc[v].Name; + const auto* VarName = ShdrDesc.VariableDesc[v].Name; for (const auto& Res : Resources) { // Skip samplers as they are not handled as independent variables - if (Res.InputType != D3D_SIT_SAMPLER && Res.Name.compare(VarName) == 0) + if (Res.InputType != D3D_SIT_SAMPLER && strcmp(Res.Name, VarName) == 0) { VariableFound = true; break; @@ -215,7 +231,7 @@ namespace Diligent for (const auto& Res : Resources) { - if ( Res.InputType == D3D_SIT_TEXTURE && Res.SRVDimension != D3D_SRV_DIMENSION_BUFFER && Res.Name.compare(TexName) == 0) + if ( Res.InputType == D3D_SIT_TEXTURE && Res.SRVDimension != D3D_SRV_DIMENSION_BUFFER && strcmp(Res.Name, TexName) == 0) { TextureFound = true; break; @@ -229,18 +245,19 @@ namespace Diligent } #endif - OnResourcesCounted(NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers); + OnResourcesCounted(NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers, ResourceNamesPoolSize); - std::vector<D3DShaderResourceAttribs, STDAllocatorRawMem<D3DShaderResourceAttribs> > TextureSRVs( STD_ALLOCATOR_RAW_MEM(D3DShaderResourceAttribs, GetRawAllocator(), "Allocator for vector<D3DShaderResourceAttribs>") ); - TextureSRVs.reserve(NumTexSRVs); + std::vector<size_t, STDAllocatorRawMem<size_t> > TexSRVInds( STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for vector<size_t>") ); + TexSRVInds.reserve(NumTexSRVs); - for(auto &Res : Resources) + for(size_t ResInd = 0; ResInd < Resources.size(); ++ResInd) { + const auto& Res = Resources[ResInd]; switch( Res.InputType ) { case D3D_SIT_CBUFFER: { - OnNewCB( std::move(Res) ); + OnNewCB( Res ); break; } @@ -254,18 +271,19 @@ namespace Diligent { if( Res.SRVDimension == D3D_SRV_DIMENSION_BUFFER ) { - OnNewBuffSRV( std::move(Res) ); + OnNewBuffSRV( Res ); } else { - TextureSRVs.emplace_back( std::move(Res) ); + // Texture SRVs must be processed all samplers are initialized + TexSRVInds.push_back(ResInd); } break; } case D3D_SIT_SAMPLER: { - OnNewSampler( std::move(Res) ); + OnNewSampler( Res ); break; } @@ -273,24 +291,24 @@ namespace Diligent { if( Res.SRVDimension == D3D_SRV_DIMENSION_BUFFER ) { - OnNewBuffUAV( std::move(Res) ); + OnNewBuffUAV( Res ); } else { - OnNewTexUAV( std::move(Res) ); + OnNewTexUAV( Res ); } break; } case D3D_SIT_STRUCTURED: { - OnNewBuffSRV( std::move(Res) ); + OnNewBuffSRV( Res ); break; } case D3D_SIT_UAV_RWSTRUCTURED: { - OnNewBuffUAV( std::move(Res) ); + OnNewBuffUAV( Res ); break; } @@ -302,7 +320,7 @@ namespace Diligent case D3D_SIT_UAV_RWBYTEADDRESS: { - OnNewBuffUAV( std::move(Res) ); + OnNewBuffUAV( Res ); break; } @@ -327,9 +345,9 @@ namespace Diligent } // Process texture SRVs. We need to do this after all samplers are initialized - for( auto &Tex : TextureSRVs ) + for( auto TexSRVInd : TexSRVInds ) { - OnNewTexSRV( std::move(Tex) ); + OnNewTexSRV( Resources[TexSRVInd] ); } } } diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h index 04ebeb51..a8e9e46a 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h @@ -59,6 +59,7 @@ #include "Shader.h" #include "STDAllocator.h" #include "HashUtils.h" +#include "StringPool.h" namespace Diligent { @@ -84,7 +85,7 @@ inline Uint32 GetAllowedTypeBits(const SHADER_VARIABLE_TYPE *AllowedVarTypes, Ui struct D3DShaderResourceAttribs { - String Name; // Move ctor will not work if it is const + const char* const Name; const Uint16 BindPoint; const Uint16 BindCount; @@ -93,18 +94,19 @@ struct D3DShaderResourceAttribs // bit | 0 1 2 3 | 4 5 6 | 7 8 9 10 | 11 12 ... 30 | 31 | // | | | | | | // | InputType | VariableType | SRV Dim | SamplerId | 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 IsStaticSamplerFlagBits = 1; - static_assert(ShaderInputTypeBits + VariableTypeBits + SRVDimBits + SamplerIdBits + IsStaticSamplerFlagBits == 32, "Attributes are better be packed into 32 bits"); + 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 StaticSamplerFlagBits = 1; + static_assert(ShaderInputTypeBits + VariableTypeBits + SRVDimBits + SamplerIdBits + StaticSamplerFlagBits == 32, "Attributes are better be packed into 32 bits"); const D3D_SHADER_INPUT_TYPE InputType : ShaderInputTypeBits; // Max value: D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER == 11 const SHADER_VARIABLE_TYPE VariableType : VariableTypeBits; // Max value: SHADER_VARIABLE_TYPE_DYNAMIC == 2 const D3D_SRV_DIMENSION SRVDimension : SRVDimBits; // Max value: D3D_SRV_DIMENSION_BUFFEREX == 11 const Uint32 SamplerId : SamplerIdBits; // Max value: 1048575 - const bool IsStaticSampler : IsStaticSamplerFlagBits; + const Uint32 StaticSamplerFlag : StaticSamplerFlagBits; // Needs to be Uint32, otherwise sizeof(D3DShaderResourceAttribs)==24 + // (https://stackoverflow.com/questions/308364/c-bitfield-packing-with-bools) static constexpr const Uint32 InvalidSamplerId = (1 << SamplerIdBits) - 1; static constexpr const Uint16 InvalidBindPoint = std::numeric_limits<Uint16>::max(); @@ -115,7 +117,7 @@ struct D3DShaderResourceAttribs static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES < (1 << VariableTypeBits), "Not enough bits to represent SHADER_VARIABLE_TYPE"); static_assert(D3D_SRV_DIMENSION_BUFFEREX < (1 << SRVDimBits), "Not enough bits to represent D3D_SRV_DIMENSION"); - D3DShaderResourceAttribs(String _Name, + D3DShaderResourceAttribs(const char* _Name, UINT _BindPoint, UINT _BindCount, D3D_SHADER_INPUT_TYPE _InputType, @@ -123,14 +125,14 @@ struct D3DShaderResourceAttribs D3D_SRV_DIMENSION _SRVDimension, Uint32 _SamplerId, bool _IsStaticSampler)noexcept : - Name(std::move(_Name)), - BindPoint(static_cast<decltype(BindPoint)>(_BindPoint)), - BindCount(static_cast<decltype(BindCount)>(_BindCount)), - InputType (_InputType), - VariableType (_VariableType), - SRVDimension (_SRVDimension), - SamplerId (_SamplerId), - IsStaticSampler(_IsStaticSampler) + Name (_Name), + BindPoint (static_cast<decltype(BindPoint)>(_BindPoint)), + BindCount (static_cast<decltype(BindCount)>(_BindCount)), + InputType (_InputType), + VariableType (_VariableType), + SRVDimension (_SRVDimension), + SamplerId (_SamplerId), + StaticSamplerFlag(_IsStaticSampler ? 1 : 0) { VERIFY(_BindPoint <= MaxBindPoint || _BindPoint == InvalidBindPoint, "Bind Point is out of allowed range"); VERIFY(_BindCount <= MaxBindCount, "Bind Count is out of allowed range"); @@ -140,7 +142,7 @@ struct D3DShaderResourceAttribs VERIFY(_SamplerId < (1 << SamplerIdBits), "SamplerId is out of representable range"); #ifdef _DEBUG if(_InputType==D3D_SIT_SAMPLER) - VERIFY_EXPR(IsStaticSampler == _IsStaticSampler); + VERIFY_EXPR(IsStaticSampler() == _IsStaticSampler); else VERIFY(!_IsStaticSampler, "Only samplers can be marked as static"); @@ -154,13 +156,10 @@ struct D3DShaderResourceAttribs #endif } - D3DShaderResourceAttribs(D3DShaderResourceAttribs&& rhs) = default; - D3DShaderResourceAttribs(const D3DShaderResourceAttribs& rhs) = delete; - - D3DShaderResourceAttribs(const D3DShaderResourceAttribs& rhs, Uint32 SamplerId)noexcept : + D3DShaderResourceAttribs(StringPool& NamesPool, const D3DShaderResourceAttribs& rhs, Uint32 SamplerId)noexcept : D3DShaderResourceAttribs { - rhs.Name, + NamesPool.CopyString(rhs.Name), rhs.BindPoint, rhs.BindCount, rhs.InputType, @@ -173,24 +172,36 @@ struct D3DShaderResourceAttribs VERIFY(InputType == D3D_SIT_TEXTURE, "Only textures can be assigned a texture sampler"); } - //D3DShaderResourceAttribs(D3DShaderResourceAttribs&& rhs)noexcept : - // Name(std::move(rhs.Name)), - // BindPoint(rhs.BindPoint), - // BindCount(rhs.BindCount), - // PackedAttribs( rhs.PackedAttribs ) - //{ - //} + D3DShaderResourceAttribs(StringPool& NamesPool, const D3DShaderResourceAttribs& rhs)noexcept : + D3DShaderResourceAttribs + { + NamesPool.CopyString(rhs.Name), + rhs.BindPoint, + rhs.BindCount, + rhs.InputType, + rhs.VariableType, + rhs.SRVDimension, + rhs.SamplerId, + rhs.StaticSamplerFlag !=0 ? true : false + } + { + } + D3DShaderResourceAttribs (const D3DShaderResourceAttribs& rhs) = delete; + D3DShaderResourceAttribs ( D3DShaderResourceAttribs&& rhs) = default; // Required for vector<D3DShaderResourceAttribs> + D3DShaderResourceAttribs& operator = (const D3DShaderResourceAttribs& rhs) = delete; + D3DShaderResourceAttribs& operator = ( D3DShaderResourceAttribs&& rhs) = delete; + Uint32 GetSamplerId()const { VERIFY( InputType == D3D_SIT_TEXTURE, "Invalid input type: D3D_SIT_TEXTURE is expected" ); return SamplerId; } - bool GetIsStaticSampler()const + bool IsStaticSampler()const { VERIFY( InputType == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" ); - return IsStaticSampler; + return StaticSamplerFlag != 0; } bool IsValidSampler()const @@ -214,20 +225,21 @@ struct D3DShaderResourceAttribs 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 && - IsStaticSampler == Attribs.IsStaticSampler; + return BindPoint == Attribs.BindPoint && + BindCount == Attribs.BindCount && + InputType == Attribs.InputType && + VariableType == Attribs.VariableType && + SRVDimension == Attribs.SRVDimension && + SamplerId == Attribs.SamplerId && + StaticSamplerFlag == Attribs.StaticSamplerFlag; } size_t GetHash()const { - return ComputeHash(BindPoint, BindCount, InputType, VariableType, SRVDimension, SamplerId, IsStaticSampler); + return ComputeHash(BindPoint, BindCount, InputType, VariableType, SRVDimension, SamplerId, StaticSamplerFlag); } }; +static_assert(sizeof(D3DShaderResourceAttribs) == sizeof(void*) + sizeof(Uint32)*2, "Unexpected sizeof(D3DShaderResourceAttribs)"); /// Diligent::ShaderResources class @@ -321,7 +333,14 @@ public: size_t GetHash()const; protected: - void Initialize(IMemoryAllocator &Allocator, Uint32 NumCBs, Uint32 NumTexSRVs, Uint32 NumTexUAVs, Uint32 NumBufSRVs, Uint32 NumBufUAVs, Uint32 NumSamplers); + void Initialize(IMemoryAllocator& Allocator, + Uint32 NumCBs, + Uint32 NumTexSRVs, + Uint32 NumTexUAVs, + Uint32 NumBufSRVs, + Uint32 NumBufUAVs, + Uint32 NumSamplers, + size_t ResourceNamesPoolSize); __forceinline D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset)noexcept { @@ -351,6 +370,10 @@ private: // | CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | Resource Names | std::unique_ptr< void, STDDeleterRawMem<void> > m_MemoryBuffer; +protected: + StringPool m_ResourceNames; + +private: // Offsets in elements of D3DShaderResourceAttribs typedef Uint16 OffsetType; OffsetType m_TexSRVOffset = 0; diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 85cda16d..d2489ef2 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -51,7 +51,14 @@ ShaderResources::~ShaderResources() GetSampler(n).~D3DShaderResourceAttribs(); } -void ShaderResources::Initialize(IMemoryAllocator &Allocator, Uint32 NumCBs, Uint32 NumTexSRVs, Uint32 NumTexUAVs, Uint32 NumBufSRVs, Uint32 NumBufUAVs, Uint32 NumSamplers) +void ShaderResources::Initialize(IMemoryAllocator& Allocator, + Uint32 NumCBs, + Uint32 NumTexSRVs, + Uint32 NumTexUAVs, + Uint32 NumBufSRVs, + Uint32 NumBufUAVs, + Uint32 NumSamplers, + size_t ResourceNamesPoolSize) { VERIFY( &m_MemoryBuffer.get_deleter().m_Allocator == &Allocator, "Incosistent allocators provided"); @@ -74,7 +81,7 @@ void ShaderResources::Initialize(IMemoryAllocator &Allocator, Uint32 NumCBs, Uin VERIFY(m_SamplersOffset + NumSamplers<= MaxOffset, "Max offset exceeded"); m_TotalResources = m_SamplersOffset + static_cast<OffsetType>(NumSamplers); - auto MemorySize = m_TotalResources * sizeof(D3DShaderResourceAttribs); + auto MemorySize = m_TotalResources * sizeof(D3DShaderResourceAttribs) + ResourceNamesPoolSize * sizeof(char); VERIFY_EXPR(GetNumCBs() == NumCBs); VERIFY_EXPR(GetNumTexSRV() == NumTexSRVs); @@ -87,6 +94,8 @@ void ShaderResources::Initialize(IMemoryAllocator &Allocator, Uint32 NumCBs, Uin { auto *pRawMem = ALLOCATE(Allocator, "Allocator for shader resources", MemorySize ); m_MemoryBuffer.reset(pRawMem); + char* NamesPool = reinterpret_cast<char*>(reinterpret_cast<D3DShaderResourceAttribs*>(pRawMem) + m_TotalResources); + m_ResourceNames.AssignMemory(NamesPool, ResourceNamesPoolSize); } } @@ -154,7 +163,7 @@ Uint32 ShaderResources::FindAssignedSamplerId(const D3DShaderResourceAttribs& Te for (Uint32 s = 0; s < NumSamplers; ++s) { const auto &Sampler = GetSampler(s); - if( StrCmpSuff(Sampler.Name.c_str(), TexSRV.Name.c_str(), D3DSamplerSuffix) ) + if( StrCmpSuff(Sampler.Name, TexSRV.Name, D3DSamplerSuffix) ) { VERIFY(Sampler.VariableType == TexSRV.VariableType, "Inconsistent texture and sampler variable types"); VERIFY(Sampler.BindCount == TexSRV.BindCount || Sampler.BindCount == 1, "Sampler assigned to array \"", TexSRV.Name, "\" is expected to be scalar or have the same dimension (",TexSRV.BindCount,"). Actual sampler array dimension : ", Sampler.BindCount); |
