@@ -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);
0 commit comments