mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-13 19:17:12 +00:00
Vk Pixel History: Small fixes + more tests
- For counting the number of fragments, also need to disable the depth bounds test, since we are not initializing the depth value currently - Reset depth to 0.0f for shader out, and set it to always pass. So that we can get depth values from just one fragment. - Initialize premod value for individual fragment events. This is not surfaced in the UI, but available from the python API and checked in tests.
This commit is contained in:
committed by
Baldur Karlsson
parent
0b6c1c14b4
commit
08cf503eea
@@ -461,12 +461,12 @@ protected:
|
||||
// TODO: should leave in the original state.
|
||||
ds->depthTestEnable = VK_FALSE;
|
||||
ds->depthWriteEnable = VK_FALSE;
|
||||
ds->depthBoundsTestEnable = VK_FALSE;
|
||||
|
||||
if(disableTests)
|
||||
{
|
||||
rs->cullMode = VK_CULL_MODE_NONE;
|
||||
rs->rasterizerDiscardEnable = VK_FALSE;
|
||||
ds->depthBoundsTestEnable = VK_FALSE;
|
||||
if(m_pDriver->GetDeviceFeatures().depthClamp)
|
||||
rs->depthClampEnable = true;
|
||||
}
|
||||
@@ -1350,6 +1350,9 @@ private:
|
||||
m_pDriver->GetCmdRenderState().BeginRenderPassAndApplyState(m_pDriver, cmd,
|
||||
VulkanRenderState::BindGraphics);
|
||||
|
||||
ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
|
||||
ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
|
||||
|
||||
if(clear)
|
||||
{
|
||||
VkClearAttachment att = {};
|
||||
@@ -2002,11 +2005,11 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
// If depth is enabled, clear out the depth value so that the test always
|
||||
// passes. Depth writes only work if depth test is enabled.
|
||||
// Regardless also need to reset the stencil back to 0.
|
||||
// Reset depth to 0.0f, depth test is set to always pass.
|
||||
// This way we get the value for just that fragment.
|
||||
// Reset stencil to 0.
|
||||
VkClearDepthStencilValue dsValue = {};
|
||||
dsValue.depth = 1.0f;
|
||||
dsValue.depth = 0.0f;
|
||||
dsValue.stencil = 0;
|
||||
VkImageSubresourceRange range = {};
|
||||
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
@@ -2014,6 +2017,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
range.baseMipLevel = 0;
|
||||
range.layerCount = 1;
|
||||
range.levelCount = 1;
|
||||
|
||||
ObjDisp(cmd)->CmdClearDepthStencilImage(Unwrap(cmd), Unwrap(m_CallbackInfo.dsImage),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &dsValue, 1,
|
||||
&range);
|
||||
@@ -2205,21 +2209,6 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
stages[i].module = replacement;
|
||||
}
|
||||
pipeCreateInfo.pStages = stages.data();
|
||||
|
||||
VkPipelineDynamicStateCreateInfo *dynState =
|
||||
(VkPipelineDynamicStateCreateInfo *)pipeCreateInfo.pDynamicState;
|
||||
|
||||
rdcarray<VkDynamicState> dynamicStates;
|
||||
RDCASSERT(dynState != NULL);
|
||||
if(!p.dynamicStates[VkDynamicStencilReference])
|
||||
{
|
||||
dynamicStates.resize(dynState->dynamicStateCount);
|
||||
memcpy(dynamicStates.data(), dynState->pDynamicStates, dynamicStates.byteSize());
|
||||
dynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||
dynState->dynamicStateCount = (uint32_t)dynamicStates.size();
|
||||
dynState->pDynamicStates = dynamicStates.data();
|
||||
}
|
||||
|
||||
pipeCreateInfo.renderPass = rp;
|
||||
|
||||
Pipelines pipes = {};
|
||||
@@ -2247,6 +2236,11 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ds->depthBoundsTestEnable = VK_FALSE;
|
||||
ds->depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
}
|
||||
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_pDriver->GetDev(), VK_NULL_HANDLE, 1,
|
||||
&pipeCreateInfo, NULL, &pipes.shaderOutPipe);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
@@ -3014,6 +3008,7 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
uint32_t eventId = events[ev].eventId;
|
||||
bool clear = (events[ev].usage == ResourceUsage::Clear);
|
||||
bool directWrite = isDirectWrite(events[ev].usage);
|
||||
|
||||
if(drawEvents.contains(events[ev].eventId) || clear || directWrite)
|
||||
{
|
||||
PixelModification mod;
|
||||
@@ -3195,6 +3190,12 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
FillInColor(shaderOutFormat, bp[offset].postMod, history[h].postMod);
|
||||
history[h].postMod.depth = bp[offset].postMod.depth.fdepth;
|
||||
}
|
||||
// If it is not the first fragment for the event, set the preMod to the
|
||||
// postMod of the previous fragment.
|
||||
if(h > 0 && (history[h].eventId == history[h - 1].eventId))
|
||||
{
|
||||
history[h].preMod = history[h - 1].postMod;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,8 @@ void main()
|
||||
|
||||
void Prepare(int argc, char **argv)
|
||||
{
|
||||
features.depthBounds = true;
|
||||
features.geometryShader = true;
|
||||
features.sampleRateShading = true;
|
||||
|
||||
VulkanGraphicsTest::Prepare(argc, argv);
|
||||
@@ -195,6 +197,33 @@ void main()
|
||||
{Vec3f(-0.6f, 0.75f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(-0.5f, 0.65f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(-0.4f, 0.75f, 0.5f), Vec4f(0.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
|
||||
// Different depth triangles
|
||||
{Vec3f(0.0f, 0.8f, 0.97f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.4f, 0.2f, 0.97f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.8f, 0.8f, 0.97f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
|
||||
{Vec3f(0.2f, 0.8f, 0.20f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.4f, 0.4f, 0.20f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.6f, 0.8f, 0.20f), Vec4f(1.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
|
||||
{Vec3f(0.2f, 0.8f, 0.30f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.4f, 0.6f, 0.30f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.6f, 0.8f, 0.30f), Vec4f(1.0f, 0.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
|
||||
{Vec3f(0.2f, 0.8f, 0.10f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.4f, 0.7f, 0.10f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.6f, 0.8f, 0.10f), Vec4f(0.0f, 0.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
|
||||
// Fails depth bounds test.
|
||||
{Vec3f(0.2f, 0.8f, 0.05f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.4f, 0.7f, 0.05f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.6f, 0.8f, 0.05f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
|
||||
// Should be back face culled.
|
||||
{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)},
|
||||
};
|
||||
|
||||
// negate y if we're using negative viewport height
|
||||
@@ -316,6 +345,16 @@ void main()
|
||||
}
|
||||
|
||||
pipeCreateInfo.depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||
|
||||
VkPipeline depthPipe;
|
||||
{
|
||||
vkh::GraphicsPipelineCreateInfo depthPipeInfo = pipeCreateInfo;
|
||||
depthPipeInfo.dynamicState.dynamicStates.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
|
||||
depthPipeInfo.depthStencilState.depthBoundsTestEnable = VK_TRUE;
|
||||
depthPipe = createGraphicsPipeline(depthPipeInfo);
|
||||
setName(dynamicStencilMaskPipe, "depthPipe");
|
||||
}
|
||||
|
||||
pipeCreateInfo.depthStencilState.stencilTestEnable = VK_TRUE;
|
||||
VkPipeline stencilWritePipe = createGraphicsPipeline(pipeCreateInfo);
|
||||
|
||||
@@ -462,6 +501,18 @@ void main()
|
||||
vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FACE_FRONT_AND_BACK, 0);
|
||||
vkCmdDraw(cmd, 3, 1, 42, 0);
|
||||
|
||||
// Six triangles, five fragments reported.
|
||||
// 0: Fails depth test
|
||||
// 1: Passes
|
||||
// 2: Fails depth test compared to 1st fragment
|
||||
// 3: Passes
|
||||
// 4: Fails depth bounds test
|
||||
// 5: Fails backface culling, not reported.
|
||||
setMarker(cmd, "Depth Test");
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, depthPipe);
|
||||
vkCmdSetDepthBounds(cmd, 0.15f, 1.0f);
|
||||
vkCmdDraw(cmd, 6 * 3, 1, 45, 0);
|
||||
|
||||
vkCmdEndRenderPass(cmd);
|
||||
|
||||
{
|
||||
|
||||
@@ -11,8 +11,10 @@ def scissor_clipped(x): return x.scissorClipped
|
||||
def stencil_test_failed(x): return x.stencilTestFailed
|
||||
def shader_discarded(x): return x.shaderDiscarded
|
||||
def shader_out_col(x): return value_selector(x.shaderOut.col)
|
||||
def shader_out_depth(x): return x.shaderOut.depth
|
||||
def pre_mod_col(x): return value_selector(x.preMod.col)
|
||||
def post_mod_col(x): return value_selector(x.postMod.col)
|
||||
def post_mod_depth(x): return x.postMod.depth
|
||||
def primitive_id(x): return x.primitiveID
|
||||
def unboundPS(x): return x.unboundPS
|
||||
|
||||
@@ -59,6 +61,7 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
fixed_scissor_pass_eid = self.find_draw("Fixed Scissor Pass").next.eventId
|
||||
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
|
||||
|
||||
# For pixel 190, 149 inside the red triangle
|
||||
x, y = 190, 149
|
||||
@@ -125,6 +128,29 @@ 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)
|
||||
|
||||
rdtest.log.print("Testing depth test for per fragment reporting")
|
||||
self.controller.SetFrameEvent(depth_test_eid, True)
|
||||
|
||||
x, y = 275, 260
|
||||
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, background_eid], [passed, True]],
|
||||
[[event_id, depth_test_eid], [primitive_id, 0], [shader_out_col, (1.0, 1.0, 1.0, 1.0)],
|
||||
[shader_out_depth, 0.97], [post_mod_col, (1.0, 0.0, 1.0, 1.0)], [post_mod_depth, 0.95]],
|
||||
[[event_id, depth_test_eid], [primitive_id, 1], [shader_out_col, (1.0, 1.0, 0.0, 1.0)],
|
||||
[shader_out_depth, 0.20], [post_mod_col, (1.0, 1.0, 0.0, 1.0)], [post_mod_depth, 0.20]],
|
||||
[[event_id, depth_test_eid], [primitive_id, 2], [shader_out_col, (1.0, 0.0, 0.0, 1.0)],
|
||||
[shader_out_depth, 0.30], [post_mod_col, (1.0, 1.0, 0.0, 1.0)], [post_mod_depth, 0.20]],
|
||||
[[event_id, depth_test_eid], [primitive_id, 3], [shader_out_col, (0.0, 0.0, 1.0, 1.0)],
|
||||
[shader_out_depth, 0.10], [post_mod_col, (0.0, 0.0, 1.0, 1.0)], [post_mod_depth, 0.10]],
|
||||
[[event_id, depth_test_eid], [primitive_id, 4], [shader_out_col, (1.0, 1.0, 1.0, 1.0)],
|
||||
[shader_out_depth, 0.05], [post_mod_col, (0.0, 0.0, 1.0, 1.0)], [post_mod_depth, 0.10]],
|
||||
]
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
def multisampled_image_test(self):
|
||||
test_marker: rd.DrawcallDescription = self.find_draw("Multisampled: test")
|
||||
draw_eid = test_marker.next.eventId
|
||||
@@ -231,7 +257,7 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
actual = events[i][c][0](modifs[i])
|
||||
if not rdtest.value_compare(actual, expected):
|
||||
raise rdtest.TestFailureException(
|
||||
"eventId {}, testing {} expected {}, got {}".format(modifs[i].eventId,
|
||||
"eventId {}, primitiveID {}: testing {} expected {}, got {}".format(modifs[i].eventId, modifs[i].primitiveID,
|
||||
events[i][c][0].__name__,
|
||||
expected,
|
||||
actual))
|
||||
@@ -241,9 +267,11 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
for i in range(len(modifs) - 1):
|
||||
if value_selector(modifs[i].postMod.col) != value_selector(modifs[i + 1].preMod.col):
|
||||
raise rdtest.TestFailureException(
|
||||
"postmod at {}: {} doesn't match premod at {}: {}".format(modifs[i].eventId,
|
||||
"postmod at {} primitive {}: {} doesn't match premod at {} primitive {}: {}".format(modifs[i].eventId,
|
||||
modifs[i].primitiveID,
|
||||
value_selector(modifs[i].postMod.col),
|
||||
modifs[i + 1].eventId,
|
||||
modifs[i + 1].primitiveID,
|
||||
value_selector(modifs[i].preMod.col)))
|
||||
|
||||
# Check that if the test failed, its postmod is the same as premod
|
||||
@@ -251,6 +279,7 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
if not modifs[i].Passed():
|
||||
if not rdtest.value_compare(value_selector(modifs[i].preMod.col), value_selector(modifs[i].postMod.col)):
|
||||
raise rdtest.TestFailureException(
|
||||
"postmod at {}: {} doesn't match premod: {}".format(modifs[i].eventId,
|
||||
"postmod at {} primitive {}: {} doesn't match premod: {}".format(modifs[i].eventId,
|
||||
modifs[i].primitiveID,
|
||||
value_selector(modifs[i].postMod.col),
|
||||
value_selector(modifs[i].preMod.col)))
|
||||
|
||||
Reference in New Issue
Block a user