From 315d4a8d4f37bc595b9e167098e623c0dd82f661 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 17 Jun 2025 12:21:39 +0100 Subject: [PATCH] Add handling for descriptor buffers to shader feedback --- .../driver/vulkan/vk_shader_feedback.cpp | 117 ++++++++++++------ 1 file changed, 78 insertions(+), 39 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_shader_feedback.cpp b/renderdoc/driver/vulkan/vk_shader_feedback.cpp index 2f5cb3b3d..61bf4812b 100644 --- a/renderdoc/driver/vulkan/vk_shader_feedback.cpp +++ b/renderdoc/driver/vulkan/vk_shader_feedback.cpp @@ -45,6 +45,27 @@ RDOC_CONFIG(uint32_t, Vulkan_Debug_PrintfBufferSize, 64 * 1024, static const uint32_t ShaderStageHeaderBitShift = 28U; static const uint32_t ShaderFeedbackReservedBindings = 1; +VkDescriptorType MakeVkDescriptorType(DescriptorType type, bool inputAttachment) +{ + switch(type) + { + case DescriptorType::Unknown: return VK_DESCRIPTOR_TYPE_MAX_ENUM; + case DescriptorType::Buffer: return VK_DESCRIPTOR_TYPE_MAX_ENUM; + case DescriptorType::ConstantBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + case DescriptorType::Sampler: return VK_DESCRIPTOR_TYPE_SAMPLER; + case DescriptorType::ImageSampler: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + case DescriptorType::Image: + return inputAttachment ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + case DescriptorType::TypedBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + case DescriptorType::ReadWriteImage: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + case DescriptorType::ReadWriteTypedBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + case DescriptorType::ReadWriteBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + case DescriptorType::AccelerationStructure: + return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + } + return VK_DESCRIPTOR_TYPE_MAX_ENUM; +} + struct BindKey { bool operator<(const BindKey &o) const @@ -59,9 +80,6 @@ struct BindKey ShaderStage stage; ShaderBindIndex index; - - // unused as key, here for convenience when looking up bindings - uint32_t arraySize; }; struct BindData @@ -1564,6 +1582,7 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId) ShaderReflection *stageRefls[NumShaderStages] = {}; { + const rdcarray &descBufs = state.descBufs; const rdcarray &descSets = (result.compute ? state.compute.descSets : state.graphics.descSets); @@ -1571,36 +1590,26 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId) for(size_t set = 0; set < pipeInfo.descSetLayouts.size(); set++) descLayouts.push_back(&creationInfo.m_DescSetLayout[pipeInfo.descSetLayouts[set]]); - auto processBinding = [this, &descLayouts, &descSets, &feedbackData]( - ShaderStage stage, DescriptorType type, uint16_t index, - uint32_t bindset, uint32_t bind, uint32_t arraySize) { + auto processBinding = [this, &descLayouts, &descBufs, &descSets, &feedbackData]( + ShaderStage stage, DescriptorType type, bool inputAttachment, + uint16_t index, uint32_t bindset, uint32_t bind, uint32_t arraySize) { // only process array bindings if(arraySize <= 1) return; BindKey key; key.stage = stage; - key.arraySize = arraySize; key.index.category = CategoryForDescriptorType(type); key.index.index = index; key.index.arrayElement = 0; if(bindset >= descLayouts.size() || !descLayouts[bindset] || bindset >= descSets.size() || - descSets[bindset].descSet == ResourceId()) + !descSets[bindset].IsBound()) { RDCERR("Invalid set %u referenced by %s shader", bindset, ToStr(key.stage).c_str()); return; } - ResourceId descSet = descSets[bindset].descSet; - - if(bind >= descLayouts[bindset]->bindings.size()) - { - RDCERR("Invalid binding %u in set %u referenced by %s shader", bind, bindset, - ToStr(key.stage).c_str()); - return; - } - // VkShaderStageFlagBits and ShaderStageMask are identical bit-for-bit. if((descLayouts[bindset]->bindings[bind].stageFlags & (VkShaderStageFlags)MaskForStage(key.stage)) == 0) @@ -1610,26 +1619,55 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId) return; } - if(descLayouts[bindset]->bindings[bind].variableSize) - { - auto it = m_pDriver->m_DescriptorSetState.find(descSet); - if(it != m_pDriver->m_DescriptorSetState.end()) - arraySize = it->second.data.variableDescriptorCount; - } - else if(arraySize == ~0U) - { - // if the array was unbounded, clamp it to the size of the descriptor set - arraySize = descLayouts[bindset]->bindings[bind].descriptorCount; - } - DescriptorAccess access; access.stage = key.stage; access.type = type; access.index = index; - access.descriptorStore = m_pDriver->GetResourceManager()->GetOriginalID(descSet); - access.byteOffset = - descLayouts[bindset]->bindings[bind].elemOffset + descLayouts[bindset]->inlineByteSize; - access.byteSize = 1; + + if(descSets[bindset].descSet == ResourceId()) + { + ResourceId id; + uint64_t offs = 0; + m_pDriver->GetResIDFromAddr(descBufs[descSets[bindset].descBufferIdx].address, id, offs); + access.descriptorStore = m_pDriver->GetResourceManager()->GetOriginalID(id); + access.byteOffset += uint32_t(offs + descSets[bindset].descBufferOffset) + + descLayouts[bindset]->bindings[bind].elemOffset; + access.byteSize = m_pDriver->DescriptorDataSize(MakeVkDescriptorType(type, inputAttachment)); + + if(descLayouts[bindset]->bindings[bind].variableSize || arraySize == ~0U) + { + arraySize = uint32_t((m_pDriver->m_CreationInfo.m_Buffer[id].size - access.byteOffset) / + access.byteSize); + } + } + else + { + ResourceId descSet = descSets[bindset].descSet; + + if(bind >= descLayouts[bindset]->bindings.size()) + { + RDCERR("Invalid binding %u in set %u referenced by %s shader", bind, bindset, + ToStr(key.stage).c_str()); + return; + } + + if(descLayouts[bindset]->bindings[bind].variableSize) + { + auto it = m_pDriver->m_DescriptorSetState.find(descSet); + if(it != m_pDriver->m_DescriptorSetState.end()) + arraySize = it->second.data.variableDescriptorCount; + } + else if(arraySize == ~0U) + { + // if the array was unbounded, clamp it to the size of the descriptor set + arraySize = descLayouts[bindset]->bindings[bind].descriptorCount; + } + + access.descriptorStore = m_pDriver->GetResourceManager()->GetOriginalID(descSet); + access.byteOffset = + descLayouts[bindset]->bindings[bind].elemOffset + descLayouts[bindset]->inlineByteSize; + access.byteSize = 1; + } feedbackData.offsetMap[key] = {feedbackData.feedbackStorageSize, arraySize, access}; @@ -1644,25 +1682,26 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId) stageRefls[(uint32_t)sh.refl->stage] = sh.refl; for(uint32_t i = 0; i < sh.refl->constantBlocks.size(); i++) - processBinding(sh.refl->stage, DescriptorType::ConstantBuffer, i & 0xffff, + processBinding(sh.refl->stage, DescriptorType::ConstantBuffer, false, i & 0xffff, sh.refl->constantBlocks[i].fixedBindSetOrSpace, sh.refl->constantBlocks[i].fixedBindNumber, sh.refl->constantBlocks[i].bindArraySize); for(uint32_t i = 0; i < sh.refl->samplers.size(); i++) - processBinding(sh.refl->stage, DescriptorType::Sampler, i & 0xffff, + processBinding(sh.refl->stage, DescriptorType::Sampler, false, i & 0xffff, sh.refl->samplers[i].fixedBindSetOrSpace, sh.refl->samplers[i].fixedBindNumber, sh.refl->samplers[i].bindArraySize); for(uint32_t i = 0; i < sh.refl->readOnlyResources.size(); i++) - processBinding(sh.refl->stage, sh.refl->readOnlyResources[i].descriptorType, i & 0xffff, + processBinding(sh.refl->stage, sh.refl->readOnlyResources[i].descriptorType, + sh.refl->readOnlyResources[i].isInputAttachment, i & 0xffff, sh.refl->readOnlyResources[i].fixedBindSetOrSpace, sh.refl->readOnlyResources[i].fixedBindNumber, sh.refl->readOnlyResources[i].bindArraySize); for(uint32_t i = 0; i < sh.refl->readWriteResources.size(); i++) - processBinding(sh.refl->stage, sh.refl->readWriteResources[i].descriptorType, i & 0xffff, - sh.refl->readWriteResources[i].fixedBindSetOrSpace, + processBinding(sh.refl->stage, sh.refl->readWriteResources[i].descriptorType, false, + i & 0xffff, sh.refl->readWriteResources[i].fixedBindSetOrSpace, sh.refl->readWriteResources[i].fixedBindNumber, sh.refl->readWriteResources[i].bindArraySize); } @@ -1805,7 +1844,7 @@ bool VulkanReplay::FetchShaderFeedback(uint32_t eventId) result.access.push_back(access); } - access.byteOffset++; + access.byteOffset += access.byteSize; } }