Skip to content

Commit

Permalink
Extend Vk Depth Test Overlays
Browse files Browse the repository at this point in the history
Support shader exported depth by replaying using the capture pixel shader to determine passing pixels
  • Loading branch information
Zorro666 committed Nov 7, 2023
1 parent a53a5fa commit e5ccab1
Show file tree
Hide file tree
Showing 5 changed files with 600 additions and 23 deletions.
298 changes: 281 additions & 17 deletions renderdoc/driver/vulkan/vk_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ struct ConciseGraphicsPipeline
};

static void create(WrappedVulkan *driver, const char *objName, const int line, VkPipeline *pipe,
const ConciseGraphicsPipeline &info)
const ConciseGraphicsPipeline &info,
const VkPipelineDepthStencilStateCreateInfo &depthStencil)
{
// if the module didn't compile, this pipeline is not be supported. Silently don't create it, code
// later should handle the missing pipeline as indicating lack of support
Expand Down Expand Up @@ -260,21 +261,6 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V
msaa.sampleShadingEnable = true;
}

const VkPipelineDepthStencilStateCreateInfo depthStencil = {
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
NULL,
0,
info.depthEnable,
info.depthEnable,
VK_COMPARE_OP_ALWAYS,
false,
info.stencilEnable,
{info.stencilOp, info.stencilOp, info.stencilOp, VK_COMPARE_OP_ALWAYS, 0xff, 0xff, 0},
{info.stencilOp, info.stencilOp, info.stencilOp, VK_COMPARE_OP_ALWAYS, 0xff, 0xff, 0},
0.0f,
1.0f,
};

const VkPipelineColorBlendAttachmentState colAttach = {
info.blendEnable,
// colour blending
Expand Down Expand Up @@ -360,6 +346,27 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V
RDCERR("Failed creating object %s at line %i, vkr was %s", objName, line, ToStr(vkr).c_str());
}

static void create(WrappedVulkan *driver, const char *objName, const int line, VkPipeline *pipe,
const ConciseGraphicsPipeline &info)
{
const VkPipelineDepthStencilStateCreateInfo depthStencil = {
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
NULL,
0,
info.depthEnable,
info.depthEnable,
VK_COMPARE_OP_ALWAYS,
false,
info.stencilEnable,
{info.stencilOp, info.stencilOp, info.stencilOp, VK_COMPARE_OP_ALWAYS, 0xff, 0xff, 0},
{info.stencilOp, info.stencilOp, info.stencilOp, VK_COMPARE_OP_ALWAYS, 0xff, 0xff, 0},
0.0f,
1.0f,
};

create(driver, objName, line, pipe, info, depthStencil);
}

// utility macro that lets us check for VkResult failures inside the utility helpers while
// preserving context from outside
#define CREATE_OBJECT(obj, ...) create(driver, #obj, __LINE__, &obj, __VA_ARGS__)
Expand Down Expand Up @@ -3825,6 +3832,8 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
CREATE_OBJECT(SRGBA8RP, VK_FORMAT_R8G8B8A8_SRGB);
CREATE_OBJECT(SRGBA8MSRP, VK_FORMAT_R8G8B8A8_SRGB, VULKAN_MESH_VIEW_SAMPLES);

CREATE_OBJECT(m_PointSampler, VK_FILTER_NEAREST);

CREATE_OBJECT(m_CheckerDescSetLayout,
{{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_ALL, NULL}});

Expand All @@ -3839,12 +3848,19 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
{2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_ALL, NULL},
});

CREATE_OBJECT(m_DepthCopyDescSetLayout, {
{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1,
VK_SHADER_STAGE_ALL, &m_PointSampler},
});

CREATE_OBJECT(m_CheckerPipeLayout, m_CheckerDescSetLayout, 0);
CREATE_OBJECT(m_QuadResolvePipeLayout, m_QuadDescSetLayout, 0);
CREATE_OBJECT(m_TriSizePipeLayout, m_TriSizeDescSetLayout, 0);
CREATE_OBJECT(m_DepthCopyPipeLayout, m_DepthCopyDescSetLayout, 0);
CREATE_OBJECT(m_QuadDescSet, descriptorPool, m_QuadDescSetLayout);
CREATE_OBJECT(m_TriSizeDescSet, descriptorPool, m_TriSizeDescSetLayout);
CREATE_OBJECT(m_CheckerDescSet, descriptorPool, m_CheckerDescSetLayout);
CREATE_OBJECT(m_DepthCopyDescSet, descriptorPool, m_DepthCopyDescSetLayout);

m_CheckerUBO.Create(driver, driver->GetDev(), 128, 10, 0);
RDCCOMPILE_ASSERT(sizeof(CheckerboardUBOData) <= 128, "checkerboard UBO size");
Expand Down Expand Up @@ -3899,7 +3915,7 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
else
continue;

// if we this sample count is supported then create a pipeline
// if know we this sample count is supported then create a pipeline
pipeInfo.renderPass = RGBA16MSRP;
pipeInfo.sampleCount = VkSampleCountFlagBits(1 << i);

