diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 74a50cd35..59c37ddd1 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -4079,6 +4079,21 @@ bool WrappedVulkan::ContextProcessChunk(ReadSerialiser &ser, VulkanChunk chunk) return true; } +void WrappedVulkan::CopyInternalDescriptor(VkCommandBuffer unwrappedCmdBuf, VkBuffer unwrappedSrc, + uint32_t size) +{ + VkBufferCopy bufCopy = {}; + bufCopy.size = size; + + for(ResourceId id : m_ResourceDescBuffers) + { + VkBuffer dst = Unwrap(GetResourceManager()->GetCurrentHandle(id)); + bufCopy.dstOffset = m_CreationInfo.m_Buffer[id].size; + + ObjDisp(m_Device)->CmdCopyBuffer(unwrappedCmdBuf, unwrappedSrc, dst, 1, &bufCopy); + } +} + bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk) { switch(chunk) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 8025f7318..10b70b0a4 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -529,6 +529,7 @@ private: bool m_NULLDescriptorPatternSaved = false; bool m_IgnoreLayoutForDescriptors = false; uint32_t m_ResourceDescriptorBufferReserveSize = 0; + rdcarray m_ResourceDescBuffers; std::unordered_map m_InlineBuffers; bool m_SeparateDepthStencil = false; @@ -1205,6 +1206,8 @@ private: void CaptureQueueSubmit(VkQueue queue, const rdcarray &commandBuffers, VkFence fence); + void CopyInternalDescriptor(VkCommandBuffer unwrappedCmdBuf, VkBuffer unwrappedSrc, uint32_t size); + CommandBufferNode *BuildSubmitTree(ResourceId cmdId, uint32_t curEvent, CommandBufferNode *rootNode = NULL); diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index ecae980a2..5fa15bc2e 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -72,7 +72,8 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V static void create(WrappedVulkan *driver, const char *objName, const int line, VkDescriptorSetLayout *descLayout, - std::initializer_list bindings) + std::initializer_list bindings, + VkDescriptorSetLayoutCreateFlags flags = 0) { VkDescriptorSetLayoutCreateInfo descsetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, @@ -82,6 +83,8 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, bindings.begin(), }; + descsetLayoutInfo.flags = flags; + VkResult vkr = driver->vkCreateDescriptorSetLayout(driver->GetDev(), &descsetLayoutInfo, NULL, descLayout); if(vkr != VK_SUCCESS) @@ -1762,6 +1765,13 @@ uint32_t VulkanReplay::PickVertex(uint32_t eventId, int32_t width, int32_t heigh return ret; } +const VulkanCreationInfo::Buffer &VulkanDebugManager::GetBufferInfo(ResourceId img) const +{ + auto it = m_pDriver->m_CreationInfo.m_Buffer.find(img); + RDCASSERT(it != m_pDriver->m_CreationInfo.m_Buffer.end()); + return it->second; +} + const VulkanCreationInfo::Image &VulkanDebugManager::GetImageInfo(ResourceId img) const { auto it = m_pDriver->m_CreationInfo.m_Image.find(img); @@ -4467,6 +4477,17 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo {0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_ALL, NULL}, }); + if(driver->DescriptorBuffers()) + { + CREATE_OBJECT(m_QuadDescBufLayout, + { + {0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_ALL, NULL}, + }, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); + + m_QuadDescriptor.Create(driver, driver->GetDev(), MaxDescriptorSize, 1, 0); + } + CREATE_OBJECT(m_TriSizeDescSetLayout, { {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_ALL, NULL}, @@ -4909,10 +4930,13 @@ void VulkanReplay::OverlayRendering::Destroy(WrappedVulkan *driver) driver->vkDestroyRenderPass(driver->GetDev(), NoDepthRP, NULL); driver->vkDestroyDescriptorSetLayout(driver->GetDev(), m_QuadDescSetLayout, NULL); + driver->vkDestroyDescriptorSetLayout(driver->GetDev(), m_QuadDescBufLayout, NULL); driver->vkDestroyPipelineLayout(driver->GetDev(), m_QuadResolvePipeLayout, NULL); for(size_t i = 0; i < ARRAY_COUNT(m_QuadResolvePipeline); i++) driver->vkDestroyPipeline(driver->GetDev(), m_QuadResolvePipeline[i], NULL); + m_QuadDescriptor.Destroy(); + driver->vkDestroyPipelineLayout(driver->GetDev(), m_DepthResolvePipeLayout, NULL); driver->vkDestroyDescriptorSetLayout(driver->GetDev(), m_DepthCopyDescSetLayout, NULL); driver->vkDestroyPipelineLayout(driver->GetDev(), m_DepthCopyPipeLayout, NULL); diff --git a/renderdoc/driver/vulkan/vk_debug.h b/renderdoc/driver/vulkan/vk_debug.h index a502b306f..a2a9b1561 100644 --- a/renderdoc/driver/vulkan/vk_debug.h +++ b/renderdoc/driver/vulkan/vk_debug.h @@ -114,6 +114,7 @@ public: VkImageLayout GetImageLayout(ResourceId image, VkImageAspectFlagBits aspect, uint32_t mip, uint32_t slice); + const VulkanCreationInfo::Buffer &GetBufferInfo(ResourceId img) const; const VulkanCreationInfo::Image &GetImageInfo(ResourceId img) const; const VulkanCreationInfo::ImageView &GetImageViewInfo(ResourceId imgView) const; const VulkanCreationInfo::Pipeline &GetPipelineInfo(ResourceId pipe) const; diff --git a/renderdoc/driver/vulkan/vk_overlay.cpp b/renderdoc/driver/vulkan/vk_overlay.cpp index 0674325ad..51bff6797 100644 --- a/renderdoc/driver/vulkan/vk_overlay.cpp +++ b/renderdoc/driver/vulkan/vk_overlay.cpp @@ -45,11 +45,12 @@ RDOC_EXTERN_CONFIG(bool, Vulkan_Debug_SingleSubmitFlushing); struct VulkanQuadOverdrawCallback : public VulkanActionCallback { VulkanQuadOverdrawCallback(WrappedVulkan *vk, VkDescriptorSetLayout descSetLayout, - VkDescriptorSet descSet, const rdcarray &events, - bool multiview) + VkDescriptorSet descSet, VkDescriptorSetLayout descBufLayout, + const rdcarray &events, bool multiview) : m_pDriver(vk), m_DescSetLayout(descSetLayout), m_DescSet(descSet), + m_DescBufLayout(descBufLayout), m_Events(events), m_Multiview(multiview) { @@ -92,6 +93,8 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback CachedPipeline pipe = m_PipelineCache[pipestate.graphics.pipeline]; CachedShader shad = m_ShaderCache[pipestate.shaderObjects[4]]; + bool descBuf = false; + // if we don't get a hit, create a modified pipeline if(pipestate.graphics.shaderObject ? shad.shad == VK_NULL_HANDLE : pipe.pipe == VK_NULL_HANDLE) { @@ -120,8 +123,13 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback descSetLayouts[i] = m_pDriver->GetResourceManager()->GetCurrentHandle( origDescSetLayouts[i]); - // this layout has storage image and - descSetLayouts[descSet] = m_DescSetLayout; + // this layout has storage image + descBuf = (p.flags & VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT) != 0; + + if(descBuf) + descSetLayouts[descSet] = m_DescBufLayout; + else + descSetLayouts[descSet] = m_DescSetLayout; // don't have to handle separate vert/frag layouts as push constant ranges must be identical const rdcarray &push = layout.pushRanges; @@ -286,18 +294,64 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback pipestate.shaderObjects[4] = GetResID(shad.shad); pipestate.graphics.lastBoundSet = shad.descSet; pipestate.graphics.pipeline = ResourceId(); + RDCASSERT(pipestate.graphics.descSets.size() >= shad.descSet); - pipestate.graphics.descSets.resize(shad.descSet + 1); - pipestate.graphics.descSets[shad.descSet].pipeLayout = GetResID(shad.pipeLayout); - pipestate.graphics.descSets[shad.descSet].descSet = GetResID(m_DescSet); + pipestate.graphics.descSets.resize_for_index(shad.descSet); + VulkanStatePipeline::DescriptorAndOffsets &descSet = pipestate.graphics.descSets[shad.descSet]; + + descSet.pipeLayout = GetResID(shad.pipeLayout); + if(descBuf) + { + descSet.descBufferEmbeddedSamplers = false; + + for(uint32_t i = 0; i < pipestate.descBufs.size(); i++) + { + if(pipestate.descBufs[i].usage & VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) + { + descSet.descBufferIdx = i; + ResourceId id; + uint64_t ignored = 0; + m_pDriver->GetResIDFromAddr(pipestate.descBufs[i].address, id, ignored); + descSet.descBufferOffset = m_pDriver->GetDebugManager()->GetBufferInfo(id).size; + break; + } + } + } + else + { + descSet.descSet = GetResID(m_DescSet); + } } else { pipestate.graphics.pipeline = GetResID(pipe.pipe); + RDCASSERT(pipestate.graphics.descSets.size() >= pipe.descSet); - pipestate.graphics.descSets.resize(pipe.descSet + 1); - pipestate.graphics.descSets[pipe.descSet].pipeLayout = GetResID(pipe.pipeLayout); - pipestate.graphics.descSets[pipe.descSet].descSet = GetResID(m_DescSet); + pipestate.graphics.descSets.resize_for_index(pipe.descSet); + VulkanStatePipeline::DescriptorAndOffsets &descSet = pipestate.graphics.descSets[pipe.descSet]; + + descSet.pipeLayout = GetResID(pipe.pipeLayout); + if(descBuf) + { + descSet.descBufferEmbeddedSamplers = false; + + for(uint32_t i = 0; i < pipestate.descBufs.size(); i++) + { + if(pipestate.descBufs[i].usage & VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) + { + descSet.descBufferIdx = i; + ResourceId id; + uint64_t ignored = 0; + m_pDriver->GetResIDFromAddr(pipestate.descBufs[i].address, id, ignored); + descSet.descBufferOffset = m_pDriver->GetDebugManager()->GetBufferInfo(id).size; + break; + } + } + } + else + { + descSet.descSet = GetResID(m_DescSet); + } } // modify dynamic state @@ -405,6 +459,7 @@ struct VulkanQuadOverdrawCallback : public VulkanActionCallback WrappedVulkan *m_pDriver; VkDescriptorSetLayout m_DescSetLayout; VkDescriptorSet m_DescSet; + VkDescriptorSetLayout m_DescBufLayout; const rdcarray &m_Events; bool m_Multiview; @@ -3057,10 +3112,48 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D m_pDriver->ReplayLog(0, events[0], eReplay_WithoutDraw); + // fill descriptor here so that initial contents doesn't overwrite it + if(m_pDriver->DescriptorBuffers()) + { + VkDescriptorGetInfoEXT info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, + NULL, + }; + + VkDescriptorImageInfo imginfo = {}; + info.type = write.descriptorType; + info.data.pStorageImage = &imdesc; + + VkDeviceSize offs = 0; + vt->GetDescriptorSetLayoutBindingOffsetEXT(Unwrap(m_Device), + Unwrap(m_Overlay.m_QuadDescBufLayout), 0, &offs); + uint32_t size = m_pDriver->DescriptorDataSize(info.type); + vt->GetDescriptorEXT(Unwrap(m_Device), &info, size, + ((byte *)m_Overlay.m_QuadDescriptor.Map()) + offs); + m_Overlay.m_QuadDescriptor.Unmap(); + + cmd = m_pDriver->GetNextCmd(); + + vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + CHECK_VKR(m_pDriver, vkr); + + // since we don't know which resource descriptor buffers the application is going to use when, + // we copy our descriptor into the end of every single one so it will be available no matter what + m_pDriver->CopyInternalDescriptor(Unwrap(cmd), m_Overlay.m_QuadDescriptor.UnwrappedBuffer(), + size); + + vkr = vt->EndCommandBuffer(Unwrap(cmd)); + CHECK_VKR(m_pDriver, vkr); + + m_pDriver->SubmitCmds(); + m_pDriver->FlushQ(); + } + { // declare callback struct here VulkanQuadOverdrawCallback cb(m_pDriver, m_Overlay.m_QuadDescSetLayout, - m_Overlay.m_QuadDescSet, events, multiviewMask > 0); + m_Overlay.m_QuadDescSet, m_Overlay.m_QuadDescBufLayout, + events, multiviewMask > 0); m_pDriver->ReplayLog(events.front(), events.back(), eReplay_Full); diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index eea1b457d..cd7ac1212 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -735,9 +735,11 @@ private: GPUBuffer m_CheckerUBO; VkDescriptorSetLayout m_QuadDescSetLayout = VK_NULL_HANDLE; + VkDescriptorSetLayout m_QuadDescBufLayout = VK_NULL_HANDLE; VkDescriptorSet m_QuadDescSet = VK_NULL_HANDLE; VkPipelineLayout m_QuadResolvePipeLayout = VK_NULL_HANDLE; VkPipeline m_QuadResolvePipeline[8] = {VK_NULL_HANDLE}; + GPUBuffer m_QuadDescriptor; VkDescriptorSetLayout m_DepthCopyDescSetLayout = VK_NULL_HANDLE; VkDescriptorSet m_DepthCopyDescSet = VK_NULL_HANDLE; diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index c9a2cc16c..ac236f16b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -1935,6 +1935,9 @@ bool WrappedVulkan::Serialise_vkCreateBuffer(SerialiserType &ser, VkDevice devic m_DeviceAddressResources.IDs.push_back(GetResID(buf)); } + if(patchedusage & VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) + m_ResourceDescBuffers.push_back(GetResID(buf)); + if(CreateInfo.flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT)) {