From ccd99a5a91b08eab21e7d3e58c174e1535dd6d67 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 13 Jun 2025 11:22:25 +0100 Subject: [PATCH] Handle descriptor buffers when processing descriptor accesses --- renderdoc/driver/vulkan/vk_common.cpp | 31 +++ renderdoc/driver/vulkan/vk_common.h | 3 + renderdoc/driver/vulkan/vk_core.cpp | 32 +-- renderdoc/driver/vulkan/vk_core.h | 4 +- renderdoc/driver/vulkan/vk_info.cpp | 182 ++++++++++++++---- renderdoc/driver/vulkan/vk_info.h | 16 +- renderdoc/driver/vulkan/vk_manager.cpp | 5 + renderdoc/driver/vulkan/vk_manager.h | 2 + renderdoc/driver/vulkan/vk_replay.cpp | 65 +++++-- .../vulkan/wrappers/vk_descriptor_funcs.cpp | 26 ++- .../vulkan/wrappers/vk_device_funcs.cpp | 18 ++ .../vulkan/wrappers/vk_resource_funcs.cpp | 7 + 12 files changed, 301 insertions(+), 90 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 133f7b2f2..510d09799 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -1645,6 +1645,37 @@ void DescriptorSetSlot::AccumulateBindRefs(DescriptorBindRefs &refs, VulkanResou } } +uint32_t DescriptorDataSize(const VkPhysicalDeviceDescriptorBufferPropertiesEXT &descSizes, + VkDescriptorType type) +{ + size_t ret = 0; + + switch(type) + { + case VK_DESCRIPTOR_TYPE_SAMPLER: ret = descSizes.samplerDescriptorSize; break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + ret = descSizes.combinedImageSamplerDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: ret = descSizes.inputAttachmentDescriptorSize; break; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: ret = descSizes.sampledImageDescriptorSize; break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: ret = descSizes.storageImageDescriptorSize; break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + ret = descSizes.uniformTexelBufferDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + ret = descSizes.storageTexelBufferDescriptorSize; + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: ret = descSizes.uniformBufferDescriptorSize; break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: ret = descSizes.storageBufferDescriptorSize; break; + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + ret = descSizes.accelerationStructureDescriptorSize; + break; + default: break; + } + + return (uint32_t)ret; +} + void DynamicRenderingLocalRead::Init(const VkBaseInStructure *infoStruct) { const VkRenderingAttachmentLocationInfo *attachmentLocationInfo = diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index ea3fcbff1..750064a90 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -918,6 +918,9 @@ DECLARE_REFLECTION_STRUCT(DescriptorSetSlot); constexpr uint64_t FixedOpaqueDescriptorCaptureSize = 16; constexpr uint64_t MaxDescriptorSize = 256; +uint32_t DescriptorDataSize(const VkPhysicalDeviceDescriptorBufferPropertiesEXT &descSizes, + VkDescriptorType type); + struct OpaqueDataForSerialising : VkOpaqueCaptureDescriptorDataCreateInfoEXT { OpaqueDataForSerialising() diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 990710ed6..1d393808a 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -209,8 +209,6 @@ WrappedVulkan::WrappedVulkan() m_FrameCaptureRecord = NULL; ResourceIDGen::SetReplayResourceIDs(); - - m_CreationInfo.pushConstantDescriptorStorage = ResourceIDGen::GetNewUniqueID(); } } @@ -5427,35 +5425,9 @@ ResourceId WrappedVulkan::GetASFromAddr(VkDeviceAddress addr) return m_ASLookupByAddr[addr]; } -size_t WrappedVulkan::DescriptorDataSize(VkDescriptorType type) +uint32_t WrappedVulkan::DescriptorDataSize(VkDescriptorType type) { - size_t ret = 0; - - const VkPhysicalDeviceDescriptorBufferPropertiesEXT &descSizes = m_DescriptorBufferProperties; - switch(type) - { - case VK_DESCRIPTOR_TYPE_SAMPLER: ret = descSizes.samplerDescriptorSize; break; - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - ret = descSizes.combinedImageSamplerDescriptorSize; - break; - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: ret = descSizes.inputAttachmentDescriptorSize; break; - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: ret = descSizes.sampledImageDescriptorSize; break; - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: ret = descSizes.storageImageDescriptorSize; break; - case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: - ret = descSizes.uniformTexelBufferDescriptorSize; - break; - case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - ret = descSizes.storageTexelBufferDescriptorSize; - break; - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: ret = descSizes.uniformBufferDescriptorSize; break; - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: ret = descSizes.storageBufferDescriptorSize; break; - case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: - ret = descSizes.accelerationStructureDescriptorSize; - break; - default: break; - } - - return ret; + return ::DescriptorDataSize(m_DescriptorBufferProperties, type); } void WrappedVulkan::EstimateDescriptorFormats() diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index b800a3c48..92ad02819 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -463,7 +463,6 @@ private: }; VkPhysicalDeviceDescriptorBufferPropertiesEXT m_DescriptorBufferProperties; - size_t DescriptorDataSize(VkDescriptorType type); Threading::CriticalSection m_ASLookupByAddrLock; rdcflatmap m_ASLookupByAddr; @@ -529,6 +528,7 @@ private: bool m_NULLDescriptorPatternSaved = false; bool m_IgnoreLayoutForDescriptors = false; + std::unordered_map m_InlineBuffers; bool m_SeparateDepthStencil = false; bool m_NULLDescriptorsAllowed = false; @@ -1494,6 +1494,8 @@ public: static VkResult GetProvidedInstanceExtensionProperties(uint32_t *pPropertyCount, VkExtensionProperties *pProperties); + uint32_t DescriptorDataSize(VkDescriptorType type); + VkBufferCreateFlags DefaultBufferCreateFlags() { return DescriptorBuffers() ? VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT : 0; diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index 9c2fb7e26..11f8d4afe 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -30,6 +30,11 @@ // for compatibility we use the same DXBC name since it's now configured by the UI RDOC_EXTERN_CONFIG(rdcarray, DXBC_Debug_SearchDirPaths); +ResourceId VulkanCreationInfo::pushConstantDescriptorStorage; +rdcarray VulkanCreationInfo::descriptorSetStorage; +rdcarray VulkanCreationInfo::descriptorBufferStorage; +rdcarray VulkanCreationInfo::inlineBufferStorage; + VkDynamicState ConvertDynamicState(VulkanDynamicStateIndex idx) { switch(idx) @@ -316,8 +321,10 @@ static VkGraphicsPipelineLibraryFlagsEXT DynamicStateValidState(VkDynamicState s } void DescSetLayout::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, - const VkDescriptorSetLayoutCreateInfo *pCreateInfo) + ResourceId id, const VkDescriptorSetLayoutCreateInfo *pCreateInfo) { + resourceId = id; + dynamicCount = 0; inlineCount = 0; inlineByteSize = 0; @@ -825,9 +832,10 @@ bool CreateDescriptorWritesForSlotData(WrappedVulkan *vk, rdcarray &descriptorAccess, - rdcarray setLayoutInfos) const +void ProcessStaticDescriptorAccess(VulkanResourceManager *resourceMan, ShaderReflection *refl, + ResourceId specStorage, + rdcarray &descriptorAccess, + rdcarray setLayoutInfos) { if(!refl) return; @@ -837,8 +845,7 @@ void VulkanCreationInfo::ShaderEntry::ProcessStaticDescriptorAccess( DescriptorAccess access; access.stage = refl->stage; - // we will store the descriptor set in byteSize to be decoded into descriptorStore later - access.byteSize = 0; + // desciptor set storage is fake, so byteSize is just 1 descriptorAccess.reserve(descriptorAccess.size() + refl->constantBlocks.size() + refl->samplers.size() + refl->readOnlyResources.size() + @@ -857,19 +864,19 @@ void VulkanCreationInfo::ShaderEntry::ProcessStaticDescriptorAccess( if(!bind.bufferBacked) { + access.byteSize = 1; + if(bind.compileConstants) { // spec constants access.descriptorStore = specStorage; - access.byteSize = 1; access.byteOffset = 0; descriptorAccess.push_back(access); } else { // push constants - access.descriptorStore = pushStorage; - access.byteSize = 1; + access.descriptorStore = VulkanCreationInfo::pushConstantDescriptorStorage; access.byteOffset = 0; descriptorAccess.push_back(access); } @@ -881,19 +888,44 @@ void VulkanCreationInfo::ShaderEntry::ProcessStaticDescriptorAccess( bind.fixedBindNumber >= setLayoutInfos[bind.fixedBindSetOrSpace]->bindings.size()) continue; - access.descriptorStore = ResourceId(); + const DescSetLayout *setLayout = setLayoutInfos[bind.fixedBindSetOrSpace]; // VkShaderStageFlagBits and ShaderStageMask are identical bit-for-bit. // this might be deliberate if the binding is never actually used dynamically, only // statically used bindings must be declared - if((setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].stageFlags & + if((setLayout->bindings[bind.fixedBindNumber].stageFlags & (VkShaderStageFlags)MaskForStage(refl->stage)) == 0) continue; - access.byteSize = bind.fixedBindSetOrSpace; - access.byteOffset = - setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset + - setLayoutInfos[bind.fixedBindSetOrSpace]->inlineByteSize; + if((setLayout->flags & (VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT)) == + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT) + { + if(setLayout->bindings[bind.fixedBindNumber].layoutDescType == + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) + { + access.descriptorStore = VulkanCreationInfo::inlineBufferStorage[bind.fixedBindSetOrSpace]; + access.byteSize = setLayout->bindings[bind.fixedBindNumber].descriptorCount; + } + else + { + access.descriptorStore = + VulkanCreationInfo::descriptorBufferStorage[bind.fixedBindSetOrSpace]; + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + } + + // we are only handling non-arrays here + access.byteOffset = setLayout->bindings[bind.fixedBindNumber].elemOffset; + } + else + { + access.descriptorStore = VulkanCreationInfo::descriptorSetStorage[bind.fixedBindSetOrSpace]; + access.byteSize = 1; + access.byteOffset = + setLayout->bindings[bind.fixedBindNumber].elemOffset + setLayout->inlineByteSize; + } + descriptorAccess.push_back(access); } } @@ -913,19 +945,43 @@ void VulkanCreationInfo::ShaderEntry::ProcessStaticDescriptorAccess( bind.fixedBindNumber >= setLayoutInfos[bind.fixedBindSetOrSpace]->bindings.size()) continue; + const DescSetLayout *setLayout = setLayoutInfos[bind.fixedBindSetOrSpace]; + // VkShaderStageFlagBits and ShaderStageMask are identical bit-for-bit. // this might be deliberate if the binding is never actually used dynamically, only // statically used bindings must be declared - if((setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].stageFlags & + if((setLayout->bindings[bind.fixedBindNumber].stageFlags & (VkShaderStageFlags)MaskForStage(refl->stage)) == 0) continue; access.type = DescriptorType::Sampler; access.index = i; - access.byteSize = bind.fixedBindSetOrSpace; - access.byteOffset = - setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset + - setLayoutInfos[bind.fixedBindSetOrSpace]->inlineByteSize; + + if((setLayout->flags & (VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT)) == + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT) + { + access.descriptorStore = VulkanCreationInfo::descriptorBufferStorage[bind.fixedBindSetOrSpace]; + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_SAMPLER); + + // we are only handling non-arrays here + access.byteOffset = setLayout->bindings[bind.fixedBindNumber].elemOffset; + } + else if(setLayout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT) + { + access.descriptorStore = resourceMan->GetOriginalID(setLayout->resourceId); + access.byteSize = 1; + access.byteOffset = bind.fixedBindNumber; + } + else + { + access.descriptorStore = VulkanCreationInfo::descriptorSetStorage[bind.fixedBindSetOrSpace]; + access.byteSize = 1; + access.byteOffset = + setLayout->bindings[bind.fixedBindNumber].elemOffset + setLayout->inlineByteSize; + } + descriptorAccess.push_back(access); } @@ -942,19 +998,47 @@ void VulkanCreationInfo::ShaderEntry::ProcessStaticDescriptorAccess( bind.fixedBindNumber >= setLayoutInfos[bind.fixedBindSetOrSpace]->bindings.size()) continue; + const DescSetLayout *setLayout = setLayoutInfos[bind.fixedBindSetOrSpace]; + // VkShaderStageFlagBits and ShaderStageMask are identical bit-for-bit. // this might be deliberate if the binding is never actually used dynamically, only // statically used bindings must be declared - if((setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].stageFlags & + if((setLayout->bindings[bind.fixedBindNumber].stageFlags & (VkShaderStageFlags)MaskForStage(refl->stage)) == 0) continue; access.type = refl->readOnlyResources[i].descriptorType; access.index = i; - access.byteSize = bind.fixedBindSetOrSpace; - access.byteOffset = - setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset + - setLayoutInfos[bind.fixedBindSetOrSpace]->inlineByteSize; + + if((setLayout->flags & (VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT)) == + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT) + { + access.descriptorStore = VulkanCreationInfo::descriptorBufferStorage[bind.fixedBindSetOrSpace]; + if(bind.isInputAttachment) + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT); + else if(bind.hasSampler) + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + else if(bind.isTexture) + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + else if(bind.descriptorType == DescriptorType::AccelerationStructure) + access.byteSize = + resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR); + else + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + + // we are only handling non-arrays here + access.byteOffset = setLayout->bindings[bind.fixedBindNumber].elemOffset; + } + else + { + access.descriptorStore = VulkanCreationInfo::descriptorSetStorage[bind.fixedBindSetOrSpace]; + access.byteSize = 1; + access.byteOffset = + setLayout->bindings[bind.fixedBindNumber].elemOffset + setLayout->inlineByteSize; + } + descriptorAccess.push_back(access); } @@ -971,19 +1055,42 @@ void VulkanCreationInfo::ShaderEntry::ProcessStaticDescriptorAccess( bind.fixedBindNumber >= setLayoutInfos[bind.fixedBindSetOrSpace]->bindings.size()) continue; + const DescSetLayout *setLayout = setLayoutInfos[bind.fixedBindSetOrSpace]; + // VkShaderStageFlagBits and ShaderStageMask are identical bit-for-bit. // this might be deliberate if the binding is never actually used dynamically, only // statically used bindings must be declared - if((setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].stageFlags & + if((setLayout->bindings[bind.fixedBindNumber].stageFlags & (VkShaderStageFlags)MaskForStage(refl->stage)) == 0) continue; access.type = refl->readWriteResources[i].descriptorType; access.index = i; - access.byteSize = bind.fixedBindSetOrSpace; - access.byteOffset = - setLayoutInfos[bind.fixedBindSetOrSpace]->bindings[bind.fixedBindNumber].elemOffset + - setLayoutInfos[bind.fixedBindSetOrSpace]->inlineByteSize; + + if((setLayout->flags & (VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT)) == + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT) + { + access.descriptorStore = VulkanCreationInfo::descriptorBufferStorage[bind.fixedBindSetOrSpace]; + if(bind.isTexture) + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + else if(bind.descriptorType == DescriptorType::ReadWriteTypedBuffer) + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); + else + access.byteSize = resourceMan->DescriptorDataSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + + // we are only handling non-arrays here + access.byteOffset = setLayout->bindings[bind.fixedBindNumber].elemOffset; + } + else + { + access.descriptorStore = VulkanCreationInfo::descriptorSetStorage[bind.fixedBindSetOrSpace]; + access.byteSize = 1; + access.byteOffset = + setLayout->bindings[bind.fixedBindNumber].elemOffset + setLayout->inlineByteSize; + } + descriptorAccess.push_back(access); } } @@ -1066,9 +1173,8 @@ void VulkanCreationInfo::ShaderObject::Init(VulkanResourceManager *resourceMan, for(ResourceId setLayout : descSetLayouts) setLayoutInfos.push_back(&info.m_DescSetLayout[setLayout]); - shad.ProcessStaticDescriptorAccess(info.pushConstantDescriptorStorage, - resourceMan->GetOriginalID(id), staticDescriptorAccess, - setLayoutInfos); + ProcessStaticDescriptorAccess(resourceMan, shad.refl, resourceMan->GetOriginalID(id), + staticDescriptorAccess, setLayoutInfos); } void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, @@ -1765,9 +1871,8 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, setLayoutInfos.push_back(&info.m_DescSetLayout[setLayout]); for(const ShaderEntry &shad : shaders) - shad.ProcessStaticDescriptorAccess(info.pushConstantDescriptorStorage, - resourceMan->GetOriginalID(id), staticDescriptorAccess, - setLayoutInfos); + ProcessStaticDescriptorAccess(resourceMan, shad.refl, resourceMan->GetOriginalID(id), + staticDescriptorAccess, setLayoutInfos); } void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, @@ -1881,9 +1986,8 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk setLayoutInfos.push_back(&info.m_DescSetLayout[setLayout]); for(const ShaderEntry &shad : shaders) - shad.ProcessStaticDescriptorAccess(info.pushConstantDescriptorStorage, - resourceMan->GetOriginalID(id), staticDescriptorAccess, - setLayoutInfos); + ProcessStaticDescriptorAccess(resourceMan, shad.refl, resourceMan->GetOriginalID(id), + staticDescriptorAccess, setLayoutInfos); } void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index b1b1f0dd5..b875b5da8 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -36,7 +36,7 @@ VulkanDynamicStateIndex ConvertDynamicState(VkDynamicState state); struct DescSetLayout { - void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, + void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, ResourceId id, const VkDescriptorSetLayoutCreateInfo *pCreateInfo); void CreateBindingsArray(BindingStorage &bindingStorage, uint32_t variableAllocSize) const; @@ -121,6 +121,8 @@ struct DescSetLayout }; rdcarray bindings; + ResourceId resourceId; + // parallel array to bindings, with a bitmask of mutable types rdcarray mutableBitmasks; @@ -246,10 +248,6 @@ struct VulkanCreationInfo // VkPipelineShaderStageRequiredSubgroupSizeCreateInfo uint32_t requiredSubgroupSize = 0; - - void ProcessStaticDescriptorAccess(ResourceId pushStorage, ResourceId specStorage, - rdcarray &staticDescriptorAccess, - rdcarray setLayoutInfos) const; }; struct Pipeline @@ -612,6 +610,8 @@ struct VulkanCreationInfo bool external; VkMemoryRequirements mrq; + + ResourceId inlineDescriptorId; }; std::unordered_map m_Buffer; @@ -814,7 +814,11 @@ struct VulkanCreationInfo std::unordered_map m_Queue; // the fake ID of the 'command buffer' descriptor store for push constants - ResourceId pushConstantDescriptorStorage; + static ResourceId pushConstantDescriptorStorage; + // fake IDs for each set/buffer + static rdcarray descriptorSetStorage; + static rdcarray descriptorBufferStorage; + static rdcarray inlineBufferStorage; void erase(ResourceId id) { diff --git a/renderdoc/driver/vulkan/vk_manager.cpp b/renderdoc/driver/vulkan/vk_manager.cpp index 87a36ee66..c93fa53e7 100644 --- a/renderdoc/driver/vulkan/vk_manager.cpp +++ b/renderdoc/driver/vulkan/vk_manager.cpp @@ -908,6 +908,11 @@ ResourceId VulkanResourceManager::GetFirstIDForHandle(uint64_t handle) return ResourceId(); } +uint32_t VulkanResourceManager::DescriptorDataSize(VkDescriptorType type) +{ + return m_Core->DescriptorDataSize(type); +} + void VulkanResourceManager::MarkMemoryFrameReferenced(ResourceId mem, VkDeviceSize offset, VkDeviceSize size, FrameRefType refType) { diff --git a/renderdoc/driver/vulkan/vk_manager.h b/renderdoc/driver/vulkan/vk_manager.h index 43f208767..139dd4e3b 100644 --- a/renderdoc/driver/vulkan/vk_manager.h +++ b/renderdoc/driver/vulkan/vk_manager.h @@ -213,6 +213,8 @@ public: ResourceId GetFirstIDForHandle(uint64_t handle); + uint32_t DescriptorDataSize(VkDescriptorType type); + // easy path for getting the wrapped handle cast to the correct type template realtype GetLiveHandle(ResourceId origid) diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 9dcbd5198..94c84a39f 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -275,6 +275,8 @@ rdcarray VulkanReplay::GetPassEvents(uint32_t eventId) ResourceId VulkanReplay::GetLiveID(ResourceId id) { + if(m_pDriver->m_InlineBuffers.find(id) != m_pDriver->m_InlineBuffers.end()) + return id; if(!m_pDriver->GetResourceManager()->HasLiveResource(id)) return ResourceId(); return m_pDriver->GetResourceManager()->GetLiveID(id); @@ -2656,24 +2658,65 @@ rdcarray VulkanReplay::GetDescriptorAccess(uint32_t eventId) for(DescriptorAccess &access : ret) { - uint32_t bindset = (uint32_t)access.byteSize; - access.byteSize = 1; - if(access.descriptorStore == m_pDriver->m_CreationInfo.pushConstantDescriptorStorage) + if(access.descriptorStore == VulkanCreationInfo::pushConstantDescriptorStorage) { access.descriptorStore = m_pDriver->GetPushConstantCommandBuffer(); } - else if(access.descriptorStore == ResourceId()) + else { - const rdcarray &descSets = - access.stage == ShaderStage::Compute ? state.compute.descSets : state.graphics.descSets; + int setIdx = VulkanCreationInfo::descriptorSetStorage.indexOf(access.descriptorStore); + int bufSetIdx = VulkanCreationInfo::descriptorBufferStorage.indexOf(access.descriptorStore); + int inlinebufSetIdx = VulkanCreationInfo::inlineBufferStorage.indexOf(access.descriptorStore); + if(setIdx >= 0) + { + const rdcarray &descSets = + access.stage == ShaderStage::Compute ? state.compute.descSets : state.graphics.descSets; - if(bindset >= descSets.size()) - { - RDCERR("Unbound descriptor set referenced in static usage"); + access.byteSize = 1; + + if(setIdx >= descSets.count()) + { + RDCERR("Unbound descriptor set referenced in static usage"); + } + else + { + access.descriptorStore = rm->GetOriginalID(descSets[setIdx].descSet); + } } - else + else if(bufSetIdx >= 0 || inlinebufSetIdx >= 0) { - access.descriptorStore = rm->GetOriginalID(descSets[bindset].descSet); + const rdcarray &descSets = + access.stage == ShaderStage::Compute ? state.compute.descSets : state.graphics.descSets; + + // one will be -1 + int i = RDCMAX(bufSetIdx, inlinebufSetIdx); + + if(i >= descSets.count()) + { + RDCERR("Unbound descriptor set referenced in static usage"); + } + else + { + const VulkanStatePipeline::DescriptorAndOffsets &bufSet = descSets[i]; + + if(bufSet.descBufferEmbeddedSamplers) + { + access.descriptorStore = rm->GetOriginalID( + m_pDriver->m_CreationInfo.m_PipelineLayout[bufSet.pipeLayout].descSetLayouts[i]); + access.byteOffset = 0; + } + else + { + ResourceId id; + uint64_t offs = 0; + m_pDriver->GetResIDFromAddr(state.descBufs[bufSet.descBufferIdx].address, id, offs); + if(inlinebufSetIdx >= 0) + access.descriptorStore = m_pDriver->m_CreationInfo.m_Buffer[id].inlineDescriptorId; + else + access.descriptorStore = rm->GetOriginalID(id); + access.byteOffset += uint32_t(offs + bufSet.descBufferOffset); + } + } } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp index 51028866c..9f1e93659 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp @@ -429,7 +429,27 @@ bool WrappedVulkan::Serialise_vkCreateDescriptorSetLayout( live = GetResourceManager()->WrapResource(Unwrap(device), layout); GetResourceManager()->AddLiveResource(SetLayout, layout); - m_CreationInfo.m_DescSetLayout[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo); + m_CreationInfo.m_DescSetLayout[live].Init(GetResourceManager(), m_CreationInfo, live, + &CreateInfo); + + if((CreateInfo.flags & (VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT | + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)) == + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT) + { + // fetch actual offsets. Sizes we defer due to possible mutable descriptors + rdcarray &bindings = m_CreationInfo.m_DescSetLayout[live].bindings; + for(uint32_t b = 0; b < bindings.size(); b++) + { + if(bindings[b].layoutDescType == VK_DESCRIPTOR_TYPE_MAX_ENUM) + continue; + + VkDeviceSize offs = 0; + ObjDisp(device)->GetDescriptorSetLayoutBindingOffsetEXT(Unwrap(device), Unwrap(layout), + b, &offs); + bindings[b].elemOffset = offs & 0xffffffffU; + RDCASSERTEQUAL(bindings[b].elemOffset, offs); + } + } } AddResource(SetLayout, ResourceType::ShaderBinding, "Descriptor Layout"); @@ -485,7 +505,7 @@ VkResult WrappedVulkan::vkCreateDescriptorSetLayout(VkDevice device, record->descInfo = new DescriptorSetData(); record->descInfo->layout = new DescSetLayout(); - record->descInfo->layout->Init(GetResourceManager(), m_CreationInfo, pCreateInfo); + record->descInfo->layout->Init(GetResourceManager(), m_CreationInfo, id, pCreateInfo); for(uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { @@ -504,7 +524,7 @@ VkResult WrappedVulkan::vkCreateDescriptorSetLayout(VkDevice device, { GetResourceManager()->AddLiveResource(id, *pSetLayout); - m_CreationInfo.m_DescSetLayout[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo); + m_CreationInfo.m_DescSetLayout[id].Init(GetResourceManager(), m_CreationInfo, id, pCreateInfo); } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 782f03ee1..9ce2ba1dd 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -4370,10 +4370,28 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi m_PhysicalDeviceData.maxMemoryAllocationSize = 0x80000000U; } + VulkanCreationInfo::pushConstantDescriptorStorage = ResourceIDGen::GetNewUniqueID(); + VulkanCreationInfo::descriptorSetStorage.resize( + m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets); + for(size_t i = 0; i < VulkanCreationInfo::descriptorSetStorage.size(); i++) + VulkanCreationInfo::descriptorSetStorage[i] = ResourceIDGen::GetNewUniqueID(); + ChooseMemoryIndices(); if(DescriptorBuffers()) + { + VulkanCreationInfo::descriptorBufferStorage.resize( + m_DescriptorBufferProperties.maxDescriptorBufferBindings); + VulkanCreationInfo::inlineBufferStorage.resize( + m_DescriptorBufferProperties.maxDescriptorBufferBindings); + for(size_t i = 0; i < VulkanCreationInfo::descriptorBufferStorage.size(); i++) + { + VulkanCreationInfo::descriptorBufferStorage[i] = ResourceIDGen::GetNewUniqueID(); + VulkanCreationInfo::inlineBufferStorage[i] = ResourceIDGen::GetNewUniqueID(); + } + EstimateDescriptorFormats(); + } APIProps.vendor = GetDriverInfo().Vendor(); diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 17a973f38..4575dbe54 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -1914,6 +1914,13 @@ bool WrappedVulkan::Serialise_vkCreateBuffer(SerialiserType &ser, VkDevice devic m_CreationInfo.m_Buffer[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo, memoryRequirements); + + if(patchedusage & VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) + { + ResourceId inlineDescriptorId = m_CreationInfo.m_Buffer[live].inlineDescriptorId = + ResourceIDGen::GetNewUniqueID(); + m_InlineBuffers[inlineDescriptorId] = live; + } } if(patchedusage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)