Add support for quad overdraw overlay with descriptor buffers

This commit is contained in:
baldurk
2025-06-16 15:55:39 +01:00
parent 71437e2800
commit b7001986bc
7 changed files with 153 additions and 12 deletions
+15
View File
@@ -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<VkBuffer>(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)
+3
View File
@@ -529,6 +529,7 @@ private:
bool m_NULLDescriptorPatternSaved = false;
bool m_IgnoreLayoutForDescriptors = false;
uint32_t m_ResourceDescriptorBufferReserveSize = 0;
rdcarray<ResourceId> m_ResourceDescBuffers;
std::unordered_map<ResourceId, ResourceId> m_InlineBuffers;
bool m_SeparateDepthStencil = false;
@@ -1205,6 +1206,8 @@ private:
void CaptureQueueSubmit(VkQueue queue, const rdcarray<VkCommandBuffer> &commandBuffers,
VkFence fence);
void CopyInternalDescriptor(VkCommandBuffer unwrappedCmdBuf, VkBuffer unwrappedSrc, uint32_t size);
CommandBufferNode *BuildSubmitTree(ResourceId cmdId, uint32_t curEvent,
CommandBufferNode *rootNode = NULL);
+25 -1
View File
@@ -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<VkDescriptorSetLayoutBinding> bindings)
std::initializer_list<VkDescriptorSetLayoutBinding> 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);
+1
View File
@@ -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;
+104 -11
View File
@@ -45,11 +45,12 @@ RDOC_EXTERN_CONFIG(bool, Vulkan_Debug_SingleSubmitFlushing);
struct VulkanQuadOverdrawCallback : public VulkanActionCallback
{
VulkanQuadOverdrawCallback(WrappedVulkan *vk, VkDescriptorSetLayout descSetLayout,
VkDescriptorSet descSet, const rdcarray<uint32_t> &events,
bool multiview)
VkDescriptorSet descSet, VkDescriptorSetLayout descBufLayout,
const rdcarray<uint32_t> &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<VkDescriptorSetLayout>(
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<VkPushConstantRange> &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<uint32_t> &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);
+2
View File
@@ -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;
@@ -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))
{