From fa22c7c7fcd554e227d9866d0baf46d19cb037f2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Mar 2024 12:20:44 +0000 Subject: [PATCH] Report vulkan dynamic offsets separately for manual application * Baking these into descriptors when we get arbitrary 'GetDescriptor' queries independent of the bound descriptor sets is not possible - a descriptor set could be in theory bound twice to two places with different dynamic offsets. * Instead we report these as part of the pipeline states and the abstraction & replay API consumer will need to manually apply them to get the true buffer offset. * The offsets are indexed by descriptor storage byte offset for easier processing (the dynamic offset struct can be turned into a pair and used to initialise a dict) --- qrenderdoc/Code/pyrenderdoc/renderdoc.i | 1 + renderdoc/api/replay/vk_pipestate.h | 44 ++++++++++++++++++ renderdoc/driver/vulkan/vk_replay.cpp | 59 ++++++++++++++++++++++++ renderdoc/replay/renderdoc_serialise.inl | 13 +++++- 4 files changed, 116 insertions(+), 1 deletion(-) diff --git a/qrenderdoc/Code/pyrenderdoc/renderdoc.i b/qrenderdoc/Code/pyrenderdoc/renderdoc.i index 3609f9bfd..5bcb13ec8 100644 --- a/qrenderdoc/Code/pyrenderdoc/renderdoc.i +++ b/qrenderdoc/Code/pyrenderdoc/renderdoc.i @@ -419,6 +419,7 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, DescriptorAccess) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, Attachment) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, BindingElement) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DescriptorBinding) +TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DynamicOffset) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DescriptorSet) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, ImageData) TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, ImageLayout) diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index 248f93d67..5f5d0fbaa 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -314,6 +314,39 @@ If :data:`descriptorCount` is 1 then this list has only one element and the bind rdcarray binds; }; +DOCUMENT("A dynamic offset applied to a single descriptor access."); +struct DynamicOffset +{ + DOCUMENT(""); + DynamicOffset() = default; + DynamicOffset(const DynamicOffset &) = default; + DynamicOffset &operator=(const DynamicOffset &) = default; + + bool operator==(const DynamicOffset &o) const + { + return descriptorByteOffset == o.descriptorByteOffset && + dynamicBufferByteOffset == o.dynamicBufferByteOffset; + } + bool operator<(const DynamicOffset &o) const + { + if(!(descriptorByteOffset == o.descriptorByteOffset)) + return descriptorByteOffset < o.descriptorByteOffset; + if(!(dynamicBufferByteOffset == o.dynamicBufferByteOffset)) + return dynamicBufferByteOffset < o.dynamicBufferByteOffset; + return false; + } + DOCUMENT(R"(The offset in bytes to the descriptor in the storage. + +:type: int +)"); + uint64_t descriptorByteOffset = 0; + DOCUMENT(R"(The dynamic offset to apply to the buffer in bytes. + +:type: int +)"); + uint64_t dynamicBufferByteOffset = 0; +}; + DOCUMENT("The contents of a descriptor set."); struct DescriptorSet { @@ -363,6 +396,16 @@ offset and size into this buffer. :type: bytes )"); bytebuf inlineData; + + DOCUMENT(R"(A list of dynamic offsets to be applied to specific bindings, on top of the contents +of their descriptors. + +.. note:: + The returned values from :meth:`PipeState.GetConstantBuffer` already have these offsets applied. + +:type: List[VKDynamicOffset] +)"); + rdcarray dynamicOffsets; }; DOCUMENT("Describes the object and descriptor set bindings of a Vulkan pipeline object."); @@ -1477,6 +1520,7 @@ struct State DECLARE_REFLECTION_STRUCT(VKPipe::BindingElement); DECLARE_REFLECTION_STRUCT(VKPipe::DescriptorBinding); +DECLARE_REFLECTION_STRUCT(VKPipe::DynamicOffset); DECLARE_REFLECTION_STRUCT(VKPipe::DescriptorSet); DECLARE_REFLECTION_STRUCT(VKPipe::Pipeline); DECLARE_REFLECTION_STRUCT(VKPipe::IndexBuffer); diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 241bd619b..e1312ef34 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -2006,6 +2006,65 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) ret.graphics.descriptorSets.resize(state.graphics.descSets.size()); ret.compute.descriptorSets.resize(state.compute.descSets.size()); + // store dynamic offsets + { + rdcarray *dsts[] = { + &ret.graphics.descriptorSets, + &ret.compute.descriptorSets, + }; + + const rdcarray *srcs[] = { + &state.graphics.descSets, + &state.compute.descSets, + }; + + for(size_t p = 0; p < ARRAY_COUNT(srcs); p++) + { + for(size_t i = 0; i < srcs[p]->size(); i++) + { + const VulkanStatePipeline::DescriptorAndOffsets &srcData = srcs[p]->at(i); + ResourceId sourceSet = srcData.descSet; + const uint32_t *srcOffset = srcData.offsets.begin(); + VKPipe::DescriptorSet &destSet = dsts[p]->at(i); + + destSet.dynamicOffsets.clear(); + + if(sourceSet == ResourceId()) + continue; + + destSet.dynamicOffsets.reserve(srcData.offsets.size()); + + VKPipe::DynamicOffset dynOffset; + + const WrappedVulkan::DescriptorSetInfo &descSetState = + m_pDriver->m_DescriptorSetState[sourceSet]; + const DescriptorSetSlot *first = descSetState.data.binds[0]; + for(size_t b = 0; b < descSetState.data.binds.size(); b++) + { + const DescSetLayout::Binding &layoutBind = + c.m_DescSetLayout[descSetState.layout].bindings[b]; + + if(layoutBind.layoutDescType != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC && + layoutBind.layoutDescType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) + continue; + + uint64_t descriptorByteOffset = descSetState.data.binds[b] - first; + + // inline UBOs aren't dynamic and variable size can't be used with dynamic buffers, so the + // count is what it is at definition time + for(uint32_t a = 0; a < layoutBind.descriptorCount; a++) + { + dynOffset.descriptorByteOffset = descriptorByteOffset + a; + dynOffset.dynamicBufferByteOffset = *srcOffset; + srcOffset++; + + destSet.dynamicOffsets.push_back(dynOffset); + } + } + } + } + } + { rdcarray *dsts[] = { &ret.graphics.descriptorSets, diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index d56e29644..6c21f9c85 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -2138,6 +2138,15 @@ void DoSerialise(SerialiserType &ser, VKPipe::DescriptorBinding &el) SIZE_CHECK(48); } +template +void DoSerialise(SerialiserType &ser, VKPipe::DynamicOffset &el) +{ + SERIALISE_MEMBER(descriptorByteOffset); + SERIALISE_MEMBER(dynamicBufferByteOffset); + + SIZE_CHECK(16); +} + template void DoSerialise(SerialiserType &ser, VKPipe::DescriptorSet &el) { @@ -2149,7 +2158,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::DescriptorSet &el) SERIALISE_MEMBER(inlineData); - SIZE_CHECK(72); + SERIALISE_MEMBER(dynamicOffsets); + + SIZE_CHECK(96); } template