mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-05 22:31:08 +00:00
Add test for MSAA evals to D3D11_Shader_Debug_Zoo
This commit is contained in:
committed by
Baldur Karlsson
parent
2ca43b82bd
commit
a5583b83ee
@@ -2707,22 +2707,34 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position,
|
||||
{
|
||||
DebugHit *hit = (DebugHit *)(initialData + i * structStride);
|
||||
|
||||
if(winner == NULL || (winner->sample != sample && hit->sample == sample) ||
|
||||
depthFunc == D3D11_COMPARISON_ALWAYS || depthFunc == D3D11_COMPARISON_NEVER ||
|
||||
depthFunc == D3D11_COMPARISON_NOT_EQUAL || depthFunc == D3D11_COMPARISON_EQUAL)
|
||||
if(winner == NULL)
|
||||
{
|
||||
// If we haven't picked a winner at all yet, use the first one
|
||||
winner = hit;
|
||||
evalSampleCache = ((float *)evalData) + evalSampleCacheData.size() * 4 * i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if((depthFunc == D3D11_COMPARISON_LESS && hit->depth < winner->depth) ||
|
||||
(depthFunc == D3D11_COMPARISON_LESS_EQUAL && hit->depth <= winner->depth) ||
|
||||
(depthFunc == D3D11_COMPARISON_GREATER && hit->depth > winner->depth) ||
|
||||
(depthFunc == D3D11_COMPARISON_GREATER_EQUAL && hit->depth >= winner->depth))
|
||||
else if(hit->sample == sample)
|
||||
{
|
||||
if(hit->sample == sample)
|
||||
// If this hit is for the sample we want, check whether it's a better pick
|
||||
if(winner->sample != sample)
|
||||
{
|
||||
// The previously selected winner was for the wrong sample, use this one
|
||||
winner = hit;
|
||||
evalSampleCache = ((float *)evalData) + evalSampleCacheData.size() * 4 * i;
|
||||
}
|
||||
else if((depthFunc == D3D11_COMPARISON_ALWAYS || depthFunc == D3D11_COMPARISON_NEVER ||
|
||||
depthFunc == D3D11_COMPARISON_NOT_EQUAL || depthFunc == D3D11_COMPARISON_EQUAL))
|
||||
{
|
||||
// For depth functions without an inequality comparison, use the last sample encountered
|
||||
winner = hit;
|
||||
evalSampleCache = ((float *)evalData) + evalSampleCacheData.size() * 4 * i;
|
||||
}
|
||||
else if((depthFunc == D3D11_COMPARISON_LESS && hit->depth < winner->depth) ||
|
||||
(depthFunc == D3D11_COMPARISON_LESS_EQUAL && hit->depth <= winner->depth) ||
|
||||
(depthFunc == D3D11_COMPARISON_GREATER && hit->depth > winner->depth) ||
|
||||
(depthFunc == D3D11_COMPARISON_GREATER_EQUAL && hit->depth >= winner->depth))
|
||||
{
|
||||
// For depth functions with an inequality, find the hit that "wins" the most
|
||||
winner = hit;
|
||||
evalSampleCache = ((float *)evalData) + evalSampleCacheData.size() * 4 * i;
|
||||
}
|
||||
@@ -2844,7 +2856,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position,
|
||||
global.sampleEvalCache[k] = var;
|
||||
}
|
||||
|
||||
// advance past this data - always by float4 as that's the buffer st ride
|
||||
// advance past this data - always by float4 as that's the buffer stride
|
||||
evalSampleCache += 4;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,12 +310,18 @@ bool OperationFlushing(const DXBCBytecode::OpcodeType &op)
|
||||
case OPCODE_GATHER4_PO_C:
|
||||
return true;
|
||||
|
||||
// unclear if these flush and it's unlikely denorms will come up, so conservatively flush
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
case OPCODE_SAMPLE_POS:
|
||||
// don't flush eval ops as some inputs may be uint
|
||||
case OPCODE_EVAL_CENTROID:
|
||||
case OPCODE_EVAL_SAMPLE_INDEX:
|
||||
case OPCODE_EVAL_SNAPPED:
|
||||
return false;
|
||||
|
||||
// don't flush samplepos since an operand is scalar
|
||||
case OPCODE_SAMPLE_POS:
|
||||
return false;
|
||||
|
||||
// unclear if these flush and it's unlikely denorms will come up, so conservatively flush
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
case OPCODE_LOD:
|
||||
case OPCODE_DERIV_RTX:
|
||||
case OPCODE_DERIV_RTX_COARSE:
|
||||
|
||||
@@ -560,6 +560,31 @@ float4 main(v2f IN) : SV_Target0
|
||||
return float4(0.4f, 0.4f, 0.4f, 0.4f);
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
std::string msaaPixel = R"EOSHADER(
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float4 col : COLOR0;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0
|
||||
{
|
||||
float2 uvCentroid = EvaluateAttributeCentroid(IN.uv);
|
||||
float2 uvSamp0 = EvaluateAttributeAtSample(IN.uv, 0) - IN.uv;
|
||||
float2 uvSampThis = EvaluateAttributeAtSample(IN.uv, samp) - IN.uv;
|
||||
float2 uvOffset = EvaluateAttributeSnapped(IN.uv, int2(1, 1));
|
||||
|
||||
float x = (uvCentroid.x + uvCentroid.y) * 0.5f;
|
||||
float y = (uvSamp0.x + uvSamp0.y) * 0.5f;
|
||||
float z = (uvSampThis.x + uvSampThis.y) * 0.5f;
|
||||
float w = (uvOffset.x + uvOffset.y) * 0.5f;
|
||||
return float4(x, y, z, w);
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
int main()
|
||||
@@ -661,6 +686,21 @@ float4 main(v2f IN) : SV_Target0
|
||||
|
||||
ctx->PSSetShaderResources(0, ARRAY_COUNT(srvs), srvs);
|
||||
|
||||
// Create resources for MSAA draw
|
||||
ID3DBlobPtr vsmsaablob = Compile(D3DDefaultVertex, "main", "vs_5_0");
|
||||
ID3DBlobPtr psmsaablob = Compile(msaaPixel, "main", "ps_5_0");
|
||||
|
||||
CreateDefaultInputLayout(vsmsaablob);
|
||||
|
||||
ID3D11VertexShaderPtr vsmsaa = CreateVS(vsmsaablob);
|
||||
ID3D11PixelShaderPtr psmsaa = CreatePS(psmsaablob);
|
||||
|
||||
ID3D11BufferPtr vbmsaa = MakeBuffer().Vertex().Data(DefaultTri);
|
||||
|
||||
ID3D11Texture2DPtr msaaTex =
|
||||
MakeTexture(DXGI_FORMAT_R32G32B32A32_FLOAT, 8, 8).Multisampled(4).RTV();
|
||||
ID3D11RenderTargetViewPtr msaaRT = MakeRTV(msaaTex);
|
||||
|
||||
while(Running())
|
||||
{
|
||||
ClearRenderTargetView(fltRT, {0.2f, 0.2f, 0.2f, 1.0f});
|
||||
@@ -684,6 +724,15 @@ float4 main(v2f IN) : SV_Target0
|
||||
|
||||
ctx->DrawInstanced(3, numTests, 0, 0);
|
||||
|
||||
ctx->OMSetRenderTargets(1, &msaaRT.GetInterfacePtr(), NULL);
|
||||
|
||||
RSSetViewport({0.0f, 0.0f, 8.0f, 8.0f, 0.0f, 1.0f});
|
||||
IASetVertexBuffer(vbmsaa, sizeof(DefaultA2V), 0);
|
||||
ctx->IASetInputLayout(defaultLayout);
|
||||
ctx->VSSetShader(vsmsaa, NULL, 0);
|
||||
ctx->PSSetShader(psmsaa, NULL, 0);
|
||||
ctx->Draw(3, 0);
|
||||
|
||||
Present();
|
||||
}
|
||||
|
||||
|
||||
@@ -333,6 +333,40 @@ class TestCase:
|
||||
|
||||
log.success("Picked value at {},{} in {} is as expected".format(x, y, res_details.name))
|
||||
|
||||
def check_pixel_sample_value(self, tex: rd.ResourceId, x, y, sample, value, eps=util.FLT_EPSILON):
|
||||
tex_details = self.get_texture(tex)
|
||||
res_details = self.get_resource(tex)
|
||||
|
||||
if type(x) is float:
|
||||
x = int((tex_details.width-1) * x)
|
||||
if type(y) is float:
|
||||
y = int((tex_details.height-1) * y)
|
||||
|
||||
cast = rd.CompType.Typeless
|
||||
if tex_details.creationFlags & rd.TextureCategory.SwapBuffer:
|
||||
cast = rd.CompType.UNormSRGB
|
||||
|
||||
# Reduce epsilon for RGBA8 textures if it's not already reduced
|
||||
if tex_details.format.compByteWidth == 1 and eps == util.FLT_EPSILON:
|
||||
eps = (1.0 / 255.0)
|
||||
|
||||
picked: rd.PixelValue = self.controller.PickPixel(tex, x, y, rd.Subresource(0, 0, sample), cast)
|
||||
|
||||
if not util.value_compare(picked.floatValue, value, eps):
|
||||
save_data = rd.TextureSave()
|
||||
save_data.resourceId = tex
|
||||
save_data.destType = rd.FileType.PNG
|
||||
|
||||
img_path = util.get_tmp_path('output.png')
|
||||
|
||||
self.controller.SaveTexture(save_data, img_path)
|
||||
|
||||
raise TestFailureException(
|
||||
"Picked value {} at {},{} sample {} doesn't match expectation of {}".
|
||||
format(picked.floatValue, x, y, sample, value), img_path)
|
||||
|
||||
log.success("Picked value at {},{} sample {} in {} is as expected".format(x, y, sample, res_details.name))
|
||||
|
||||
def check_triangle(self, out = None, back = None, fore = None, vp = None):
|
||||
pipe: rd.PipeState = self.controller.GetPipelineState()
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ class D3D11_Shader_Debug_Zoo(rdtest.TestCase):
|
||||
failed = False
|
||||
|
||||
# Loop over every test
|
||||
rdtest.log.print("Performing general tests:")
|
||||
rdtest.log.indent()
|
||||
for test in range(draw.numInstances):
|
||||
# Debug the shader
|
||||
trace: rd.ShaderDebugTrace = self.controller.DebugPixel(4 * test, 0, rd.ReplayController.NoPreference,
|
||||
@@ -38,6 +40,40 @@ class D3D11_Shader_Debug_Zoo(rdtest.TestCase):
|
||||
self.controller.FreeTrace(trace)
|
||||
|
||||
rdtest.log.success("Test {} matched as expected".format(test))
|
||||
rdtest.log.dedent()
|
||||
|
||||
rdtest.log.print("Performing MSAA tests:")
|
||||
rdtest.log.indent()
|
||||
draw = draw.next
|
||||
self.controller.SetFrameEvent(draw.eventId, False)
|
||||
pipe: rd.PipeState = self.controller.GetPipelineState()
|
||||
for test in range(4):
|
||||
# Debug the shader
|
||||
trace: rd.ShaderDebugTrace = self.controller.DebugPixel(4, 4, test,
|
||||
rd.ReplayController.NoPreference)
|
||||
|
||||
# Validate that the correct sample index was debugged
|
||||
inputs: List[rd.ShaderVariable] = list(trace.inputs)
|
||||
sampRegister = self.find_input_source_var(trace, rd.ShaderBuiltin.MSAASampleIndex)
|
||||
sampInput = [var for var in inputs if var.name == sampRegister.variables[0].name][0]
|
||||
if sampInput.value.uv[0] != test:
|
||||
rdtest.log.error("Test {} did not pick the correct sample.".format(test))
|
||||
|
||||
cycles, variables = self.process_trace(trace)
|
||||
|
||||
output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0)
|
||||
|
||||
debugged = self.evalute_source_var(output, variables)
|
||||
|
||||
# Validate the debug output result
|
||||
try:
|
||||
self.check_pixel_sample_value(pipe.GetOutputTargets()[0].resourceId, 4, 4, test, debugged.value.fv[0:4], 0.0)
|
||||
except rdtest.TestFailureException as ex:
|
||||
failed = True
|
||||
rdtest.log.error("Test {} did not match. {}".format(test, str(ex)))
|
||||
continue
|
||||
|
||||
rdtest.log.dedent()
|
||||
|
||||
if failed:
|
||||
raise rdtest.TestFailureException("Some tests were not as expected")
|
||||
|
||||
Reference in New Issue
Block a user