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:
Aliya Pazylbekova
2020-05-12 18:55:41 -04:00
committed by Baldur Karlsson
parent 0b6c1c14b4
commit 08cf503eea
3 changed files with 104 additions and 23 deletions
+21 -20
View File
@@ -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);
{
+32 -3
View File
@@ -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)))