Skip to content

Commit 333c3d1

Browse files
committed
Move buffervk to InlineConstantBufferAttribsVk, aligning to D3D11 impl.
1 parent b882f3e commit 333c3d1

File tree

4 files changed

+75
-87
lines changed

4 files changed

+75
-87
lines changed

Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,24 @@ ASSERT_SIZEOF(ImmutableSamplerAttribsVk, 8, "The struct is used in serialization
6464
/// 1. True push constants (from SPIR-V push_constant storage class) - use vkCmdPushConstants
6565
/// 2. Emulated inline constants - use dynamic uniform buffers (similar to D3D11 backend)
6666
///
67-
/// Note: This structure only stores attributes/metadata. The actual storage (pBuffer for emulated
68-
/// inline constants, push constant data for true push constants) is managed per-SRB in
69-
/// ShaderResourceCacheVk to avoid conflicts between multiple PipelineStates sharing the same
70-
/// PipelineResourceSignature.
67+
/// For emulated inline constants (not push constants), the Buffer is created in the Signature
68+
/// and shared by all SRBs (similar to D3D11). Each SRB has its own CPU staging memory.
69+
/// For push constants, pPushConstantData points to the static cache's staging memory.
7170
struct InlineConstantBufferAttribsVk
7271
{
7372
Uint32 ResIndex = 0; // Resource index in the signature (used for matching)
7473
Uint32 DescrSet = 0; // Descriptor set index (0 for push constants as placeholder)
7574
Uint32 BindingIndex = 0; // Binding index within the descriptor set
7675
Uint32 NumConstants = 0; // Number of 32-bit constants
7776
bool IsPushConstant = false; // True if this is a Vulkan push constant (not emulated)
78-
// Note: pBuffer and pPushConstantData are now stored per-SRB in ShaderResourceCacheVk
77+
78+
// For emulated inline constants: shared buffer created in the Signature (similar to D3D11)
79+
// All SRBs reference this same buffer to reduce memory usage.
80+
RefCntAutoPtr<BufferVkImpl> pBuffer;
81+
82+
// For static push constants: pointer to data in the static resource cache
83+
// This allows CopyStaticResources to copy the data to SRB caches.
84+
void* pPushConstantData = nullptr;
7985
};
8086

8187
struct PipelineResourceSignatureInternalDataVk : PipelineResourceSignatureInternalData<PipelineResourceAttribsVk, ImmutableSamplerAttribsVk>

Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -313,32 +313,6 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
313313

314314
Uint32 GetNumPushConstantBuffers() const { return m_NumPushConstantBuffers; }
315315

316-
// Initializes inline constant buffers array
317-
void InitializeInlineConstantBuffers(Uint32 NumBuffers)
318-
{
319-
m_NumInlineConstantBuffers = static_cast<Uint16>(NumBuffers);
320-
if (NumBuffers > 0)
321-
{
322-
m_pInlineConstantBuffers = std::make_unique<RefCntAutoPtr<BufferVkImpl>[]>(NumBuffers);
323-
}
324-
}
325-
326-
// Sets the inline constant buffer at the given ResIndex
327-
void SetInlineConstantBuffer(Uint32 ResIndex, RefCntAutoPtr<BufferVkImpl>&& pBuffer)
328-
{
329-
VERIFY_EXPR(ResIndex < m_NumInlineConstantBuffers);
330-
m_pInlineConstantBuffers[ResIndex] = std::move(pBuffer);
331-
}
332-
333-
// Gets the inline constant buffer at the given ResIndex
334-
BufferVkImpl* GetInlineConstantBuffer(Uint32 ResIndex) const
335-
{
336-
VERIFY_EXPR(ResIndex < m_NumInlineConstantBuffers);
337-
return m_pInlineConstantBuffers[ResIndex].RawPtr();
338-
}
339-
340-
Uint32 GetNumInlineConstantBuffers() const { return m_NumInlineConstantBuffers; }
341-
342316
Uint32 GetNumDescriptorSets() const { return m_NumSets; }
343317
bool HasDynamicResources() const { return m_NumDynamicBuffers > 0; }
344318

@@ -387,11 +361,9 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
387361
// Each pointer points to memory within m_pInlineConstantMemory
388362
std::unique_ptr<void*[]> m_pPushConstantDataPtrs;
389363

390-
// Array of inline constant buffers (one per emulated inline constant buffer)
391-
// Each SRB has its own copy of these buffers to avoid conflicts between
392-
// multiple PipelineStates sharing the same PipelineResourceSignature
393-
std::unique_ptr<RefCntAutoPtr<BufferVkImpl>[]> m_pInlineConstantBuffers;
394-
Uint16 m_NumInlineConstantBuffers = 0;
364+
// Note: Inline constant buffers (for emulated inline constants) are now stored in
365+
// InlineConstantBufferAttribsVk::pBuffer in the PipelineResourceSignature, similar to D3D11.
366+
// All SRBs share the same buffer to reduce memory usage.
395367

396368
Uint16 m_NumSets = 0;
397369
Uint16 m_NumPushConstantBuffers = 0;

Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,26 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts(const bool IsSerialized)
414414
InlineCBAttribs.BindingIndex = pAttribs->BindingIndex;
415415
InlineCBAttribs.NumConstants = ResDesc.ArraySize; // For inline constants, ArraySize is the number of 32-bit constants
416416
InlineCBAttribs.IsPushConstant = IsPushConstant;
417-
// Note: Per-SRB buffers are created in InitSRBResourceCache() to avoid conflicts
418-
// between multiple PipelineStates sharing the same PipelineResourceSignature
417+
418+
// For emulated inline constants (not push constants), create a shared buffer in the Signature
419+
// All SRBs will reference this same buffer (similar to D3D11 backend)
420+
if (!IsPushConstant && m_pDevice)
421+
{
422+
std::string Name = m_Desc.Name;
423+
Name += " - ";
424+
Name += ResDesc.Name;
425+
BufferDesc CBDesc;
426+
CBDesc.Name = Name.c_str();
427+
CBDesc.Size = ResDesc.ArraySize * sizeof(Uint32);
428+
CBDesc.Usage = USAGE_DYNAMIC;
429+
CBDesc.BindFlags = BIND_UNIFORM_BUFFER;
430+
CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
431+
432+
RefCntAutoPtr<IBuffer> pBuffer;
433+
m_pDevice->CreateBuffer(CBDesc, nullptr, &pBuffer);
434+
VERIFY_EXPR(pBuffer);
435+
InlineCBAttribs.pBuffer = RefCntAutoPtr<BufferVkImpl>{pBuffer, IID_BufferVk};
436+
}
419437
}
420438
}
421439
VERIFY_EXPR(InlineConstantBufferIdx == m_NumInlineConstantBufferAttribs);
@@ -596,7 +614,7 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts(const bool IsSerialized)
596614
Uint32 StaticPushConstantIdx = 0;
597615
for (Uint32 i = 0; i < m_NumInlineConstantBufferAttribs; ++i)
598616
{
599-
const InlineConstantBufferAttribsVk& InlineCBAttr = m_InlineConstantBufferAttribs[i];
617+
InlineConstantBufferAttribsVk& InlineCBAttr = m_InlineConstantBufferAttribs[i];
600618

601619
const PipelineResourceDesc& ResDesc = GetResourceDesc(InlineCBAttr.ResIndex);
602620
const ResourceAttribs& Attr = GetResourceAttribs(InlineCBAttr.ResIndex);
@@ -607,8 +625,10 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts(const bool IsSerialized)
607625

608626
if (InlineCBAttr.IsPushConstant)
609627
{
610-
// For push constants, store the data pointer in the static resource cache
628+
// For push constants, store the data pointer both in the static resource cache
629+
// and in InlineCBAttr for easy access during CopyStaticResources
611630
m_pStaticResCache->SetPushConstantDataPtr(StaticPushConstantIdx++, pCurrentDataPtr);
631+
InlineCBAttr.pPushConstantData = pCurrentDataPtr;
612632
}
613633
else
614634
{
@@ -636,6 +656,18 @@ void PipelineResourceSignatureVkImpl::Destruct()
636656
GetDevice()->SafeReleaseDeviceObject(std::move(Layout), ~0ull);
637657
}
638658

659+
// Release shared inline constant buffers before base class Destruct
660+
// Each InlineConstantBufferAttribsVk::pBuffer holds a RefCntAutoPtr to the shared buffer
661+
if (m_InlineConstantBufferAttribs)
662+
{
663+
for (Uint32 i = 0; i < m_NumInlineConstantBufferAttribs; ++i)
664+
{
665+
m_InlineConstantBufferAttribs[i].pBuffer.Release();
666+
}
667+
m_InlineConstantBufferAttribs.reset();
668+
}
669+
m_NumInlineConstantBufferAttribs = 0;
670+
639671
// Note: Static inline constant data is now managed by m_pStaticResCache
640672
// and will be freed when the cache is destroyed
641673

@@ -673,29 +705,28 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
673705

674706
// Initialize inline constant buffers - allocate staging memory and set up data pointers
675707
// For push constants, each SRB gets its own copy of the data (stored in ShaderResourceCacheVk)
676-
// For emulated inline constants, each SRB gets its own buffer to avoid conflicts between
677-
// multiple PipelineStates sharing the same PipelineResourceSignature
708+
// For emulated inline constants, all SRBs share the same buffer (stored in InlineConstantBufferAttribsVk::pBuffer)
709+
// This is similar to D3D11 backend design where buffers are created in the Signature and shared by all SRBs
678710
if (m_NumInlineConstantBufferAttribs > 0)
679711
{
680712
// Ensure the cache reports inline constants so DeviceContextVkImpl
681713
// updates emulated buffers even if no data has been written yet.
682714
ResourceCache.MarkHasInlineConstants();
683715

684-
// Count push constant buffers, emulated inline constant buffers, and calculate total memory size
716+
// Calculate total memory size for CPU staging data
685717
Uint32 TotalInlineConstantSize = 0;
686718
for (Uint32 i = 0; i < m_NumInlineConstantBufferAttribs; ++i)
687719
{
688720
const InlineConstantBufferAttribsVk& InlineCBAttr = m_InlineConstantBufferAttribs[i];
689721
TotalInlineConstantSize += InlineCBAttr.NumConstants * sizeof(Uint32);
690722
}
691723

692-
// Initialize push constant data pointers array in the resource cache, use ResIndex to access actual PushConstantDataPtr later.
724+
// Initialize push constant data pointers array in the resource cache
725+
// Use TotalResources as the array size to allow direct indexing by ResIndex
693726
ResourceCache.InitializePushConstantDataPtrs(TotalResources);
694727

695-
// Initialize inline constant buffers array in the resource cache, use ResIndex to access actual InlineConstantBuffer later.
696-
ResourceCache.InitializeInlineConstantBuffers(TotalResources);
697-
698-
// Allocate memory for all inline constants
728+
// Allocate memory for all inline constants (CPU staging data)
729+
// Each SRB has its own copy of the staging data, but shares the GPU buffer
699730
void* pInlineConstantMemory = nullptr;
700731
if (TotalInlineConstantSize > 0)
701732
{
@@ -706,7 +737,7 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
706737
ResourceCache.SetInlineConstantMemory(CacheMemAllocator, pInlineConstantMemory);
707738
}
708739

709-
// Assign memory to each inline constant buffer and create per-SRB buffers
740+
// Assign staging memory to each inline constant buffer
710741
Uint8* pCurrentDataPtr = static_cast<Uint8*>(pInlineConstantMemory);
711742
for (Uint32 i = 0; i < m_NumInlineConstantBufferAttribs; ++i)
712743
{
@@ -718,40 +749,16 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
718749
// For push constants, store the data pointer in the resource cache
719750
// Each SRB has its own copy of push constant data
720751
ResourceCache.SetPushConstantDataPtr(InlineCBAttr.ResIndex, pCurrentDataPtr);
721-
pCurrentDataPtr += DataSize;
722752
}
723753
else
724754
{
725-
// For emulated inline constants, create a per-SRB buffer
726-
const PipelineResourceDesc& ResDesc = GetResourceDesc(InlineCBAttr.ResIndex);
727-
const ResourceAttribs& Attr = GetResourceAttribs(InlineCBAttr.ResIndex);
728-
729-
// Initialize the inline constant data in the resource cache
755+
// For emulated inline constants, initialize staging memory in the resource cache
756+
// The GPU buffer is shared from InlineCBAttr.pBuffer (created in CreateSetLayouts)
757+
const ResourceAttribs& Attr = GetResourceAttribs(InlineCBAttr.ResIndex);
730758
ResourceCache.InitializeInlineConstantBuffer(Attr.DescrSet, Attr.CacheOffset(CacheType),
731759
InlineCBAttr.NumConstants, pCurrentDataPtr);
732-
733-
// Create a per-SRB USAGE_DYNAMIC uniform buffer
734-
if (m_pDevice)
735-
{
736-
std::string Name = m_Desc.Name;
737-
Name += " - ";
738-
Name += ResDesc.Name;
739-
Name += " (SRB)";
740-
BufferDesc CBDesc;
741-
CBDesc.Name = Name.c_str();
742-
CBDesc.Size = DataSize;
743-
CBDesc.Usage = USAGE_DYNAMIC;
744-
CBDesc.BindFlags = BIND_UNIFORM_BUFFER;
745-
CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
746-
747-
RefCntAutoPtr<IBuffer> pBuffer;
748-
m_pDevice->CreateBuffer(CBDesc, nullptr, &pBuffer);
749-
VERIFY_EXPR(pBuffer);
750-
ResourceCache.SetInlineConstantBuffer(InlineCBAttr.ResIndex, RefCntAutoPtr<BufferVkImpl>{pBuffer, IID_BufferVk});
751-
}
752-
753-
pCurrentDataPtr += DataSize;
754760
}
761+
pCurrentDataPtr += DataSize;
755762
}
756763
}
757764

