mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-25 07:56:33 +00:00
Add helper for quantised-checking of depth test failures on fragments
This commit is contained in:
@@ -2736,6 +2736,51 @@ pixel.
|
||||
!viewClipped && !scissorClipped && !shaderDiscarded && !depthTestFailed &&
|
||||
!stencilTestFailed && !predicationSkipped;
|
||||
}
|
||||
|
||||
DOCUMENT(R"(Update the depth-test failure state based on known shader output depth value and
|
||||
preMod reference value, quantised to a certain number of depth bits with epsilon.
|
||||
|
||||
This is primarily used internally and should not be needed to be called externally.
|
||||
|
||||
:param int depthBits: How many bits are in the depth buffer: 16, 24 or 32.
|
||||
:param CompareFunction depthFunc: The comparison function active for the depth test
|
||||
)");
|
||||
void CheckDepthTestQuantised(uint32_t depthBits, CompareFunction depthFunc)
|
||||
{
|
||||
float shadDepth = shaderOut.depth;
|
||||
const float compareDepth = preMod.depth;
|
||||
|
||||
float eps = 1.2e-7f;
|
||||
if(depthBits == 24)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffffff))) / float(0xffffff);
|
||||
eps = float(1.0f) / float(0xffffff);
|
||||
}
|
||||
else if(depthBits == 16)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffff))) / float(0xffff);
|
||||
eps = float(1.0f) / float(0xffff);
|
||||
}
|
||||
|
||||
bool passed = true;
|
||||
if(depthFunc == CompareFunction::Equal)
|
||||
passed = shadDepth > compareDepth ? ((shadDepth - compareDepth) <= eps)
|
||||
: ((compareDepth - shadDepth) <= eps);
|
||||
else if(depthFunc == CompareFunction::NotEqual)
|
||||
passed = shadDepth > compareDepth ? ((shadDepth - compareDepth) > eps)
|
||||
: ((compareDepth - shadDepth) > eps);
|
||||
else if(depthFunc == CompareFunction::Less)
|
||||
passed = (shadDepth - eps < compareDepth);
|
||||
else if(depthFunc == CompareFunction::LessEqual)
|
||||
passed = (shadDepth - eps <= compareDepth);
|
||||
else if(depthFunc == CompareFunction::Greater)
|
||||
passed = (shadDepth + eps > compareDepth);
|
||||
else if(depthFunc == CompareFunction::GreaterEqual)
|
||||
passed = (shadDepth + eps >= compareDepth);
|
||||
|
||||
if(!passed)
|
||||
depthTestFailed = true;
|
||||
}
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(PixelModification);
|
||||
|
||||
@@ -2466,35 +2466,20 @@ rdcarray<PixelModification> D3D11Replay::PixelHistory(rdcarray<EventUsage> event
|
||||
if(history[h].preMod.depth >= 0.0f && history[h].shaderOut.depth >= 0.0f)
|
||||
{
|
||||
DXGI_FORMAT dfmt = depthFormats[history[h].eventId];
|
||||
float shadDepth = history[h].shaderOut.depth;
|
||||
|
||||
// quantise depth to match before comparing
|
||||
uint32_t depthBits = 32;
|
||||
if(dfmt == DXGI_FORMAT_D24_UNORM_S8_UINT || dfmt == DXGI_FORMAT_X24_TYPELESS_G8_UINT ||
|
||||
dfmt == DXGI_FORMAT_R24_UNORM_X8_TYPELESS || dfmt == DXGI_FORMAT_R24G8_TYPELESS)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffffff))) / float(0xffffff);
|
||||
depthBits = 24;
|
||||
}
|
||||
else if(dfmt == DXGI_FORMAT_D16_UNORM || dfmt == DXGI_FORMAT_R16_TYPELESS ||
|
||||
dfmt == DXGI_FORMAT_R16_UNORM)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffff))) / float(0xffff);
|
||||
depthBits = 16;
|
||||
}
|
||||
|
||||
bool passed = true;
|
||||
if(depthOps[history[h].eventId] == D3D11_COMPARISON_EQUAL)
|
||||
passed = (shadDepth == history[h].preMod.depth);
|
||||
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_NOT_EQUAL)
|
||||
passed = (shadDepth != history[h].preMod.depth);
|
||||
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_LESS)
|
||||
passed = (shadDepth < history[h].preMod.depth);
|
||||
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_LESS_EQUAL)
|
||||
passed = (shadDepth <= history[h].preMod.depth);
|
||||
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_GREATER)
|
||||
passed = (shadDepth > history[h].preMod.depth);
|
||||
else if(depthOps[history[h].eventId] == D3D11_COMPARISON_GREATER_EQUAL)
|
||||
passed = (shadDepth >= history[h].preMod.depth);
|
||||
|
||||
history[h].depthTestFailed = !passed;
|
||||
history[h].CheckDepthTestQuantised(depthBits, MakeCompareFunc(depthOps[history[h].eventId]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -212,14 +212,15 @@ enum D3D12PixelHistoryTests : uint32_t
|
||||
TestMustFail_SampleMask = 1 << 15,
|
||||
|
||||
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,
|
||||
DepthTest_Mask = 0x7U << DepthTest_Shift,
|
||||
DepthTest_Always = uint32_t(CompareFunction::AlwaysTrue) << DepthTest_Shift,
|
||||
DepthTest_Never = uint32_t(CompareFunction::Never) << DepthTest_Shift,
|
||||
DepthTest_Equal = uint32_t(CompareFunction::Equal) << DepthTest_Shift,
|
||||
DepthTest_NotEqual = uint32_t(CompareFunction::NotEqual) << DepthTest_Shift,
|
||||
DepthTest_Less = uint32_t(CompareFunction::Less) << DepthTest_Shift,
|
||||
DepthTest_LessEqual = uint32_t(CompareFunction::LessEqual) << DepthTest_Shift,
|
||||
DepthTest_Greater = uint32_t(CompareFunction::Greater) << DepthTest_Shift,
|
||||
DepthTest_GreaterEqual = uint32_t(CompareFunction::GreaterEqual) << DepthTest_Shift,
|
||||
};
|
||||
|
||||
static bool IsDepthFormat(D3D12_RESOURCE_DESC desc)
|
||||
@@ -3291,39 +3292,23 @@ rdcarray<PixelModification> D3D12Replay::PixelHistory(rdcarray<EventUsage> event
|
||||
{
|
||||
uint32_t flags = tfCb->GetEventFlags(history[h].eventId);
|
||||
|
||||
flags &= 0x7 << DepthTest_Shift;
|
||||
|
||||
DXGI_FORMAT dfmt = cb.GetDepthFormat(eid);
|
||||
float shadDepth = history[h].shaderOut.depth;
|
||||
|
||||
uint32_t depthBits = 32;
|
||||
// Quantize depth to match before comparing
|
||||
if(dfmt == DXGI_FORMAT_D24_UNORM_S8_UINT || dfmt == DXGI_FORMAT_X24_TYPELESS_G8_UINT ||
|
||||
dfmt == DXGI_FORMAT_R24_UNORM_X8_TYPELESS || dfmt == DXGI_FORMAT_R24G8_TYPELESS)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffffff))) / float(0xffffff);
|
||||
depthBits = 24;
|
||||
}
|
||||
else if(dfmt == DXGI_FORMAT_D16_UNORM || dfmt == DXGI_FORMAT_R16_TYPELESS ||
|
||||
dfmt == DXGI_FORMAT_R16_UNORM)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffff))) / float(0xffff);
|
||||
depthBits = 16;
|
||||
}
|
||||
|
||||
bool passed = true;
|
||||
if(flags == DepthTest_Equal)
|
||||
passed = (shadDepth == history[h].preMod.depth);
|
||||
else if(flags == DepthTest_NotEqual)
|
||||
passed = (shadDepth != history[h].preMod.depth);
|
||||
else if(flags == DepthTest_Less)
|
||||
passed = (shadDepth < history[h].preMod.depth);
|
||||
else if(flags == DepthTest_LessEqual)
|
||||
passed = (shadDepth <= history[h].preMod.depth);
|
||||
else if(flags == DepthTest_Greater)
|
||||
passed = (shadDepth > history[h].preMod.depth);
|
||||
else if(flags == DepthTest_GreaterEqual)
|
||||
passed = (shadDepth >= history[h].preMod.depth);
|
||||
|
||||
if(!passed)
|
||||
history[h].depthTestFailed = true;
|
||||
history[h].CheckDepthTestQuantised(
|
||||
depthBits, CompareFunction((flags & DepthTest_Mask) >> DepthTest_Shift));
|
||||
|
||||
rdcpair<float, float> depthBounds = tfCb->GetEventDepthBounds(history[h].eventId);
|
||||
|
||||
|
||||
@@ -2011,24 +2011,6 @@ void QueryPrimitiveIdPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
}
|
||||
}
|
||||
|
||||
bool depthTestPassed(int depthFunc, float shaderOutputDepth, float depthInBuffer)
|
||||
{
|
||||
switch(depthFunc)
|
||||
{
|
||||
case eGL_NEVER: return false;
|
||||
case eGL_LESS: return shaderOutputDepth < depthInBuffer;
|
||||
case eGL_EQUAL: return shaderOutputDepth == depthInBuffer;
|
||||
case eGL_LEQUAL: return shaderOutputDepth <= depthInBuffer;
|
||||
case eGL_GREATER: return shaderOutputDepth > depthInBuffer;
|
||||
case eGL_NOTEQUAL: return shaderOutputDepth != depthInBuffer;
|
||||
case eGL_GEQUAL: return shaderOutputDepth >= depthInBuffer;
|
||||
case eGL_ALWAYS: return true;
|
||||
|
||||
default: RDCERR("Unexpected depth function: %d", depthFunc);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CalculateFragmentDepthTests(WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
const rdcarray<EventUsage> &modEvents,
|
||||
rdcarray<PixelModification> &history,
|
||||
@@ -2060,9 +2042,9 @@ void CalculateFragmentDepthTests(WrappedOpenGL *driver, GLPixelHistoryResources
|
||||
|
||||
GLboolean depthTestEnabled = driver->glIsEnabled(eGL_DEPTH_TEST);
|
||||
// default for no depth test
|
||||
int depthFunc = eGL_ALWAYS;
|
||||
GLenum depthFunc = eGL_ALWAYS;
|
||||
if(depthTestEnabled)
|
||||
driver->glGetIntegerv(eGL_DEPTH_FUNC, &depthFunc);
|
||||
driver->glGetIntegerv(eGL_DEPTH_FUNC, (int *)&depthFunc);
|
||||
for(; historyIndex < history.size() && modEvents[i].eventId == history[historyIndex].eventId;
|
||||
++historyIndex)
|
||||
{
|
||||
@@ -2071,8 +2053,44 @@ void CalculateFragmentDepthTests(WrappedOpenGL *driver, GLPixelHistoryResources
|
||||
continue;
|
||||
}
|
||||
|
||||
history[historyIndex].depthTestFailed = !depthTestPassed(
|
||||
depthFunc, history[historyIndex].shaderOut.depth, history[historyIndex].preMod.depth);
|
||||
GLuint curDepth = 0;
|
||||
GLint depthType = 0;
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||
(GLint *)&curDepth);
|
||||
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
|
||||
&depthType);
|
||||
|
||||
GLenum depthFormat = eGL_NONE;
|
||||
|
||||
if(curDepth != 0)
|
||||
{
|
||||
ResourceId id;
|
||||
if(depthType != eGL_RENDERBUFFER)
|
||||
{
|
||||
id = driver->GetResourceManager()->GetResID(TextureRes(driver->GetCtx(), curDepth));
|
||||
}
|
||||
else
|
||||
{
|
||||
id = driver->GetResourceManager()->GetResID(RenderbufferRes(driver->GetCtx(), curDepth));
|
||||
}
|
||||
depthFormat = driver->m_Textures[id].internalFormat;
|
||||
|
||||
uint32_t depthBits = 32;
|
||||
if(depthFormat == eGL_DEPTH_COMPONENT24 || depthFormat == eGL_DEPTH24_STENCIL8 ||
|
||||
depthFormat == eGL_UNSIGNED_INT_24_8)
|
||||
{
|
||||
depthBits = 24;
|
||||
}
|
||||
else if(depthFormat == eGL_DEPTH_COMPONENT16)
|
||||
{
|
||||
depthBits = 16;
|
||||
}
|
||||
|
||||
history[historyIndex].CheckDepthTestQuantised(depthBits, MakeCompareFunc(depthFunc));
|
||||
}
|
||||
}
|
||||
|
||||
if(i < modEvents.size() - 1)
|
||||
|
||||
@@ -136,14 +136,15 @@ enum : uint32_t
|
||||
TestMustFail_SampleMask = 1 << 15,
|
||||
|
||||
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,
|
||||
DepthTest_Mask = 0x7U << DepthTest_Shift,
|
||||
DepthTest_Always = uint32_t(CompareFunction::AlwaysTrue) << DepthTest_Shift,
|
||||
DepthTest_Never = uint32_t(CompareFunction::Never) << DepthTest_Shift,
|
||||
DepthTest_Equal = uint32_t(CompareFunction::Equal) << DepthTest_Shift,
|
||||
DepthTest_NotEqual = uint32_t(CompareFunction::NotEqual) << DepthTest_Shift,
|
||||
DepthTest_Less = uint32_t(CompareFunction::Less) << DepthTest_Shift,
|
||||
DepthTest_LessEqual = uint32_t(CompareFunction::LessEqual) << DepthTest_Shift,
|
||||
DepthTest_Greater = uint32_t(CompareFunction::Greater) << DepthTest_Shift,
|
||||
DepthTest_GreaterEqual = uint32_t(CompareFunction::GreaterEqual) << DepthTest_Shift,
|
||||
};
|
||||
|
||||
struct VkCopyPixelParams
|
||||
@@ -4890,39 +4891,19 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
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);
|
||||
const uint32_t flags = tfCb->GetEventFlags(history[h].eventId);
|
||||
|
||||
flags &= 0x7 << DepthTest_Shift;
|
||||
|
||||
VkFormat dfmt = cb.GetDepthFormat(eid);
|
||||
float shadDepth = history[h].shaderOut.depth;
|
||||
const VkFormat dfmt = cb.GetDepthFormat(eid);
|
||||
uint32_t depthBits = 32;
|
||||
|
||||
// quantise depth to match before comparing
|
||||
if(dfmt == VK_FORMAT_D24_UNORM_S8_UINT || dfmt == VK_FORMAT_X8_D24_UNORM_PACK32)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffffff))) / float(0xffffff);
|
||||
}
|
||||
depthBits = 24;
|
||||
else if(dfmt == VK_FORMAT_D16_UNORM || dfmt == VK_FORMAT_D16_UNORM_S8_UINT)
|
||||
{
|
||||
shadDepth = float(uint32_t(float(shadDepth * 0xffff))) / float(0xffff);
|
||||
}
|
||||
depthBits = 16;
|
||||
|
||||
bool passed = true;
|
||||
if(flags == DepthTest_Equal)
|
||||
passed = (shadDepth == history[h].preMod.depth);
|
||||
else if(flags == DepthTest_NotEqual)
|
||||
passed = (shadDepth != history[h].preMod.depth);
|
||||
else if(flags == DepthTest_Less)
|
||||
passed = (shadDepth < history[h].preMod.depth);
|
||||
else if(flags == DepthTest_LessEqual)
|
||||
passed = (shadDepth <= history[h].preMod.depth);
|
||||
else if(flags == DepthTest_Greater)
|
||||
passed = (shadDepth > history[h].preMod.depth);
|
||||
else if(flags == DepthTest_GreaterEqual)
|
||||
passed = (shadDepth >= history[h].preMod.depth);
|
||||
|
||||
if(!passed)
|
||||
history[h].depthTestFailed = true;
|
||||
history[h].CheckDepthTestQuantised(
|
||||
depthBits, CompareFunction((flags & DepthTest_Mask) >> DepthTest_Shift));
|
||||
|
||||
rdcpair<float, float> depthBounds = tfCb->GetEventDepthBounds(history[h].eventId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user