Expand All @@ -3924,9 +3940,240 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
driver->vkDestroyRenderPass(driver->GetDev(), RGBA16MSRP, NULL);
}

samplesHandled = 0;
{
ConciseGraphicsPipeline DepthCopyPipeInfo = {
SRGBA8RP,
m_DepthCopyPipeLayout,
shaderCache->GetBuiltinModule(BuiltinShader::BlitVS),
shaderCache->GetBuiltinModule(BuiltinShader::DepthCopyFS),
{VK_DYNAMIC_STATE_VIEWPORT},
VK_SAMPLE_COUNT_1_BIT,
false, // sampleRateShading
true, // depthEnable
true, // stencilEnable
VK_STENCIL_OP_ZERO,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_DST_ALPHA,
VK_BLEND_FACTOR_ONE,
0x0, // writeMask
};

VkAttachmentReference colRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkAttachmentReference dsRef = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};

VkAttachmentDescription attDescs[] = {
{0, VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE, colRef.layout, colRef.layout},
{0, VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_1_BIT, // will patch this just below
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE, dsRef.layout, dsRef.layout},
};

VkSubpassDescription subp = {
0, VK_PIPELINE_BIND_POINT_GRAPHICS,
0, NULL, // inputs
1, &colRef, // color
NULL, // resolve
&dsRef, // depth-stencil
0, NULL, // preserve
};

VkRenderPassCreateInfo rpinfo = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
NULL,
0,
2,
attDescs,
1,
&subp,
0,
NULL, // dependencies
};

if(DepthCopyPipeInfo.fragment != VK_NULL_HANDLE)
{
for(VkFormat fmt : {VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT})
{
VkPipeline *pipelines = m_DepthCopyPipeline[fmt];
attDescs[1].format = fmt;
for(size_t i = 0; i < 8; i++)
{
VkSampleCountFlagBits samples = VkSampleCountFlagBits(1 << i);

if((supportedSampleCounts & (uint32_t)samples) == 0)
continue;

VkRenderPass DEPTHMSRP = VK_NULL_HANDLE;
attDescs[0].samples = samples;
attDescs[1].samples = samples;
VkResult vkr = driver->vkCreateRenderPass(driver->GetDev(), &rpinfo, NULL, &DEPTHMSRP);
if(vkr != VK_SUCCESS)
RDCERR("Failed to create depth overlay resolve render pass: %s", ToStr(vkr).c_str());

if(DEPTHMSRP != VK_NULL_HANDLE)
samplesHandled |= (uint32_t)samples;
else
continue;

// if we know this sample count is supported then create a pipeline
DepthCopyPipeInfo.renderPass = DEPTHMSRP;
DepthCopyPipeInfo.sampleCount = VkSampleCountFlagBits(1 << i);

if(i == 0)
DepthCopyPipeInfo.fragment = shaderCache->GetBuiltinModule(BuiltinShader::DepthCopyFS);
else
DepthCopyPipeInfo.fragment = shaderCache->GetBuiltinModule(BuiltinShader::DepthCopyMSFS);

CREATE_OBJECT(pipelines[i], DepthCopyPipeInfo);

driver->vkDestroyRenderPass(driver->GetDev(), DEPTHMSRP, NULL);
}
}
}
}
RDCASSERTEQUAL((uint32_t)driver->GetDeviceProps().limits.framebufferColorSampleCounts,
samplesHandled);

samplesHandled = 0;
{
// make patched shader
VkShaderModule greenFSmod = VK_NULL_HANDLE;
float green[] = {0.0f, 1.0f, 0.0f, 1.0f};
driver->GetDebugManager()->PatchFixedColShader(greenFSmod, green);

CREATE_OBJECT(m_DepthResolvePipeLayout, VK_NULL_HANDLE, 0);

ConciseGraphicsPipeline DepthResolvePipeInfo = {
SRGBA8RP,
m_DepthResolvePipeLayout,
shaderCache->GetBuiltinModule(BuiltinShader::BlitVS),
greenFSmod,
{VK_DYNAMIC_STATE_VIEWPORT},
VK_SAMPLE_COUNT_1_BIT,
false, // sampleRateShading
false, // depthEnable
true, // stencilEnable
VK_STENCIL_OP_KEEP,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_DST_ALPHA,
VK_BLEND_FACTOR_ONE,
0xf, // writeMask
};

const VkPipelineDepthStencilStateCreateInfo depthStencil = {
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
NULL,
0,
false,
false,
VK_COMPARE_OP_ALWAYS,
false,
true,
{VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xff, 0x0,
1},
{VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xff, 0x0,
1},
0.0f,
1.0f,
};

VkAttachmentReference colRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkAttachmentReference dsRef = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};

VkAttachmentDescription attDescs[] = {
{0, VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE, colRef.layout, colRef.layout},
{0, VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_1_BIT, // will patch this just below
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, dsRef.layout, dsRef.layout},
};