@@ -771,8 +778,9 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
771778
ResourceCache.AssignDescriptorSetAllocation(GetDescriptorSetIndex<DESCRIPTOR_SET_ID_STATIC_MUTABLE>(), std::move(SetAllocation));
772779
}
773780

774-
// Bind internal inline constant buffers to the resource cache
781+
// Bind shared inline constant buffers to the resource cache
775782
// This must be done after descriptor set allocation so that descriptor writes work correctly
783+
// The buffers are created in CreateSetLayouts() and shared by all SRBs (similar to D3D11)
776784
for (Uint32 i = 0; i < m_NumInlineConstantBufferAttribs; ++i)
777785
{
778786
const InlineConstantBufferAttribsVk& InlineCBAttr = m_InlineConstantBufferAttribs[i];
@@ -781,8 +789,8 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
781789
if (InlineCBAttr.IsPushConstant)
782790
continue;
783791

784-
// Get the per-SRB buffer from the resource cache
785-
BufferVkImpl* pBuffer = ResourceCache.GetInlineConstantBuffer(InlineCBAttr.ResIndex);
792+
// Get the shared buffer from the Signature (created in CreateSetLayouts)
793+
BufferVkImpl* pBuffer = InlineCBAttr.pBuffer.RawPtr();
786794
if (!pBuffer)
787795
continue;
788796

@@ -796,7 +804,7 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
796804
// Note: Dynamic descriptor sets are allocated per-draw call, so we can't write to them here
797805
if (ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
798806
{
799-
// Bind the internal uniform buffer to the resource cache
807+
// Bind the shared uniform buffer to the resource cache
800808
ResourceCache.SetResource(
801809
&GetDevice()->GetLogicalDevice(),
802810
Attr.DescrSet,
@@ -1363,19 +1371,20 @@ void PipelineResourceSignatureVkImpl::UpdateInlineConstantBuffers(const ShaderRe
13631371
continue;
13641372
}
13651373

1366-
// For emulated inline constants, get the per-SRB buffer from the resource cache
1367-
BufferVkImpl* pBuffer = ResourceCache.GetInlineConstantBuffer(InlineCBAttr.ResIndex);
1374+
// For emulated inline constants, get the shared buffer from the Signature
1375+
// All SRBs share this buffer (similar to D3D11 backend)
1376+
BufferVkImpl* pBuffer = InlineCBAttr.pBuffer.RawPtr();
13681377

13691378
if (pBuffer)
13701379
{
1371-
// Get data from the resource cache using the correct CacheOffset
1372-
// Similar to D3D11 backend which uses BindPoints to locate the resource
1380+
// Get data from the SRB's resource cache using the correct CacheOffset
1381+
// Each SRB has its own CPU staging data, but shares the GPU buffer
13731382
const ResourceAttribs& Attr = GetResourceAttribs(InlineCBAttr.ResIndex);
13741383
const Uint32 CacheOffset = Attr.CacheOffset(CacheType);
13751384
const void* pInlineConstantData = ResourceCache.GetInlineConstantData(Attr.DescrSet, CacheOffset);
13761385
VERIFY_EXPR(pInlineConstantData != nullptr);
13771386

1378-
// Map the buffer and copy the data
1387+
// Map the shared buffer and copy the data
13791388
void* pMappedData = nullptr;
13801389
Ctx.MapBuffer(pBuffer, MAP_WRITE, MAP_FLAG_DISCARD, pMappedData);
13811390
memcpy(pMappedData, pInlineConstantData, DataSize);

Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,8 @@ PipelineResourceSignatureDescWrapper PipelineStateVkImpl::GetDefaultResourceSign
690690
PipelineResourceDesc& Res = const_cast<PipelineResourceDesc&>(SignDesc.Get().Resources[i]);
691691
if ((Res.Flags & PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) != 0)
692692
{
693-
Res.Flags |= PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT;
693+
//TODO: making first inline constant a push constant will lead to assert on CreateSetLayouts
694+
//Res.Flags |= PIPELINE_RESOURCE_FLAG_VULKAN_PUSH_CONSTANT;
694695
break;
695696
}
696697
}

0 commit comments

Comments
 (0)