Extend Vk Depth Test Overlays

Support shader exported depth by replaying using the capture pixel shader to determine passing pixels
This commit is contained in:
Jake Turner
2023-08-11 11:10:34 +01:00
parent 1246f8007a
commit d72d79052a
5 changed files with 659 additions and 15 deletions
+326 -10
View File
@@ -195,6 +195,14 @@ static void create(WrappedVulkan *driver, const char *objName, const int line,
RDCERR("Failed creating object %s at line %i, vkr was %s", objName, line, ToStr(vkr).c_str());
}
enum class StencilMode
{
KEEP,
KEEP_TEST_EQUAL_ONE,
REPLACE,
WRITE_ZERO,
};
// a simpler one-shot descriptor containing anything we might want to vary in a graphics pipeline
struct ConciseGraphicsPipeline
{
@@ -214,7 +222,7 @@ struct ConciseGraphicsPipeline
// depth stencil
bool depthEnable;
bool stencilEnable;
VkStencilOp stencilOp;
StencilMode stencilOperations;
// color blend
bool colourOutput;
@@ -260,6 +268,34 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V
msaa.sampleShadingEnable = true;
}
VkCompareOp stencilTest = VK_COMPARE_OP_ALWAYS;
VkStencilOp stencilOp = VK_STENCIL_OP_KEEP;
uint8_t stencilReference = 0;
switch(info.stencilOperations)
{
case StencilMode::KEEP:
{
break;
}
case StencilMode::KEEP_TEST_EQUAL_ONE:
{
stencilTest = VK_COMPARE_OP_EQUAL;
stencilReference = 1;
break;
}
case StencilMode::REPLACE:
{
stencilOp = VK_STENCIL_OP_REPLACE;
break;
}
case StencilMode::WRITE_ZERO:
{
stencilOp = VK_STENCIL_OP_ZERO;
break;
}
};
const VkPipelineDepthStencilStateCreateInfo depthStencil = {
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
NULL,
@@ -269,8 +305,8 @@ static void create(WrappedVulkan *driver, const char *objName, const int line, V
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},
{stencilOp, stencilOp, stencilOp, stencilTest, 0xff, 0xff, stencilReference},
{stencilOp, stencilOp, stencilOp, stencilTest, 0xff, 0xff, stencilReference},
0.0f,
1.0f,
};
@@ -686,7 +722,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver)
true, // sampleRateShading
true, // depthEnable
true, // stencilEnable
VK_STENCIL_OP_REPLACE,
StencilMode::REPLACE,
false, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_ONE,
@@ -738,7 +774,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver)
false, // sampleRateShading
false, // depthEnable
false, // stencilEnable
VK_STENCIL_OP_REPLACE,
StencilMode::REPLACE,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_ONE,
@@ -1079,7 +1115,7 @@ void VulkanDebugManager::CreateCustomShaderPipeline(ResourceId shader, VkPipelin
false, // sampleRateShading
false, // depthEnable
false, // stencilEnable
VK_STENCIL_OP_KEEP,
StencilMode::KEEP,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_ONE,
@@ -2094,7 +2130,7 @@ void VulkanDebugManager::FillWithDiscardPattern(VkCommandBuffer cmd, DiscardType
false, // sampleRateShading
true, // depthEnable
true, // stencilEnable
VK_STENCIL_OP_REPLACE,
StencilMode::REPLACE,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_ONE,
@@ -3393,7 +3429,7 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
false, // sampleRateShading
false, // depthEnable
false, // stencilEnable
VK_STENCIL_OP_KEEP,
StencilMode::KEEP,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_ONE,
@@ -3840,6 +3876,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}});
@@ -3854,12 +3892,24 @@ 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");
@@ -3876,7 +3926,7 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
false, // sampleRateShading
false, // depthEnable
false, // stencilEnable
VK_STENCIL_OP_KEEP,
StencilMode::KEEP,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_SRC_ALPHA,
@@ -3914,7 +3964,7 @@ void VulkanReplay::OverlayRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
else
continue;
// if we this sample count is supported then create a pipeline
// if we know this sample count is supported then create a pipeline
pipeInfo.renderPass = RGBA16MSRP;
pipeInfo.sampleCount = VkSampleCountFlagBits(1 << i);
@@ -3939,9 +3989,260 @@ 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
StencilMode::WRITE_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
};
RDCCOMPILE_ASSERT(ARRAY_COUNT(m_DepthResolvePipeline) == ARRAY_COUNT(m_DepthResolvePipeline),
"m_DepthCopyPipeline size must match m_DepthResolvePipeline");
if(DepthCopyPipeInfo.fragment != VK_NULL_HANDLE)
{
for(size_t f = 0; f < ARRAY_COUNT(m_DepthCopyPipeline); ++f)
{
VkFormat fmt = (f == 0) ? VK_FORMAT_D24_UNORM_S8_UINT : VK_FORMAT_D32_SFLOAT_S8_UINT;
attDescs[1].format = fmt;
for(size_t i = 0; i < ARRAY_COUNT(m_DepthCopyPipeline[f]); ++i)
{
m_DepthCopyPipeline[f][i] = VK_NULL_HANDLE;
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(m_DepthCopyPipeline[f][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
StencilMode::KEEP_TEST_EQUAL_ONE,
true, // colourOutput
false, // blendEnable
VK_BLEND_FACTOR_DST_ALPHA,
VK_BLEND_FACTOR_ONE,
0xf, // 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_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(size_t f = 0; f < ARRAY_COUNT(m_DepthResolvePipeline); ++f)
{
VkFormat fmt = (f == 0) ? VK_FORMAT_D24_UNORM_S8_UINT : VK_FORMAT_D32_SFLOAT_S8_UINT;
attDescs[1].format = fmt;
for(size_t i = 0; i < ARRAY_COUNT(m_DepthResolvePipeline[f]); ++i)
{
m_DepthResolvePipeline[f][i] = VK_NULL_HANDLE;
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 we know this sample count is supported then create a pipeline
DepthResolvePipeInfo.renderPass = rgba16MSRP;
DepthResolvePipeInfo.sampleCount = VkSampleCountFlagBits(1 << i);
CREATE_OBJECT(m_DepthResolvePipeline[f][i], DepthResolvePipeInfo);
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);
@@ -3974,6 +4275,19 @@ 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);
driver->vkDestroyDescriptorSetLayout(driver->GetDev(), m_DepthCopyDescSetLayout, NULL);
driver->vkDestroyPipelineLayout(driver->GetDev(), m_DepthCopyPipeLayout, NULL);
for(size_t f = 0; f < ARRAY_COUNT(m_DepthResolvePipeline); ++f)
{
for(size_t i = 0; i < ARRAY_COUNT(m_DepthResolvePipeline[f]); ++i)
{
driver->vkDestroyPipeline(driver->GetDev(), m_DepthResolvePipeline[f][i], NULL);
driver->vkDestroyPipeline(driver->GetDev(), m_DepthCopyPipeline[f][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++)
@@ -3986,6 +4300,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)
+316 -5
View File
@@ -1189,7 +1189,6 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
VkPipelineShaderStageCreateInfo *fragShader = NULL;
for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++)
{
VkPipelineShaderStageCreateInfo &sh =
@@ -1567,6 +1566,9 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
}
else if(overlay == DebugOverlay::Depth || overlay == DebugOverlay::Stencil)
{
VkImage dsImage = VK_NULL_HANDLE;
VkDeviceMemory dsImageMem = VK_NULL_HANDLE;
float highlightCol[] = {0.0f, 0.0f, 0.0f, 0.0f};
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@@ -1595,6 +1597,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
{
vkr = vt->EndCommandBuffer(Unwrap(cmd));
CheckVkResult(vkr);
cmd = VK_NULL_HANDLE;
VkFramebuffer depthFB = VK_NULL_HANDLE;
VkRenderPass depthRP = VK_NULL_HANDLE;
@@ -1602,6 +1605,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
VulkanCreationInfo &createinfo = m_pDriver->m_CreationInfo;
ResourceId depthStencilView;
VkFormat dsFmt = VK_FORMAT_UNDEFINED;
if(state.dynamicRendering.active)
{
@@ -1624,8 +1628,17 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
}
}
bool useDepthWriteStencilPass = false;
bool needDepthCopyToDepthStencil = false;
size_t fmtIndex = ARRAY_COUNT(m_Overlay.m_DepthCopyPipeline);
size_t sampleIndex = SampleIndex(iminfo.samples);
if(depthStencilView != ResourceId())
{
if(overlay == DebugOverlay::Depth)
useDepthWriteStencilPass = true;
VkAttachmentDescription attDescs[] = {
{0, overlayFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
@@ -1642,7 +1655,41 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
ResourceId depthIm = depthViewInfo.image;
VulkanCreationInfo::Image &depthImageInfo = createinfo.m_Image[depthIm];
attDescs[1].format = depthImageInfo.format;
dsFmt = depthImageInfo.format;
VkFormat dsNewFmt = dsFmt;
if(useDepthWriteStencilPass)
{
if(dsFmt == VK_FORMAT_D32_SFLOAT_S8_UINT)
dsNewFmt = VK_FORMAT_D32_SFLOAT_S8_UINT;
else if(dsFmt == VK_FORMAT_D24_UNORM_S8_UINT)
dsNewFmt = VK_FORMAT_D24_UNORM_S8_UINT;
else if(dsFmt == VK_FORMAT_D32_SFLOAT)
dsNewFmt = VK_FORMAT_D32_SFLOAT_S8_UINT;
else if(dsFmt == VK_FORMAT_D16_UNORM)
dsNewFmt = m_Overlay.m_DefaultDepthStencilFormat;
else
dsNewFmt = m_Overlay.m_DefaultDepthStencilFormat;
RDCASSERT((dsNewFmt == VK_FORMAT_D24_UNORM_S8_UINT) ||
(dsNewFmt == VK_FORMAT_D32_SFLOAT_S8_UINT));
fmtIndex = (dsNewFmt == VK_FORMAT_D24_UNORM_S8_UINT) ? 0 : 1;
if(m_Overlay.m_DepthResolvePipeline[fmtIndex][sampleIndex] == 0)
{
RDCERR("Unhandled depth resolve format : %s", ToStr(dsNewFmt).c_str());
return ResourceId();
}
if(dsNewFmt != dsFmt)
{
needDepthCopyToDepthStencil = true;
if(m_Overlay.m_DepthCopyPipeline[fmtIndex][sampleIndex] == 0)
{
RDCERR("Unhandled depth copy format : %s", ToStr(dsNewFmt).c_str());
return ResourceId();
}
}
}
attDescs[1].format = dsNewFmt;
attDescs[0].samples = attDescs[1].samples = iminfo.samples;
{
@@ -1688,9 +1735,144 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
vkr = m_pDriver->vkCreateRenderPass(m_Device, &rpinfo, NULL, &depthRP);
CheckVkResult(vkr);
VkImageView dsView =
m_pDriver->GetResourceManager()->GetCurrentHandle<VkImageView>(depthStencilView);
if(needDepthCopyToDepthStencil)
{
VkImageSubresourceRange dsSubRange = {
VK_IMAGE_ASPECT_DEPTH_BIT, sub.mip, 1, sub.slice, sub.numSlices,
};
VkImage dsRealImage = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(depthIm);
VkImageViewCreateInfo dsViewInfo = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
NULL,
0,
dsRealImage,
VK_IMAGE_VIEW_TYPE_2D,
dsFmt,
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
dsSubRange,
};
vkr = m_pDriver->vkCreateImageView(m_Device, &dsViewInfo, NULL, &dsView);
// update descriptor to point to copy of original depth buffer
VkDescriptorImageInfo imdesc = {0};
imdesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
imdesc.sampler = VK_NULL_HANDLE;
imdesc.imageView = Unwrap(dsView);
VkWriteDescriptorSet write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
NULL,
Unwrap(m_Overlay.m_DepthCopyDescSet),
0,
0,
1,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
&imdesc,
NULL,
NULL,
};
vt->UpdateDescriptorSets(Unwrap(m_Device), 1, &write, 0, NULL);
// Create texture for new depth buffer
VkImageCreateInfo dsNewImInfo = {
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
NULL,
0,
VK_IMAGE_TYPE_2D,
dsNewFmt,
depthImageInfo.extent,
(uint32_t)depthImageInfo.mipLevels,
(uint32_t)depthImageInfo.arrayLayers,
depthImageInfo.samples,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
VK_SHARING_MODE_EXCLUSIVE,
0,
NULL,
VK_IMAGE_LAYOUT_UNDEFINED,
};
vkr = m_pDriver->vkCreateImage(m_Device, &dsNewImInfo, NULL, &dsImage);
CheckVkResult(vkr);
NameVulkanObject(dsImage, "Overlay Depth+Stencil Image");
VkMemoryRequirements mrq = {0};
m_pDriver->vkGetImageMemoryRequirements(m_Device, dsImage, &mrq);
VkMemoryAllocateInfo allocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
NULL,
mrq.size,
m_pDriver->GetGPULocalMemoryIndex(mrq.memoryTypeBits),
};
vkr = m_pDriver->vkAllocateMemory(m_Device, &allocInfo, NULL, &dsImageMem);
CheckVkResult(vkr);
if(vkr != VK_SUCCESS)
return ResourceId();
vkr = m_pDriver->vkBindImageMemory(m_Device, dsImage, dsImageMem, 0);
CheckVkResult(vkr);
cmd = m_pDriver->GetNextCmd();
if(cmd == VK_NULL_HANDLE)
return ResourceId();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
CheckVkResult(vkr);
// move original depth buffer to shader read state
m_pDriver->FindImageState(depthIm)->InlineTransition(
cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_GENERAL,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
m_pDriver->GetImageTransitionInfo());
// transition new depth buffer to depth write state
m_pDriver->FindImageState(GetResID(dsImage))
->InlineTransition(cmd, m_pDriver->m_QueueFamilyIdx, VK_IMAGE_LAYOUT_GENERAL, 0,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
m_pDriver->GetImageTransitionInfo());
vkr = vt->EndCommandBuffer(Unwrap(cmd));
CheckVkResult(vkr);
cmd = VK_NULL_HANDLE;
dsSubRange = {
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
sub.mip,
1,
sub.slice,
sub.numSlices,
};
dsViewInfo = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
NULL,
0,
dsImage,
VK_IMAGE_VIEW_TYPE_2D,
dsNewFmt,
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
dsSubRange,
};
vkr = m_pDriver->vkCreateImageView(m_Device, &dsViewInfo, NULL, &dsView);
CheckVkResult(vkr);
}
VkImageView views[] = {
m_Overlay.ImageView,
m_pDriver->GetResourceManager()->GetCurrentHandle<VkImageView>(depthStencilView),
dsView,
};
// Create framebuffer rendering just to overlay image, no depth
@@ -1708,6 +1890,50 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
vkr = m_pDriver->vkCreateFramebuffer(m_Device, &fbinfo, NULL, &depthFB);
CheckVkResult(vkr);
// Fullscreen pass using shader to copy original depth buffer -> new depth buffer
// Pipeline also writes 0 to the stencil during the pass
if(needDepthCopyToDepthStencil)
{
cmd = m_pDriver->GetNextCmd();
if(cmd == VK_NULL_HANDLE)
return ResourceId();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
CheckVkResult(vkr);
VkClearValue clearval = {};
VkRenderPassBeginInfo rpbegin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
NULL,
Unwrap(depthRP),
Unwrap(depthFB),
state.renderArea,
1,
&clearval,
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
Unwrap(m_Overlay.m_DepthCopyPipeline[fmtIndex][sampleIndex]));
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
Unwrap(m_Overlay.m_DepthCopyPipeLayout), 0, 1,
UnwrapPtr(m_Overlay.m_DepthCopyDescSet), 0, NULL);
VkViewport viewport = {
0.0f, 0.0f, (float)m_Overlay.ImageDim.width, (float)m_Overlay.ImageDim.height,
0.0f, 1.0f,
};
vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport);
vt->CmdDraw(Unwrap(cmd), 4, 1, 0, 0);
vt->CmdEndRenderPass(Unwrap(cmd));
vkr = vt->EndCommandBuffer(Unwrap(cmd));
CheckVkResult(vkr);
cmd = VK_NULL_HANDLE;
}
dsFmt = dsNewFmt;
}
// if depthRP is NULL, so is depthFB, and it means no depth buffer was
@@ -1722,7 +1948,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// make patched shader
VkShaderModule failmod = {}, passmod = {};
VkPipeline failpipe = {}, passpipe = {};
VkPipeline failpipe = {}, passpipe = {}, depthWriteStencilPipe = {};
// first shader, no depth/stencil testing, writes red
GetDebugManager()->PatchFixedColShader(failmod, highlightCol);
@@ -1768,6 +1994,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// subpass 0 in either render pass
pipeCreateInfo.subpass = 0;
VkPipelineShaderStageCreateInfo orgFragShader = {};
VkPipelineShaderStageCreateInfo *fragShader = NULL;
for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++)
@@ -1776,6 +2003,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
(VkPipelineShaderStageCreateInfo &)pipeCreateInfo.pStages[i];
if(sh.stage == VK_SHADER_STAGE_FRAGMENT_BIT)
{
orgFragShader = sh;
sh.pName = "main";
fragShader = &sh;
break;
@@ -1784,6 +2012,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
if(fragShader == NULL)
{
useDepthWriteStencilPass = false;
// we know this is safe because it's pointing to a static array that's
// big enough for all shaders
@@ -1832,6 +2061,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
// disable culling/discard and enable depth clamp. That way we show any failures due to these
VkPipelineRasterizationStateCreateInfo *rs =
(VkPipelineRasterizationStateCreateInfo *)pipeCreateInfo.pRasterizationState;
VkPipelineRasterizationStateCreateInfo orgRS = *rs;
rs->cullMode = VK_CULL_MODE_NONE;
rs->rasterizerDiscardEnable = false;
@@ -1842,6 +2072,39 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
&failpipe);
CheckVkResult(vkr);
if(useDepthWriteStencilPass)
{
pipeCreateInfo.renderPass = depthRP;
*rs = orgRS;
// disable colour write
for(uint32_t i = 0; i < cb->attachmentCount; i++)
{
VkPipelineColorBlendAttachmentState *att =
(VkPipelineColorBlendAttachmentState *)&cb->pAttachments[i];
att->blendEnable = false;
att->colorWriteMask = 0x0;
}
// Write stencil 0x1 for depth passing pixels
ds->stencilTestEnable = true;
ds->front.compareOp = VK_COMPARE_OP_ALWAYS;
ds->front.failOp = VK_STENCIL_OP_KEEP;
ds->front.depthFailOp = VK_STENCIL_OP_KEEP;
ds->front.passOp = VK_STENCIL_OP_REPLACE;
ds->front.compareMask = 0xff;
ds->front.reference = 0x1;
ds->front.writeMask = 0xff;
ds->back = ds->front;
// Use original shader
*fragShader = orgFragShader;
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo,
NULL, &depthWriteStencilPipe);
CheckVkResult(vkr);
}
// modify state
state.SetRenderPass(GetResID(m_Overlay.NoDepthRP));
state.subpass = 0;
@@ -1858,7 +2121,11 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw);
state.graphics.pipeline = GetResID(passpipe);
if(useDepthWriteStencilPass)
state.graphics.pipeline = GetResID(depthWriteStencilPipe);
else
state.graphics.pipeline = GetResID(passpipe);
if(depthRP != VK_NULL_HANDLE)
{
state.SetRenderPass(GetResID(depthRP));
@@ -1872,6 +2139,47 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
m_pDriver->ReplayLog(0, eventId, eReplay_OnlyDraw);
if(useDepthWriteStencilPass)
{
// Resolve stencil = 0x1 pixels to green
cmd = m_pDriver->GetNextCmd();
if(cmd == VK_NULL_HANDLE)
return ResourceId();
RDCASSERT((dsFmt == VK_FORMAT_D24_UNORM_S8_UINT) || (dsFmt == VK_FORMAT_D32_SFLOAT_S8_UINT));
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
CheckVkResult(vkr);
VkClearValue clearval = {};
VkRenderPassBeginInfo rpbegin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
NULL,
Unwrap(depthRP),
Unwrap(depthFB),
state.renderArea,
1,
&clearval,
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
Unwrap(m_Overlay.m_DepthResolvePipeline[fmtIndex][sampleIndex]));
VkViewport viewport = {
0.0f, 0.0f, (float)m_Overlay.ImageDim.width, (float)m_Overlay.ImageDim.height,
0.0f, 1.0f,
};
vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport);
vt->CmdDraw(Unwrap(cmd), 4, 1, 0, 0);
vt->CmdEndRenderPass(Unwrap(cmd));
vkr = vt->EndCommandBuffer(Unwrap(cmd));
CheckVkResult(vkr);
cmd = VK_NULL_HANDLE;
}
// submit & flush so that we don't have to keep pipeline around for a while
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
@@ -1891,6 +2199,9 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D
m_pDriver->vkDestroyShaderModule(m_Device, failmod, NULL);
m_pDriver->vkDestroyPipeline(m_Device, passpipe, NULL);
m_pDriver->vkDestroyShaderModule(m_Device, passmod, NULL);
m_pDriver->vkDestroyPipeline(m_Device, depthWriteStencilPipe, NULL);
m_pDriver->vkDestroyImage(m_Device, dsImage, NULL);
m_pDriver->vkFreeMemory(m_Device, dsImageMem, NULL);
if(depthRP != VK_NULL_HANDLE)
{
+11
View File
@@ -670,10 +670,21 @@ private:
VkPipelineLayout m_QuadResolvePipeLayout = VK_NULL_HANDLE;
VkPipeline m_QuadResolvePipeline[8] = {VK_NULL_HANDLE};
VkDescriptorSetLayout m_DepthCopyDescSetLayout = VK_NULL_HANDLE;
VkDescriptorSet m_DepthCopyDescSet = VK_NULL_HANDLE;
VkPipelineLayout m_DepthCopyPipeLayout = VK_NULL_HANDLE;
VkPipeline m_DepthCopyPipeline[2][5];
VkPipelineLayout m_DepthResolvePipeLayout = VK_NULL_HANDLE;
VkPipeline m_DepthResolvePipeline[2][5];
GPUBuffer m_TriSizeUBO;
VkDescriptorSetLayout m_TriSizeDescSetLayout = VK_NULL_HANDLE;
VkDescriptorSet m_TriSizeDescSet = VK_NULL_HANDLE;
VkPipelineLayout m_TriSizePipeLayout = VK_NULL_HANDLE;
VkSampler m_PointSampler = VK_NULL_HANDLE;
VkFormat m_DefaultDepthStencilFormat;
} m_Overlay;
struct MeshRendering
@@ -131,6 +131,10 @@ static const BuiltinShaderConfig builtinShaders[] = {
BuiltinShaderConfig(BuiltinShader::DepthBuf2MSFS, EmbeddedResource(glsl_vk_depthbuf2ms_frag),
rdcspv::ShaderStage::Fragment,
FeatureCheck::SampleShading | FeatureCheck::NonMetalBackend),
BuiltinShaderConfig(BuiltinShader::DepthCopyFS, EmbeddedResource(glsl_depth_copy_frag),
rdcspv::ShaderStage::Fragment, FeatureCheck::FragmentStores),
BuiltinShaderConfig(BuiltinShader::DepthCopyMSFS, EmbeddedResource(glsl_depth_copyms_frag),
rdcspv::ShaderStage::Fragment, FeatureCheck::FragmentStores),
};
RDCCOMPILE_ASSERT(ARRAY_COUNT(builtinShaders) == arraydim<BuiltinShader>(),
@@ -60,6 +60,8 @@ enum class BuiltinShader
DepthMS2BufferCS,
Buffer2MSCS,
DepthBuf2MSFS,
DepthCopyFS,
DepthCopyMSFS,
Count,
};