VkSubpassDescription subp = {
0, VK_PIPELINE_BIND_POINT_GRAPHICS,
0, NULL, // inputs
1, &colRef, // color
NULL, // resolve
&dsRef, // depth-stencil
0, NULL, // preserve
};

VkRenderPassCreateInfo rpinfo = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
NULL,
0,
2,
attDescs,
1,
&subp,
0,
NULL, // dependencies
};

if(DepthResolvePipeInfo.fragment != VK_NULL_HANDLE)
{
for(VkFormat fmt : {VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT})
{
VkPipeline *pipelines = m_DepthResolvePipeline[fmt];
attDescs[1].format = fmt;
for(size_t i = 0; i < 8; i++)
{
VkSampleCountFlagBits samples = VkSampleCountFlagBits(1 << i);

if((supportedSampleCounts & (uint32_t)samples) == 0)
continue;

VkRenderPass RGBA16MSRP = VK_NULL_HANDLE;
attDescs[0].samples = samples;
attDescs[1].samples = samples;
VkResult vkr = driver->vkCreateRenderPass(driver->GetDev(), &rpinfo, NULL, &RGBA16MSRP);
if(vkr != VK_SUCCESS)
RDCERR("Failed to create depth overlay resolve render pass: %s", ToStr(vkr).c_str());

if(RGBA16MSRP != VK_NULL_HANDLE)
samplesHandled |= (uint32_t)samples;
else
continue;

// if know we this sample count is supported then create a pipeline
DepthResolvePipeInfo.renderPass = RGBA16MSRP;
DepthResolvePipeInfo.sampleCount = VkSampleCountFlagBits(1 << i);

CREATE_OBJECT(pipelines[i], DepthResolvePipeInfo, depthStencil);

driver->vkDestroyRenderPass(driver->GetDev(), RGBA16MSRP, NULL);
}
}
}
}

RDCASSERTEQUAL((uint32_t)driver->GetDeviceProps().limits.framebufferColorSampleCounts,
samplesHandled);

m_DefaultDepthStencilFormat = VK_FORMAT_UNDEFINED;
{
for(VkFormat fmt : {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT})
{
VkImageFormatProperties imgprops = {};
VkResult vkr = driver->vkGetPhysicalDeviceImageFormatProperties(
driver->GetPhysDev(), fmt, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &imgprops);
if(vkr == VK_SUCCESS)
{
m_DefaultDepthStencilFormat = fmt;
break;
}
}
}
if(m_DefaultDepthStencilFormat == VK_FORMAT_UNDEFINED)
{
RDCERR("Overlay failed to find default depth stencil format");
}

VkDescriptorBufferInfo checkerboard = {};
m_CheckerUBO.FillDescriptor(checkerboard);

Expand Down Expand Up @@ -3959,6 +4206,21 @@ void VulkanReplay::OverlayRendering::Destroy(WrappedVulkan *driver)
for(size_t i = 0; i < ARRAY_COUNT(m_QuadResolvePipeline); i++)
driver->vkDestroyPipeline(driver->GetDev(), m_QuadResolvePipeline[i], NULL);

driver->vkDestroyPipelineLayout(driver->GetDev(), m_DepthResolvePipeLayout, NULL);
for(auto it = m_DepthResolvePipeline.begin(); it != m_DepthResolvePipeline.end(); it++)
{
for(size_t i = 0; i < 8; i++)
driver->vkDestroyPipeline(driver->GetDev(), it->second[i], NULL);
}

driver->vkDestroyDescriptorSetLayout(driver->GetDev(), m_DepthCopyDescSetLayout, NULL);
driver->vkDestroyPipelineLayout(driver->GetDev(), m_DepthCopyPipeLayout, NULL);
for(auto it = m_DepthCopyPipeline.begin(); it != m_DepthCopyPipeline.end(); it++)
{
for(size_t i = 0; i < 8; i++)
driver->vkDestroyPipeline(driver->GetDev(), it->second[i], NULL);
}

driver->vkDestroyDescriptorSetLayout(driver->GetDev(), m_CheckerDescSetLayout, NULL);
driver->vkDestroyPipelineLayout(driver->GetDev(), m_CheckerPipeLayout, NULL);
for(size_t i = 0; i < ARRAY_COUNT(m_CheckerF16Pipeline); i++)
Expand All @@ -3971,6 +4233,8 @@ void VulkanReplay::OverlayRendering::Destroy(WrappedVulkan *driver)
m_TriSizeUBO.Destroy();
driver->vkDestroyDescriptorSetLayout(driver->GetDev(), m_TriSizeDescSetLayout, NULL);
driver->vkDestroyPipelineLayout(driver->GetDev(), m_TriSizePipeLayout, NULL);

driver->vkDestroySampler(driver->GetDev(), m_PointSampler, NULL);
}

void VulkanReplay::MeshRendering::Init(WrappedVulkan *driver, VkDescriptorPool descriptorPool)
Expand Down
Loading

0 comments on commit e5ccab1

Please sign in to comment.