@@ -417,18 +417,17 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts(const bool IsSerialized)
417417
418418 if (!IsPushConstant && m_pDevice)
419419 {
420- // Create a USAGE_STAGING uniform buffer for emulating inline constants.
421- // Using USAGE_STAGING ensures the buffer has a backing VkBuffer resource with
422- // persistently mapped host-visible memory, avoiding Dynamic Buffer ID reuse issues
423- // that can occur with USAGE_DYNAMIC buffers (which suballocate from dynamic heap).
420+ // Create a USAGE_DYNAMIC uniform buffer for emulating inline constants.
424421 // All SRBs created from this signature will share the same inline constant buffer.
422+ // Note: DvpValidateCommittedResource skips dynamic allocation verification for
423+ // inline constant buffers to avoid Dynamic Buffer ID reuse validation issues.
425424 std::string Name = m_Desc.Name ;
426425 Name += " - " ;
427426 Name += ResDesc.Name ;
428427 BufferDesc CBDesc;
429428 CBDesc.Name = Name.c_str ();
430429 CBDesc.Size = ResDesc.ArraySize * sizeof (Uint32);
431- CBDesc.Usage = USAGE_STAGING ;
430+ CBDesc.Usage = USAGE_DYNAMIC ;
432431 CBDesc.BindFlags = BIND_UNIFORM_BUFFER;
433432 CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
434433
@@ -689,7 +688,7 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
689688 {
690689 // Ensure the cache reports inline constants so DeviceContextVkImpl
691690 // updates emulated buffers even if no data has been written yet.
692- // ResourceCache.MarkHasInlineConstants();
691+ ResourceCache.MarkHasInlineConstants ();
693692
694693 // Count push constant buffers and calculate total memory size
695694 Uint32 NumPushConstantBuffers = 0 ;
@@ -1198,7 +1197,16 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const DeviceC
11981197 // is bound. It will be null if the type is incorrect.
11991198 if (const BufferVkImpl* pBufferVk = Res.pObject .RawPtr <BufferVkImpl>())
12001199 {
1201- pDeviceCtx->DvpVerifyDynamicAllocation (pBufferVk);
1200+ // Skip dynamic allocation verification for inline constant buffers.
1201+ // These are internal buffers managed by the signature and are updated
1202+ // via UpdateInlineConstantBuffers() before each draw/dispatch.
1203+ // The Dynamic Buffer ID may be reused after PSO recreation (e.g., from cache),
1204+ // which would cause false validation failures.
1205+ const bool IsInlineConstantBuffer = (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_INLINE_CONSTANTS) != 0 ;
1206+ if (!IsInlineConstantBuffer)
1207+ {
1208+ pDeviceCtx->DvpVerifyDynamicAllocation (pBufferVk);
1209+ }
12021210
12031211 if ((pBufferVk->GetDesc ().Size < SPIRVAttribs.BufferStaticSize ) &&
12041212 (GetDevice ()->GetValidationFlags () & VALIDATION_FLAG_CHECK_SHADER_BUFFER_SIZE) != 0 )
@@ -1343,12 +1351,11 @@ void PipelineResourceSignatureVkImpl::UpdateInlineConstantBuffers(const ShaderRe
13431351 const void * pInlineConstantData = ResourceCache.GetInlineConstantData (InlineCBAttr.DescrSet , InlineCBAttr.BindingIndex );
13441352 VERIFY_EXPR (pInlineConstantData != nullptr );
13451353
1346- // Copy data directly to the buffer's CPU address.
1347- // USAGE_STAGING buffer has a backing VkBuffer resource with persistently mapped
1348- // host-visible memory, so we can write directly without Map/Unmap.
1349- void * pDstData = InlineCBAttr.pBuffer ->GetCPUAddress ();
1350- VERIFY_EXPR (pDstData != nullptr );
1351- memcpy (pDstData, pInlineConstantData, DataSize);
1354+ // Map the buffer and copy the data
1355+ void * pMappedData = nullptr ;
1356+ Ctx.MapBuffer (InlineCBAttr.pBuffer , MAP_WRITE, MAP_FLAG_DISCARD, pMappedData);
1357+ memcpy (pMappedData, pInlineConstantData, DataSize);
1358+ Ctx.UnmapBuffer (InlineCBAttr.pBuffer , MAP_WRITE);
13521359 continue ;
13531360 }
13541361 }
0 commit comments