diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-06-22 15:28:57 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-06-22 15:28:57 +0000 |
| commit | 4c2d453927451a990dac84da2abdc777e04a5db0 (patch) | |
| tree | 72226a47df2d5340cc4ef475e2b0091be6b37102 /Graphics/GraphicsEngineD3D12 | |
| parent | Added SRBMemoryAllocator (diff) | |
| download | DiligentCore-4c2d453927451a990dac84da2abdc777e04a5db0.tar.gz DiligentCore-4c2d453927451a990dac84da2abdc777e04a5db0.zip | |
Improved shader resource binding memory allocation in D3D12 backend: replaced AdaptiveFixedBlockAllocator with SRBMemAllocator
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
9 files changed, 102 insertions, 61 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h index a248ccf3..698396b8 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h @@ -31,7 +31,7 @@ #include "PipelineStateBase.h" #include "RootSignature.h" #include "ShaderResourceLayoutD3D12.h" -#include "AdaptiveFixedBlockAllocator.h" +#include "SRBMemoryAllocator.h" /// Namespace for the Direct3D11 implementation of the graphics engine namespace Diligent @@ -70,12 +70,9 @@ public: bool dbgContainsShaderResources()const; - IMemoryAllocator& GetResourceCacheDataAllocator(){return m_ResourceCacheDataAllocator;} - IMemoryAllocator& GetShaderResourceLayoutDataAllocator(Uint32 ActiveShaderInd) + SRBMemoryAllocator& GetSRBMemoryAllocator() { - VERIFY_EXPR(ActiveShaderInd < m_NumShaders); - auto *pAllocator = m_ResLayoutDataAllocators.GetAllocator(ActiveShaderInd); - return pAllocator != nullptr ? *pAllocator : GetRawAllocator(); + return m_SRBMemAllocator; } IShaderVariable *GetDummyShaderVar(){return &m_DummyVar;} @@ -89,37 +86,13 @@ private: RootSignature m_RootSig; DummyShaderVariable m_DummyVar; - // Looks like there may be a bug in msvc: when allocators are declared as - // an array and if an exception is thrown from constructor, the app crashes - class ResLayoutDataAllocators - { - public: - ~ResLayoutDataAllocators() - { - for(size_t i=0; i < _countof(m_pAllocators); ++i) - if(m_pAllocators[i] != nullptr) - DESTROY_POOL_OBJECT(m_pAllocators[i]); - } - void Init(Uint32 NumActiveShaders, Uint32 SRBAllocationGranularity) - { - VERIFY_EXPR(NumActiveShaders <= _countof(m_pAllocators) ); - for(Uint32 i=0; i < NumActiveShaders; ++i) - m_pAllocators[i] = NEW_POOL_OBJECT(AdaptiveFixedBlockAllocator, "Shader resource layout data allocator", GetRawAllocator(), SRBAllocationGranularity); - } - AdaptiveFixedBlockAllocator *GetAllocator(Uint32 ActiveShaderInd) - { - VERIFY_EXPR(ActiveShaderInd < _countof(m_pAllocators) ); - return m_pAllocators[ActiveShaderInd]; - } - private: - AdaptiveFixedBlockAllocator *m_pAllocators[5] = {}; - }m_ResLayoutDataAllocators; // Allocators must be defined before default SRB + // Must be defined before default SRB + SRBMemoryAllocator m_SRBMemAllocator; ShaderResourceLayoutD3D12* m_pShaderResourceLayouts[6] = {}; - AdaptiveFixedBlockAllocator m_ResourceCacheDataAllocator; // Use separate allocator for every shader stage // Do not use strong reference to avoid cyclic references - // Default SRB must be defined after allocators + // Default SRB must be defined after m_SRBMemAllocator std::unique_ptr<class ShaderResourceBindingD3D12Impl, STDDeleter<ShaderResourceBindingD3D12Impl, FixedBlockMemoryAllocator> > m_pDefaultShaderResBinding; }; diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.h b/Graphics/GraphicsEngineD3D12/include/RootSignature.h index 9d3fd016..bcfc1781 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.h +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.h @@ -292,7 +292,10 @@ public: void Finalize(ID3D12Device *pd3d12Device); ID3D12RootSignature* GetD3D12RootSignature()const{return m_pd3d12RootSignature;} - void InitResourceCache(class RenderDeviceD3D12Impl *pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator &CacheMemAllocator)const; + + size_t GetResourceCacheRequiredMemSize()const; + + void InitResourceCache(class RenderDeviceD3D12Impl* pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator& CacheMemAllocator)const; void InitStaticSampler(SHADER_TYPE ShaderType, const String& TextureName, @@ -347,6 +350,8 @@ private: #ifdef _DEBUG void dbgVerifyRootParameters()const; #endif + + std::vector<Uint32, STDAllocatorRawMem<Uint32> > GetCacheTableSizes()const; Uint32 m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_NUM_TYPES]; Uint32 m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_NUM_TYPES]; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h index 98bc4112..dc4f61a8 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h @@ -115,6 +115,9 @@ public: ~ShaderResourceCacheD3D12(); + static size_t GetRequiredMemorySize(Uint32 NumTables, + Uint32 TableSizes[]); + void Initialize(IMemoryAllocator& MemAllocator, Uint32 NumTables, Uint32 TableSizes[]); diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h index 34856aba..79f58da7 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h @@ -144,6 +144,10 @@ public: ~ShaderResourceLayoutD3D12(); + static size_t GetRequiredMemorySize(const ShaderResourceLayoutD3D12& SrcLayout, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes); + // The method is called by // - ShaderD3D12Impl class instance to initialize static resource layout and initialize shader resource cache // to hold static resources @@ -151,10 +155,10 @@ public: // Root indices and descriptor table offsets are assigned during the initialization; // no shader resource cache is provided void Initialize(ID3D12Device* pd3d12Device, - const std::shared_ptr<const ShaderResourcesD3D12>& pSrcResources, + const std::shared_ptr<const ShaderResourcesD3D12>& pSrcResources, IMemoryAllocator& LayoutDataAllocator, - const SHADER_VARIABLE_TYPE* VarTypes, - Uint32 NumAllowedTypes, + const SHADER_VARIABLE_TYPE* VarTypes, + Uint32 NumAllowedTypes, ShaderResourceCacheD3D12* pResourceCache, class RootSignature* pRootSig); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index d9c60b2a..d4dcf2f6 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -82,7 +82,7 @@ PipelineStateD3D12Impl :: PipelineStateD3D12Impl(IReferenceCounters* pRefCo const PipelineStateDesc& PipelineDesc) : TPipelineStateBase(pRefCounters, pDeviceD3D12, PipelineDesc), m_DummyVar(*this), - m_ResourceCacheDataAllocator(GetRawAllocator(), PipelineDesc.SRBAllocationGranularity), + m_SRBMemAllocator(GetRawAllocator()), m_pDefaultShaderResBinding(nullptr, STDDeleter<ShaderResourceBindingD3D12Impl, FixedBlockMemoryAllocator>(pDeviceD3D12->GetSRBAllocator()) ) { auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); @@ -215,7 +215,17 @@ PipelineStateD3D12Impl :: PipelineStateD3D12Impl(IReferenceCounters* pRefCo } if(PipelineDesc.SRBAllocationGranularity > 1) - m_ResLayoutDataAllocators.Init(m_NumShaders, PipelineDesc.SRBAllocationGranularity); + { + std::array<size_t, MaxShadersInPipeline> ShaderResLayoutDataSizes = {}; + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + std::array<SHADER_VARIABLE_TYPE, 3> AllowedVarTypes = { SHADER_VARIABLE_TYPE_STATIC, SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC }; + ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D12::GetRequiredMemorySize(*m_pShaderResourceLayouts[s], AllowedVarTypes.data(), static_cast<Uint32>(AllowedVarTypes.size())); + } + + auto CacheMemorySize = m_RootSig.GetResourceCacheRequiredMemSize(); + m_SRBMemAllocator.Initialize(PipelineDesc.SRBAllocationGranularity, m_NumShaders, ShaderResLayoutDataSizes.data(), 1, &CacheMemorySize); + } auto &SRBAllocator = pDeviceD3D12->GetSRBAllocator(); // Default shader resource binding must be initialized after resource layouts are parsed! diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 52854d88..0e0ffcf6 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -536,10 +536,13 @@ void RootSignature::Finalize(ID3D12Device* pd3d12Device) } } -//http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-the-Cache-for-Shader-Resource-Binding-Object -void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl, - ShaderResourceCacheD3D12& ResourceCache, - IMemoryAllocator& CacheMemAllocator)const +size_t RootSignature::GetResourceCacheRequiredMemSize()const +{ + auto CacheTableSizes = GetCacheTableSizes(); + return ShaderResourceCacheD3D12::GetRequiredMemorySize(static_cast<Uint32>(CacheTableSizes.size()), CacheTableSizes.data()); +} + +std::vector<Uint32, STDAllocatorRawMem<Uint32> > RootSignature::GetCacheTableSizes()const { // Get root table size for every root index // m_RootParams keeps root tables sorted by the array index, not the root index @@ -556,6 +559,16 @@ void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl auto &RootParam = m_RootParams.GetRootView(rv); CacheTableSizes[RootParam.GetRootIndex()] = 1; } + + return CacheTableSizes; +} + +//http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-the-Cache-for-Shader-Resource-Binding-Object +void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl, + ShaderResourceCacheD3D12& ResourceCache, + IMemoryAllocator& CacheMemAllocator)const +{ + auto CacheTableSizes = GetCacheTableSizes(); // Initialize resource cache to hold root tables ResourceCache.Initialize(CacheMemAllocator, static_cast<Uint32>(CacheTableSizes.size()), CacheTableSizes.data()); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 2403b938..26e37b48 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -30,33 +30,34 @@ namespace Diligent { -ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl( IReferenceCounters* pRefCounters, - PipelineStateD3D12Impl* pPSO, - bool IsPSOInternal) : +ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounters* pRefCounters, + PipelineStateD3D12Impl* pPSO, + bool IsPSOInternal) : TBase( pRefCounters, pPSO, IsPSOInternal ), m_ShaderResourceCache(ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources) { - auto *ppShaders = pPSO->GetShaders(); + auto* ppShaders = pPSO->GetShaders(); m_NumShaders = pPSO->GetNumShaders(); - auto *pRenderDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(pPSO->GetDevice()); - pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, pPSO->GetResourceCacheDataAllocator()); + auto* pRenderDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(pPSO->GetDevice()); + auto& ResCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); + pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, ResCacheDataAllocator); - auto *pResLayoutRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12", m_NumShaders * sizeof(ShaderResourceLayoutD3D12)); + auto* pResLayoutRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12", m_NumShaders * sizeof(ShaderResourceLayoutD3D12)); m_pResourceLayouts = reinterpret_cast<ShaderResourceLayoutD3D12*>(pResLayoutRawMem); for (Uint32 s = 0; s < m_NumShaders; ++s) { - auto *pShader = ppShaders[s]; + auto* pShader = ppShaders[s]; auto ShaderType = pShader->GetDesc().ShaderType; auto ShaderInd = GetShaderTypeIndex(ShaderType); - auto &ShaderResLayoutDataAllocator = pPSO->GetShaderResourceLayoutDataAllocator(s); + auto& ShaderResLayoutDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object - SHADER_VARIABLE_TYPE Types[] = {SHADER_VARIABLE_TYPE_STATIC, SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC}; + std::array<SHADER_VARIABLE_TYPE, 3> AllowedVarTypes = { SHADER_VARIABLE_TYPE_STATIC, SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC }; const auto &SrcLayout = pPSO->GetShaderResLayout(ShaderType); - new (m_pResourceLayouts + s) ShaderResourceLayoutD3D12(*this, SrcLayout, ShaderResLayoutDataAllocator, Types, _countof(Types), m_ShaderResourceCache); + new (m_pResourceLayouts + s) ShaderResourceLayoutD3D12(*this, SrcLayout, ShaderResLayoutDataAllocator, AllowedVarTypes.data(), static_cast<Uint32>(AllowedVarTypes.size()), m_ShaderResourceCache); m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s); } @@ -72,7 +73,7 @@ ShaderResourceBindingD3D12Impl::~ShaderResourceBindingD3D12Impl() IMPLEMENT_QUERY_INTERFACE( ShaderResourceBindingD3D12Impl, IID_ShaderResourceBindingD3D12, TBase ) -void ShaderResourceBindingD3D12Impl::BindResources(Uint32 ShaderFlags, IResourceMapping *pResMapping, Uint32 Flags) +void ShaderResourceBindingD3D12Impl::BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) { for (auto ShaderInd = 0; ShaderInd <= CSInd; ++ShaderInd ) { @@ -96,7 +97,7 @@ IShaderVariable *ShaderResourceBindingD3D12Impl::GetVariable(SHADER_TYPE ShaderT LOG_ERROR_MESSAGE("Failed to find shader variable \"", Name,"\" in shader resource binding: shader type ", GetShaderTypeLiteralName(ShaderType), " is not initialized"); return ValidatedCast<PipelineStateD3D12Impl>(GetPipelineState())->GetDummyShaderVar(); } - auto *pVar = m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Name); + auto* pVar = m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Name); if(pVar == nullptr) pVar = ValidatedCast<PipelineStateD3D12Impl>(GetPipelineState())->GetDummyShaderVar(); @@ -104,9 +105,9 @@ IShaderVariable *ShaderResourceBindingD3D12Impl::GetVariable(SHADER_TYPE ShaderT } #ifdef VERIFY_SHADER_BINDINGS -void ShaderResourceBindingD3D12Impl::dbgVerifyResourceBindings(const PipelineStateD3D12Impl *pPSO) +void ShaderResourceBindingD3D12Impl::dbgVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO) { - auto *pRefPSO = GetPipelineState(); + auto* pRefPSO = GetPipelineState(); if (pPSO->IsIncompatibleWith(pRefPSO)) { LOG_ERROR("Shader resource binding is incompatible with the pipeline state \"", pPSO->GetDesc().Name, '\"'); @@ -118,7 +119,7 @@ void ShaderResourceBindingD3D12Impl::dbgVerifyResourceBindings(const PipelineSta #endif -void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const PipelineStateD3D12Impl *pPSO) +void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const PipelineStateD3D12Impl* pPSO) { VERIFY(!StaticResourcesInitialized(), "Static resources have already been initialized"); VERIFY(pPSO == GetPipelineState(), "Invalid pipeline state provided"); @@ -128,7 +129,7 @@ void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const PipelineSta // Copy static resources for (Uint32 s = 0; s < NumShaders; ++s) { - auto *pShader = ValidatedCast<ShaderD3D12Impl>( ppShaders[s] ); + auto* pShader = ValidatedCast<ShaderD3D12Impl>( ppShaders[s] ); #ifdef VERIFY_SHADER_BINDINGS pShader->DbgVerifyStaticResourceBindings(); #endif diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp index 2b3ae439..4b2d0508 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp @@ -27,8 +27,17 @@ namespace Diligent { + size_t ShaderResourceCacheD3D12::GetRequiredMemorySize(Uint32 NumTables, + Uint32 TableSizes[]) + { + size_t MemorySize = NumTables * sizeof(RootTable); + for(Uint32 t=0; t < NumTables; ++t) + MemorySize += TableSizes[t] * sizeof(Resource); + return MemorySize; + } + // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Cache-Structure - void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator &MemAllocator, Uint32 NumTables, Uint32 TableSizes[]) + void ShaderResourceCacheD3D12::Initialize(IMemoryAllocator& MemAllocator, Uint32 NumTables, Uint32 TableSizes[]) { // Memory layout: // __________________________________________________________ @@ -49,6 +58,7 @@ namespace Diligent for(Uint32 t=0; t < NumTables; ++t) TotalResources += TableSizes[t]; auto MemorySize = NumTables * sizeof(RootTable) + TotalResources * sizeof(Resource); + VERIFY_EXPR(MemorySize == GetRequiredMemorySize(NumTables, TableSizes)); if(MemorySize > 0) { m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 98a64a7a..7b292c62 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -125,6 +125,27 @@ void ShaderResourceLayoutD3D12::AllocateMemory(IMemoryAllocator& m_Samplers = reinterpret_cast<Sampler*>(reinterpret_cast<SRV_CBV_UAV*>(pRawMem) + TotalSrvCbvUav); } + +size_t ShaderResourceLayoutD3D12::GetRequiredMemorySize(const ShaderResourceLayoutD3D12& SrcLayout, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes) +{ + + Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + + size_t MemSize = 0; + for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + { + if( !IsAllowedType(VarType, AllowedTypeBits)) + continue; + + MemSize += SrcLayout.GetCbvSrvUavCount(VarType) * sizeof(SRV_CBV_UAV); + MemSize += SrcLayout.GetSamplerCount(VarType) * sizeof(Sampler); + } + return MemSize; +} + + // Clones layout from the reference layout maintained by the pipeline state // Root indices and descriptor table offsets must be correct // Resource cache is not initialized. @@ -201,6 +222,7 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& #endif } + // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Shader-Resource-Layouts-and-Root-Signature-in-a-Pipeline-State-Object // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Resource-Layouts-in-a-Pipeline-State void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device, |
