mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Handle depth clipping and depth bounds failure separately
* This prevents truly depth-clipped fragments from being wrongly reported as other failures like backface culling.
This commit is contained in:
@@ -580,6 +580,8 @@ private:
|
||||
s += tr("\nBackface culled");
|
||||
if(mod.depthClipped)
|
||||
s += tr("\nDepth Clipped");
|
||||
if(mod.depthBoundsFailed)
|
||||
s += tr("\nDepth bounds test failed");
|
||||
if(mod.scissorClipped)
|
||||
s += tr("\nScissor Clipped");
|
||||
if(mod.shaderDiscarded)
|
||||
|
||||
@@ -1797,9 +1797,10 @@ struct PixelModification
|
||||
unboundPS == o.unboundPS && fragIndex == o.fragIndex && primitiveID == o.primitiveID &&
|
||||
preMod == o.preMod && shaderOut == o.shaderOut && postMod == o.postMod &&
|
||||
sampleMasked == o.sampleMasked && backfaceCulled == o.backfaceCulled &&
|
||||
depthClipped == o.depthClipped && viewClipped == o.viewClipped &&
|
||||
scissorClipped == o.scissorClipped && shaderDiscarded == o.shaderDiscarded &&
|
||||
depthTestFailed == o.depthTestFailed && stencilTestFailed == o.stencilTestFailed;
|
||||
depthClipped == o.depthClipped && depthBoundsFailed == o.depthBoundsFailed &&
|
||||
viewClipped == o.viewClipped && scissorClipped == o.scissorClipped &&
|
||||
shaderDiscarded == o.shaderDiscarded && depthTestFailed == o.depthTestFailed &&
|
||||
stencilTestFailed == o.stencilTestFailed;
|
||||
}
|
||||
bool operator<(const PixelModification &o) const
|
||||
{
|
||||
@@ -1825,6 +1826,8 @@ struct PixelModification
|
||||
return backfaceCulled < o.backfaceCulled;
|
||||
if(!(depthClipped == o.depthClipped))
|
||||
return depthClipped < o.depthClipped;
|
||||
if(!(depthBoundsFailed == o.depthBoundsFailed))
|
||||
return depthBoundsFailed < o.depthBoundsFailed;
|
||||
if(!(viewClipped == o.viewClipped))
|
||||
return viewClipped < o.viewClipped;
|
||||
if(!(scissorClipped == o.scissorClipped))
|
||||
@@ -1871,6 +1874,8 @@ pixel.
|
||||
bool backfaceCulled;
|
||||
DOCUMENT("``True`` if depth near/far clipping eliminated this fragment.");
|
||||
bool depthClipped;
|
||||
DOCUMENT("``True`` if depth bounds clipping eliminated this fragment.");
|
||||
bool depthBoundsFailed;
|
||||
DOCUMENT("``True`` if viewport clipping eliminated this fragment.");
|
||||
bool viewClipped;
|
||||
DOCUMENT("``True`` if scissor clipping eliminated this fragment.");
|
||||
@@ -1891,8 +1896,9 @@ pixel.
|
||||
)");
|
||||
bool Passed() const
|
||||
{
|
||||
return !sampleMasked && !backfaceCulled && !depthClipped && !viewClipped && !scissorClipped &&
|
||||
!shaderDiscarded && !depthTestFailed && !stencilTestFailed && !predicationSkipped;
|
||||
return !sampleMasked && !backfaceCulled && !depthClipped && !depthBoundsFailed &&
|
||||
!viewClipped && !scissorClipped && !shaderDiscarded && !depthTestFailed &&
|
||||
!stencilTestFailed && !predicationSkipped;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -117,22 +117,23 @@ bool isDirectWrite(ResourceUsage usage)
|
||||
|
||||
enum : uint32_t
|
||||
{
|
||||
TestEnabled_Culling = 1 << 0,
|
||||
TestEnabled_Scissor = 1 << 1,
|
||||
TestEnabled_SampleMask = 1 << 2,
|
||||
TestEnabled_DepthBounds = 1 << 3,
|
||||
TestEnabled_StencilTesting = 1 << 4,
|
||||
TestEnabled_DepthTesting = 1 << 5,
|
||||
TestEnabled_FragmentDiscard = 1 << 6,
|
||||
TestEnabled_DepthClipping = 1 << 0,
|
||||
TestEnabled_Culling = 1 << 1,
|
||||
TestEnabled_Scissor = 1 << 2,
|
||||
TestEnabled_SampleMask = 1 << 3,
|
||||
TestEnabled_DepthBounds = 1 << 4,
|
||||
TestEnabled_StencilTesting = 1 << 5,
|
||||
TestEnabled_DepthTesting = 1 << 6,
|
||||
TestEnabled_FragmentDiscard = 1 << 7,
|
||||
|
||||
Blending_Enabled = 1 << 7,
|
||||
UnboundFragmentShader = 1 << 8,
|
||||
TestMustFail_Culling = 1 << 9,
|
||||
TestMustFail_Scissor = 1 << 10,
|
||||
TestMustPass_Scissor = 1 << 11,
|
||||
TestMustFail_DepthTesting = 1 << 12,
|
||||
TestMustFail_StencilTesting = 1 << 13,
|
||||
TestMustFail_SampleMask = 1 << 14,
|
||||
Blending_Enabled = 1 << 8,
|
||||
UnboundFragmentShader = 1 << 9,
|
||||
TestMustFail_Culling = 1 << 10,
|
||||
TestMustFail_Scissor = 1 << 11,
|
||||
TestMustPass_Scissor = 1 << 12,
|
||||
TestMustFail_DepthTesting = 1 << 13,
|
||||
TestMustFail_StencilTesting = 1 << 14,
|
||||
TestMustFail_SampleMask = 1 << 15,
|
||||
|
||||
DepthTest_Shift = 29,
|
||||
DepthTest_Always = 0U << DepthTest_Shift,
|
||||
@@ -1781,6 +1782,9 @@ private:
|
||||
|
||||
// Culling
|
||||
{
|
||||
if(p.depthClipEnable && !p.depthClampEnable)
|
||||
flags |= TestEnabled_DepthClipping;
|
||||
|
||||
if(pipestate.cullMode != VK_CULL_MODE_NONE)
|
||||
flags |= TestEnabled_Culling;
|
||||
|
||||
@@ -1912,8 +1916,9 @@ private:
|
||||
PipelineCreationFlags_DisableDepthTest = 1 << 1,
|
||||
PipelineCreationFlags_DisableStencilTest = 1 << 2,
|
||||
PipelineCreationFlags_DisableDepthBoundsTest = 1 << 3,
|
||||
PipelineCreationFlags_FixedColorShader = 1 << 4,
|
||||
PipelineCreationFlags_IntersectOriginalScissor = 1 << 5,
|
||||
PipelineCreationFlags_DisableDepthClipping = 1 << 4,
|
||||
PipelineCreationFlags_FixedColorShader = 1 << 5,
|
||||
PipelineCreationFlags_IntersectOriginalScissor = 1 << 6,
|
||||
};
|
||||
|
||||
void ReplayDrawWithTests(VkCommandBuffer cmd, uint32_t eid, uint32_t eventFlags,
|
||||
@@ -1949,13 +1954,24 @@ private:
|
||||
if(eventFlags & TestEnabled_Culling)
|
||||
{
|
||||
uint32_t pipeFlags =
|
||||
PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_DisableDepthBoundsTest |
|
||||
PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_FixedColorShader;
|
||||
PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_DisableDepthClipping |
|
||||
PipelineCreationFlags_DisableDepthBoundsTest | PipelineCreationFlags_DisableStencilTest |
|
||||
PipelineCreationFlags_FixedColorShader;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, outputIndex);
|
||||
VkMarkerRegion::Set(StringFormat::Fmt("Test culling on %u", eid), cmd);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_Culling);
|
||||
}
|
||||
|
||||
if(eventFlags & TestEnabled_DepthClipping)
|
||||
{
|
||||
uint32_t pipeFlags =
|
||||
PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_DisableDepthBoundsTest |
|
||||
PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_FixedColorShader;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, replacementShaders, outputIndex);
|
||||
VkMarkerRegion::Set(StringFormat::Fmt("Test depth clipping on %u", eid), cmd);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_DepthClipping);
|
||||
}
|
||||
|
||||
// Scissor
|
||||
if(eventFlags & TestMustFail_Scissor)
|
||||
return;
|
||||
@@ -2081,6 +2097,8 @@ private:
|
||||
ds->stencilTestEnable = VK_FALSE;
|
||||
if(pipeCreateFlags & PipelineCreationFlags_DisableDepthBoundsTest)
|
||||
ds->depthBoundsTestEnable = VK_FALSE;
|
||||
if(pipeCreateFlags & PipelineCreationFlags_DisableDepthClipping)
|
||||
rs->depthClampEnable = VK_TRUE;
|
||||
|
||||
rdcarray<VkPipelineShaderStageCreateInfo> stages;
|
||||
stages.resize(ci.stageCount);
|
||||
@@ -3090,6 +3108,15 @@ void UpdateTestsFailed(const TestsFailedCallback *tfCb, uint32_t eventId, uint32
|
||||
if(mod.backfaceCulled)
|
||||
return;
|
||||
|
||||
if(eventFlags & TestEnabled_DepthClipping)
|
||||
{
|
||||
uint64_t occlData = tfCb->GetOcclusionResult(eventId, TestEnabled_DepthClipping);
|
||||
mod.depthClipped = (occlData == 0);
|
||||
}
|
||||
|
||||
if(mod.depthClipped)
|
||||
return;
|
||||
|
||||
if((eventFlags & (TestEnabled_Scissor | TestMustPass_Scissor | TestMustFail_Scissor)) ==
|
||||
TestEnabled_Scissor)
|
||||
{
|
||||
@@ -3121,9 +3148,9 @@ void UpdateTestsFailed(const TestsFailedCallback *tfCb, uint32_t eventId, uint32
|
||||
if(eventFlags & TestEnabled_DepthBounds)
|
||||
{
|
||||
uint64_t occlData = tfCb->GetOcclusionResult(eventId, TestEnabled_DepthBounds);
|
||||
mod.depthClipped = (occlData == 0);
|
||||
mod.depthBoundsFailed = (occlData == 0);
|
||||
}
|
||||
if(mod.depthClipped)
|
||||
if(mod.depthBoundsFailed)
|
||||
return;
|
||||
|
||||
if((eventFlags & (TestEnabled_StencilTesting | TestMustFail_StencilTesting)) ==
|
||||
|
||||
@@ -896,6 +896,7 @@ void DoSerialise(SerialiserType &ser, PixelModification &el)
|
||||
SERIALISE_MEMBER(sampleMasked);
|
||||
SERIALISE_MEMBER(backfaceCulled);
|
||||
SERIALISE_MEMBER(depthClipped);
|
||||
SERIALISE_MEMBER(depthBoundsFailed);
|
||||
SERIALISE_MEMBER(viewClipped);
|
||||
SERIALISE_MEMBER(scissorClipped);
|
||||
SERIALISE_MEMBER(shaderDiscarded);
|
||||
|
||||
@@ -224,6 +224,15 @@ void main()
|
||||
{Vec3f(0.6f, 0.8f, 0.25f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
{Vec3f(0.4f, 0.7f, 0.25f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.2f, 0.8f, 0.25f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
|
||||
// depth bounds prep
|
||||
{Vec3f(0.6f, -0.3f, 0.3f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.7f, -0.5f, 0.5f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.8f, -0.3f, 0.7f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
// depth bounds clip
|
||||
{Vec3f(0.6f, -0.3f, 0.3f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.7f, -0.5f, 0.5f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.8f, -0.3f, 0.7f), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
};
|
||||
|
||||
// negate y if we're using negative viewport height
|
||||
@@ -370,7 +379,7 @@ void main()
|
||||
depthPipeInfo.dynamicState.dynamicStates.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
|
||||
depthPipeInfo.depthStencilState.depthBoundsTestEnable = VK_TRUE;
|
||||
depthPipe = createGraphicsPipeline(depthPipeInfo);
|
||||
setName(dynamicStencilMaskPipe, "depthPipe");
|
||||
setName(depthPipe, "depthPipe");
|
||||
}
|
||||
|
||||
pipeCreateInfo.depthStencilState.stencilTestEnable = VK_TRUE;
|
||||
@@ -386,11 +395,21 @@ void main()
|
||||
pipeCreateInfo.depthStencilState.stencilTestEnable = VK_TRUE;
|
||||
pipeCreateInfo.depthStencilState.front.compareOp = VK_COMPARE_OP_GREATER;
|
||||
VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo);
|
||||
pipeCreateInfo.depthStencilState.stencilTestEnable = VK_FALSE;
|
||||
|
||||
pipeCreateInfo.rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT;
|
||||
VkPipeline cullFrontPipe = createGraphicsPipeline(pipeCreateInfo);
|
||||
pipeCreateInfo.rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
|
||||
pipeCreateInfo.depthStencilState.depthBoundsTestEnable = VK_TRUE;
|
||||
pipeCreateInfo.depthStencilState.minDepthBounds = 0.0f;
|
||||
pipeCreateInfo.depthStencilState.maxDepthBounds = 1.0f;
|
||||
VkPipeline depthBoundsPipe1 = createGraphicsPipeline(pipeCreateInfo);
|
||||
pipeCreateInfo.depthStencilState.minDepthBounds = 0.4f;
|
||||
pipeCreateInfo.depthStencilState.maxDepthBounds = 0.6f;
|
||||
VkPipeline depthBoundsPipe2 = createGraphicsPipeline(pipeCreateInfo);
|
||||
pipeCreateInfo.depthStencilState.depthBoundsTestEnable = VK_FALSE;
|
||||
|
||||
renderPassCreateInfo.attachments.pop_back();
|
||||
renderPassCreateInfo.subpasses[0].pDepthStencilAttachment = NULL;
|
||||
|
||||
@@ -533,6 +552,13 @@ void main()
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cullFrontPipe);
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
|
||||
setMarker(cmd, "Depth Bounds Prep");
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, depthBoundsPipe1);
|
||||
vkCmdDraw(cmd, 3, 1, 63, 0);
|
||||
setMarker(cmd, "Depth Bounds Clip");
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, depthBoundsPipe2);
|
||||
vkCmdDraw(cmd, 3, 1, 66, 0);
|
||||
|
||||
// add a marker so we can easily locate this draw
|
||||
setMarker(cmd, "Test Begin");
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ def passed(x): return x.Passed()
|
||||
def event_id(x): return x.eventId
|
||||
def culled(x): return x.backfaceCulled
|
||||
def depth_test_failed(x): return x.depthTestFailed
|
||||
def depth_clipped(x): return x.depthClipped
|
||||
def depth_bounds_failed(x): return x.depthBoundsFailed
|
||||
def scissor_clipped(x): return x.scissorClipped
|
||||
def stencil_test_failed(x): return x.stencilTestFailed
|
||||
def shader_discarded(x): return x.shaderDiscarded
|
||||
@@ -69,6 +71,8 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
dynamic_stencil_ref_eid = self.find_draw("Dynamic Stencil Ref").next.eventId
|
||||
dynamic_stencil_mask_eid = self.find_draw("Dynamic Stencil Mask").next.eventId
|
||||
depth_test_eid = self.find_draw("Depth Test").next.eventId
|
||||
depth_bounds_prep_eid = self.find_draw("Depth Bounds Prep").next.eventId
|
||||
depth_bounds_clip_eid = self.find_draw("Depth Bounds Clip").next.eventId
|
||||
|
||||
# For pixel 190, 149 inside the red triangle
|
||||
x, y = 190, 149
|
||||
@@ -118,6 +122,59 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
x, y = 330, 145
|
||||
rdtest.log.print("Testing pixel {}, {}".format(x, y))
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
events = [
|
||||
[[event_id, begin_renderpass_eid], [passed, True]],
|
||||
[[event_id, test_eid], [passed, True], [primitive_id, 3], [shader_out_col, (0.0, 0.0, 0.0, 2.75)]],
|
||||
]
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
x, y = 340, 145
|
||||
rdtest.log.print("Testing pixel {}, {}".format(x, y))
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
events = [
|
||||
[[event_id, begin_renderpass_eid], [passed, True]],
|
||||
[[event_id, test_eid], [passed, False], [depth_clipped, True]],
|
||||
]
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
x, y = 330, 105
|
||||
rdtest.log.print("Testing pixel {}, {}".format(x, y))
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
events = [
|
||||
[[event_id, begin_renderpass_eid], [passed, True]],
|
||||
[[event_id, depth_bounds_prep_eid], [passed, True], [primitive_id, 0], [shader_out_col, (1.0, 0.0, 0.0, 2.75)]],
|
||||
[[event_id, depth_bounds_clip_eid], [passed, True], [primitive_id, 0], [shader_out_col, (0.0, 1.0, 0.0, 2.75)]],
|
||||
]
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
x, y = 320, 105
|
||||
rdtest.log.print("Testing pixel {}, {}".format(x, y))
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
events = [
|
||||
[[event_id, begin_renderpass_eid], [passed, True]],
|
||||
[[event_id, depth_bounds_prep_eid], [passed, True], [primitive_id, 0], [shader_out_col, (1.0, 0.0, 0.0, 2.75)]],
|
||||
[[event_id, depth_bounds_clip_eid], [passed, False], [depth_bounds_failed, True]],
|
||||
]
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
x, y = 345, 105
|
||||
rdtest.log.print("Testing pixel {}, {}".format(x, y))
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
events = [
|
||||
[[event_id, begin_renderpass_eid], [passed, True]],
|
||||
[[event_id, depth_bounds_prep_eid], [passed, True], [primitive_id, 0], [shader_out_col, (1.0, 0.0, 0.0, 2.75)]],
|
||||
[[event_id, depth_bounds_clip_eid], [passed, False], [depth_bounds_failed, True]],
|
||||
]
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
rdtest.log.print("Testing dynamic state pipelines")
|
||||
self.controller.SetFrameEvent(dynamic_stencil_mask_eid, True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user