Manually check depth test to get per-fragment pass/fail

This commit is contained in:
baldurk
2020-07-16 13:28:45 +01:00
parent a8c97a7530
commit 4d6d949f42
3 changed files with 96 additions and 6 deletions
+3 -3
View File
@@ -281,7 +281,7 @@ public:
if(mod.primitiveID == ~0U)
ret = tr("Unknown primitive\n");
if(mod.shaderDiscarded)
if(!mod.Passed())
ret += failureString(mod);
return ret;
@@ -365,7 +365,7 @@ public:
}
else
{
if(getMod(index).shaderDiscarded)
if(!getMod(index).Passed())
return QBrush(QColor::fromRgb(255, 235, 235));
}
}
@@ -382,7 +382,7 @@ public:
}
else
{
if(getMod(index).shaderDiscarded)
if(!getMod(index).Passed())
return QBrush(textColor);
}
}
@@ -640,6 +640,7 @@ rdcarray<PixelModification> D3D11Replay::PixelHistory(rdcarray<EventUsage> event
// while issuing the above queries we can check to see which tests are enabled so we don't
// bother checking if depth testing failed if the depth test was disabled
rdcarray<uint32_t> flags(events.size());
std::map<uint32_t, D3D11_COMPARISON_FUNC> depthOps;
enum
{
TestEnabled_BackfaceCulling = 1 << 0,
@@ -894,6 +895,8 @@ rdcarray<PixelModification> D3D11Replay::PixelHistory(rdcarray<EventUsage> event
flags[ev] |= (TestEnabled_BackfaceCulling | TestEnabled_DepthClip);
}
D3D11_COMPARISON_FUNC depthOp = D3D11_COMPARISON_LESS;
if(curDS)
{
D3D11_DEPTH_STENCIL_DESC dsDesc;
@@ -906,6 +909,12 @@ rdcarray<PixelModification> D3D11Replay::PixelHistory(rdcarray<EventUsage> event
if(dsDesc.DepthFunc == D3D11_COMPARISON_NEVER)
flags[ev] |= TestMustFail_DepthTesting;
depthOp = dsDesc.DepthFunc;
}
else
{
depthOp = D3D11_COMPARISON_ALWAYS;
}
if(dsDesc.StencilEnable)
@@ -933,6 +942,8 @@ rdcarray<PixelModification> D3D11Replay::PixelHistory(rdcarray<EventUsage> event
flags[ev] |= TestEnabled_DepthTesting;
}
depthOps[events[ev].eventId] = depthOp;
if(rsDesc.ScissorEnable)
{
// see if we can find at least one scissor region this pixel could fall into
@@ -2424,6 +2435,27 @@ rdcarray<PixelModification> D3D11Replay::PixelHistory(rdcarray<EventUsage> event
shadColSlot++;
depthSlot++;
}
// check the depth value between premod/shaderout against the known test if we have valid depth
// values, as we don't have per-fragment depth test information.
if(history[h].preMod.depth >= 0.0f && history[h].shaderOut.depth >= 0.0f)
{
bool passed = true;
if(depthOps[history[h].eventId] == D3D11_COMPARISON_EQUAL)
passed = (history[h].shaderOut.depth == history[h].preMod.depth);
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_NOT_EQUAL)
passed = (history[h].shaderOut.depth != history[h].preMod.depth);
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_LESS)
passed = (history[h].shaderOut.depth < history[h].preMod.depth);
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_LESS_EQUAL)
passed = (history[h].shaderOut.depth <= history[h].preMod.depth);
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_GREATER)
passed = (history[h].shaderOut.depth > history[h].preMod.depth);
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_GREATER_EQUAL)
passed = (history[h].shaderOut.depth >= history[h].preMod.depth);
history[h].depthTestFailed = !passed;
}
}
m_pImmediateContext->Unmap(shadoutStoreReadback, 0);
+61 -3
View File
@@ -115,7 +115,7 @@ bool isDirectWrite(ResourceUsage usage)
usage == ResourceUsage::GenMips);
}
enum
enum : uint32_t
{
TestEnabled_Culling = 1 << 0,
TestEnabled_Scissor = 1 << 1,
@@ -133,6 +133,16 @@ enum
TestMustFail_DepthTesting = 1 << 12,
TestMustFail_StencilTesting = 1 << 13,
TestMustFail_SampleMask = 1 << 14,
DepthTest_Shift = 29,
DepthTest_Always = 0U << DepthTest_Shift,
DepthTest_Never = 1U << DepthTest_Shift,
DepthTest_Equal = 2U << DepthTest_Shift,
DepthTest_NotEqual = 3U << DepthTest_Shift,
DepthTest_Less = 4U << DepthTest_Shift,
DepthTest_LessEqual = 5U << DepthTest_Shift,
DepthTest_Greater = 6U << DepthTest_Shift,
DepthTest_GreaterEqual = 7U << DepthTest_Shift,
};
struct CopyPixelParams
@@ -1718,6 +1728,7 @@ struct TestsFailedCallback : public VulkanPixelHistoryCallback
{
}
void PreEndCommandBuffer(VkCommandBuffer cmd) {}
bool HasEventFlags(uint32_t eventId) { return m_EventFlags.find(eventId) != m_EventFlags.end(); }
uint32_t GetEventFlags(uint32_t eventId)
{
auto it = m_EventFlags.find(eventId);
@@ -1784,6 +1795,27 @@ private:
flags |= TestEnabled_DepthTesting;
if(pipestate.depthCompareOp == VK_COMPARE_OP_NEVER)
flags |= TestMustFail_DepthTesting;
if(pipestate.depthCompareOp == VK_COMPARE_OP_NEVER)
flags |= DepthTest_Never;
if(pipestate.depthCompareOp == VK_COMPARE_OP_LESS)
flags |= DepthTest_Less;
if(pipestate.depthCompareOp == VK_COMPARE_OP_EQUAL)
flags |= DepthTest_Equal;
if(pipestate.depthCompareOp == VK_COMPARE_OP_LESS_OR_EQUAL)
flags |= DepthTest_LessEqual;
if(pipestate.depthCompareOp == VK_COMPARE_OP_GREATER)
flags |= DepthTest_Greater;
if(pipestate.depthCompareOp == VK_COMPARE_OP_NOT_EQUAL)
flags |= DepthTest_NotEqual;
if(pipestate.depthCompareOp == VK_COMPARE_OP_GREATER_OR_EQUAL)
flags |= DepthTest_GreaterEqual;
if(pipestate.depthCompareOp == VK_COMPARE_OP_ALWAYS)
flags |= DepthTest_Always;
}
else
{
flags |= DepthTest_Always;
}
if(pipestate.stencilTestEnable)
@@ -3270,8 +3302,6 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
}
}
SAFE_DELETE(tfCb);
// Try to read memory back
EventInfo *eventsInfo;
@@ -3450,9 +3480,37 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
history[h].preMod = history[h - 1].postMod;
}
}
// check the depth value between premod/shaderout against the known test if we have valid
// depth values, as we don't have per-fragment depth test information.
if(history[h].preMod.depth >= 0.0f && history[h].shaderOut.depth >= 0.0f && tfCb &&
tfCb->HasEventFlags(history[h].eventId))
{
uint32_t flags = tfCb->GetEventFlags(history[h].eventId);
flags &= 0x7 << DepthTest_Shift;
bool passed = true;
if(flags == DepthTest_Equal)
passed = (history[h].shaderOut.depth == history[h].preMod.depth);
else if(flags == DepthTest_NotEqual)
passed = (history[h].shaderOut.depth != history[h].preMod.depth);
else if(flags == DepthTest_Less)
passed = (history[h].shaderOut.depth < history[h].preMod.depth);
else if(flags == DepthTest_LessEqual)
passed = (history[h].shaderOut.depth <= history[h].preMod.depth);
else if(flags == DepthTest_Greater)
passed = (history[h].shaderOut.depth > history[h].preMod.depth);
else if(flags == DepthTest_GreaterEqual)
passed = (history[h].shaderOut.depth >= history[h].preMod.depth);
history[h].depthTestFailed = !passed;
}
}
}
SAFE_DELETE(tfCb);
GetDebugManager()->PixelHistoryDestroyResources(resources);
ObjDisp(dev)->DestroyQueryPool(Unwrap(dev), occlusionPool, NULL);
delete shaderCache;