Handle collisions with existing UAVs in root signature when patching

* When debugging a pixel or doing quad overdraw we replace the pixel shader and
  patch in our own UAV. Previously we were moving other UAVs out of the way that
  were visible to the pixel shader, but this fails if a UAV is visible to all
  stages and used in a vertex stage.
* Now instead for pixel shader inputs we pick a free space and use it. For quad
  overdraw we pick an arbitrary high space to hopefully use the precompiled
  shader, and if it's somehow not free we recompile the shader with a free
  space.
This commit is contained in:
baldurk
2023-01-06 13:18:57 +00:00
parent 779a8af657
commit 220b26aa59
11 changed files with 351 additions and 40 deletions
+4
View File
@@ -259,6 +259,10 @@ cbuffer DebugSampleOperation REG(b0)
#define FLT_EPSILON 1.192092896e-07f
#endif
// we pick a space that hopefully no-one else will use
// must match the define in quadoverdraw.hlsl
#define QUADOVERDRAW_UAV_SPACE 105202922
// histogram/minmax is calculated in blocks of NxN each with MxM tiles.
// e.g. a tile is 32x32 pixels, then this is arranged in blocks of 32x32 tiles.
// 1 compute thread = 1 tile, 1 compute group = 1 block
+10
View File
@@ -29,7 +29,17 @@
// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx
////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(UAV_SPACE) && defined(D3D12)
// must match the define in hlsl_cbuffers.h
#define UAV_SPACE space105202922
#endif
#if defined(D3D12)
RWTexture2DArray<uint> overdrawUAV : register(u0, UAV_SPACE);
#else
RWTexture2DArray<uint> overdrawUAV : register(u0);
#endif
Texture2DArray<uint> overdrawSRV : register(t0);
[earlydepthstencil] void RENDERDOC_QuadOverdrawPS(float4 vpos
+28 -13
View File
@@ -1949,8 +1949,10 @@ void D3D12Replay::OverlayRendering::Init(WrappedID3D12Device *device, D3D12Debug
rdcstr hlsl = GetEmbeddedResource(quadoverdraw_hlsl);
hlsl = "#define D3D12 1\n\n" + hlsl;
shaderCache->GetShaderBlob(hlsl.c_str(), "RENDERDOC_QuadOverdrawPS",
D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "ps_5_0", &QuadOverdrawWritePS);
D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "ps_5_1", &QuadOverdrawWritePS);
// only create DXIL shaders if DXIL was used by the application, since dxc/dxcompiler is really
// flakey.
@@ -2480,15 +2482,17 @@ void D3D12Replay::HistogramMinMax::Release()
SAFE_RELEASE(MinMaxTileBuffer);
}
void MoveRootSignatureElementsToRegisterSpace(D3D12RootSignature &sig, uint32_t registerSpace,
D3D12DescriptorType type,
D3D12_SHADER_VISIBILITY visibility)
uint32_t GetFreeRegSpace(const D3D12RootSignature &sig, const uint32_t registerSpace,
D3D12DescriptorType type, D3D12_SHADER_VISIBILITY visibility)
{
// This function is used when root signature elements need to be added to a specific register
// space, such as for debug overlays. We can't remove elements from the root signature entirely
// because then then the root signature indices wouldn't match up as expected. Instead move them
// into the specified register space so that another register space (commonly space0) can be used
// for other purposes.
// because then then the root signature indices wouldn't match up as expected. Instead we see if a
// given desired register space is unused (which can be referenced in pre-compiled shaders), and
// if not return an unused space for use instead.
uint32_t maxSpace = 0;
bool usedDesiredSpace = false;
size_t numParams = sig.Parameters.size();
for(size_t i = 0; i < numParams; i++)
{
@@ -2504,32 +2508,43 @@ void MoveRootSignatureElementsToRegisterSpace(D3D12RootSignature &sig, uint32_t
D3D12_DESCRIPTOR_RANGE_TYPE rangeType = sig.Parameters[i].ranges[r].RangeType;
if(rangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV && type == D3D12DescriptorType::CBV)
{
sig.Parameters[i].ranges[r].RegisterSpace += registerSpace;
maxSpace = RDCMAX(maxSpace, sig.Parameters[i].ranges[r].RegisterSpace);
usedDesiredSpace |= (sig.Parameters[i].ranges[r].RegisterSpace == registerSpace);
}
else if(rangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV && type == D3D12DescriptorType::SRV)
{
sig.Parameters[i].ranges[r].RegisterSpace += registerSpace;
maxSpace = RDCMAX(maxSpace, sig.Parameters[i].ranges[r].RegisterSpace);
usedDesiredSpace |= (sig.Parameters[i].ranges[r].RegisterSpace == registerSpace);
}
else if(rangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV && type == D3D12DescriptorType::UAV)
{
sig.Parameters[i].ranges[r].RegisterSpace += registerSpace;
maxSpace = RDCMAX(maxSpace, sig.Parameters[i].ranges[r].RegisterSpace);
usedDesiredSpace |= (sig.Parameters[i].ranges[r].RegisterSpace == registerSpace);
}
}
}
else if(rootType == D3D12_ROOT_PARAMETER_TYPE_CBV && type == D3D12DescriptorType::CBV)
{
sig.Parameters[i].Descriptor.RegisterSpace += registerSpace;
maxSpace = RDCMAX(maxSpace, sig.Parameters[i].Descriptor.RegisterSpace);
usedDesiredSpace |= (sig.Parameters[i].Descriptor.RegisterSpace == registerSpace);
}
else if(rootType == D3D12_ROOT_PARAMETER_TYPE_SRV && type == D3D12DescriptorType::SRV)
{
sig.Parameters[i].Descriptor.RegisterSpace += registerSpace;
maxSpace = RDCMAX(maxSpace, sig.Parameters[i].Descriptor.RegisterSpace);
usedDesiredSpace |= (sig.Parameters[i].Descriptor.RegisterSpace == registerSpace);
}
else if(rootType == D3D12_ROOT_PARAMETER_TYPE_UAV && type == D3D12DescriptorType::UAV)
{
sig.Parameters[i].Descriptor.RegisterSpace += registerSpace;
maxSpace = RDCMAX(maxSpace, sig.Parameters[i].Descriptor.RegisterSpace);
usedDesiredSpace |= (sig.Parameters[i].Descriptor.RegisterSpace == registerSpace);
}
}
}
if(usedDesiredSpace)
return maxSpace + 1;
return registerSpace;
}
void AddDebugDescriptorsToRenderState(WrappedID3D12Device *pDevice, D3D12RenderState &rs,
+2 -3
View File
@@ -253,9 +253,8 @@ private:
rdcarray<ID3D12Resource *> m_DiscardBuffers;
};
void MoveRootSignatureElementsToRegisterSpace(D3D12RootSignature &sig, uint32_t registerSpace,
D3D12DescriptorType type,
D3D12_SHADER_VISIBILITY visibility);
uint32_t GetFreeRegSpace(const D3D12RootSignature &sig, const uint32_t registerSpace,
D3D12DescriptorType type, D3D12_SHADER_VISIBILITY visibility);
void AddDebugDescriptorsToRenderState(WrappedID3D12Device *pDevice, D3D12RenderState &rs,
const rdcarray<PortableHandle> &handles,
+33 -6
View File
@@ -87,15 +87,20 @@ struct D3D12QuadOverdrawCallback : public D3D12ActionCallback
D3D12RootSignature modsig = sig->sig;
UINT regSpace = modsig.maxSpaceIndex + 1;
MoveRootSignatureElementsToRegisterSpace(modsig, regSpace, D3D12DescriptorType::UAV,
D3D12_SHADER_VISIBILITY_PIXEL);
uint32_t regSpace = GetFreeRegSpace(modsig, QUADOVERDRAW_UAV_SPACE, D3D12DescriptorType::UAV,
D3D12_SHADER_VISIBILITY_PIXEL);
if(regSpace != QUADOVERDRAW_UAV_SPACE)
{
RDCLOG("Register space %u wasn't available for use, recompiling shaders",
QUADOVERDRAW_UAV_SPACE);
}
D3D12_DESCRIPTOR_RANGE1 range;
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
range.NumDescriptors = 1;
range.BaseShaderRegister = 0;
range.RegisterSpace = 0;
range.RegisterSpace = regSpace;
range.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
range.OffsetInDescriptorsFromTableStart = 0;
@@ -147,7 +152,7 @@ struct D3D12QuadOverdrawCallback : public D3D12ActionCallback
// dxil is stricter about pipeline signatures matching. On D3D11 there's an error but all
// drivers handle a PS that reads no VS outputs and only screenspace SV_Position and
// SV_Coverage. On D3D12 we need to patch to generate a new PS
m_pDevice->GetReplay()->PatchQuadWritePS(pipeDesc, dxil);
m_pDevice->GetReplay()->PatchQuadWritePS(pipeDesc, regSpace, dxil);
if(pipeDesc.PS.BytecodeLength == 0)
{
m_pDevice->AddDebugMessage(
@@ -296,13 +301,35 @@ static void SetRTVDesc(D3D12_RENDER_TARGET_VIEW_DESC &rtDesc, const D3D12_RESOUR
}
}
void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pipeDesc, bool dxil)
void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pipeDesc,
uint32_t regSpace, bool dxil)
{
pipeDesc.PS.pShaderBytecode = NULL;
pipeDesc.PS.BytecodeLength = 0;
ID3DBlob *quadWriteBlob = dxil ? m_Overlay.QuadOverdrawWriteDXILPS : m_Overlay.QuadOverdrawWritePS;
if(regSpace != QUADOVERDRAW_UAV_SPACE)
{
rdcstr hlsl = GetEmbeddedResource(quadoverdraw_hlsl);
hlsl =
"#define D3D12 1\n\n" + StringFormat::Fmt("#define UAV_SPACE space%u\n\n", regSpace) + hlsl;
if(dxil)
{
m_pDevice->GetShaderCache()->GetShaderBlob(hlsl.c_str(), "RENDERDOC_QuadOverdrawPS",
D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "ps_6_0",
&quadWriteBlob);
}
else
{
m_pDevice->GetShaderCache()->GetShaderBlob(hlsl.c_str(), "RENDERDOC_QuadOverdrawPS",
D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "ps_5_1",
&quadWriteBlob);
}
}
if(!quadWriteBlob)
{
RDCERR("Compiled quad overdraw write %s blob isn't available", dxil ? "DXIL" : "DXBC");
+2 -1
View File
@@ -256,7 +256,8 @@ public:
bool IsRenderOutput(ResourceId id) { return GetRenderOutputSubresource(id).mip != ~0U; }
void FileChanged() {}
AMDCounters *GetAMDCounters() { return m_pAMDCounters; }
void PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pipeDesc, bool dxil);
void PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pipeDesc, uint32_t regSpace,
bool dxil);
private:
void FillRootElements(uint32_t eventId, const D3D12RenderState::RootSignature &rootSig,
@@ -517,7 +517,7 @@ rdcstr D3D12ShaderCache::GetShaderBlob(const char *source, const char *entry,
}
}
if(m_CacheShaders)
if(m_CacheShaders && byteBlob)
{
m_ShaderCache[hash] = byteBlob;
byteBlob->AddRef();
+15 -15
View File
@@ -2055,14 +2055,25 @@ struct PSInitialData
)";
WrappedID3D12RootSignature *sig =
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rs.graphics.rootsig);
// Need to be able to add a descriptor table with our UAV without hitting the 64 DWORD limit
RDCASSERT(sig->sig.dwordLength < 64);
D3D12RootSignature modsig = sig->sig;
UINT regSpace = GetFreeRegSpace(modsig, 0, D3D12DescriptorType::UAV, D3D12_SHADER_VISIBILITY_PIXEL);
// If this event uses MSAA, then at least one render target must be preserved to get
// multisampling info. leave u0 alone and start with register u1
extractHlsl += "RWStructuredBuffer<PSInitialData> PSInitialBuffer : register(u1);\n\n";
extractHlsl += StringFormat::Fmt(
"RWStructuredBuffer<PSInitialData> PSInitialBuffer : register(u1, space%u);\n\n", regSpace);
if(!evalSampleCacheData.empty())
{
// float4 is wasteful in some cases but it's easier than using byte buffers and manual packing
extractHlsl += "RWBuffer<float4> PSEvalBuffer : register(u2);\n\n";
extractHlsl +=
StringFormat::Fmt("RWBuffer<float4> PSEvalBuffer : register(u2, space%u);\n\n", regSpace);
}
if(usePrimitiveID)
@@ -2188,7 +2199,7 @@ void ExtractInputsPS(PSInput IN,
ID3DBlob *psBlob = NULL;
UINT flags = D3DCOMPILE_WARNINGS_ARE_ERRORS;
if(m_pDevice->GetShaderCache()->GetShaderBlob(extractHlsl.c_str(), "ExtractInputsPS", flags, {},
"ps_5_0", &psBlob) != "")
"ps_5_1", &psBlob) != "")
{
RDCERR("Failed to create shader to extract inputs");
return new ShaderDebugTrace;
@@ -2293,23 +2304,12 @@ void ExtractInputsPS(PSInput IN,
m_pDevice->CreateUnorderedAccessView(pMsaaEvalBuffer, NULL, &uavDesc, msaaClearUav);
}
WrappedID3D12RootSignature *sig =
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rs.graphics.rootsig);
// Need to be able to add a descriptor table with our UAV without hitting the 64 DWORD limit
RDCASSERT(sig->sig.dwordLength < 64);
D3D12RootSignature modsig = sig->sig;
UINT regSpace = modsig.maxSpaceIndex + 1;
MoveRootSignatureElementsToRegisterSpace(modsig, regSpace, D3D12DescriptorType::UAV,
D3D12_SHADER_VISIBILITY_PIXEL);
// Create the descriptor table for our UAV
D3D12_DESCRIPTOR_RANGE1 descRange;
descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
descRange.NumDescriptors = pMsaaEvalBuffer ? 2 : 1;
descRange.BaseShaderRegister = 1;
descRange.RegisterSpace = 0;
descRange.RegisterSpace = regSpace;
descRange.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
descRange.OffsetInDescriptorsFromTableStart = 0;
+1 -1
View File
@@ -820,7 +820,7 @@ namespace DXCEnumerateAndCheck {
<Exec Command="&quot;$(DXCExecutable)&quot; &quot;$(ProjectDir)data\hlsl\fixedcol.hlsl&quot; -T ps_6_0 -DVARIANT=1 -E main -Qstrip_reflect -Fo &quot;$(DXILBakedDir)fixedcol_1.dxbc&quot;" />
<Exec Command="&quot;$(DXCExecutable)&quot; &quot;$(ProjectDir)data\hlsl\fixedcol.hlsl&quot; -T ps_6_0 -DVARIANT=2 -E main -Qstrip_reflect -Fo &quot;$(DXILBakedDir)fixedcol_2.dxbc&quot;" />
<Exec Command="&quot;$(DXCExecutable)&quot; &quot;$(ProjectDir)data\hlsl\fixedcol.hlsl&quot; -T ps_6_0 -DVARIANT=3 -E main -Qstrip_reflect -Fo &quot;$(DXILBakedDir)fixedcol_3.dxbc&quot;" />
<Exec Command="&quot;$(DXCExecutable)&quot; &quot;$(ProjectDir)data\hlsl\quadoverdraw.hlsl&quot; -T ps_6_0 -E RENDERDOC_QuadOverdrawPS -Qstrip_reflect -Fo &quot;$(DXILBakedDir)quadwrite.dxbc&quot;" />
<Exec Command="&quot;$(DXCExecutable)&quot; &quot;$(ProjectDir)data\hlsl\quadoverdraw.hlsl&quot; -T ps_6_0 -DD3D12=1 -E RENDERDOC_QuadOverdrawPS -Qstrip_reflect -Fo &quot;$(DXILBakedDir)quadwrite.dxbc&quot;" />
</Target>
<ItemGroup>
<Natvis Include="renderdoc.natvis" />
+181
View File
@@ -0,0 +1,181 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2022 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "d3d12_test.h"
RD_TEST(D3D12_Vertex_UAV, D3D12GraphicsTest)
{
static constexpr const char *Description =
"Runs some tests with a vertex shader visible UAV to test that root signature patching for "
"any PS UAVs works correctly";
std::string vertex = R"EOSHADER(
#ifndef SPACE
#define SPACE space0
#endif
#if SM >= 51
RWByteAddressBuffer testUAV : register(u0, SPACE);
RWByteAddressBuffer testUAV2 : register(u1, SPACE);
#else
RWByteAddressBuffer testUAV : register(u0);
RWByteAddressBuffer testUAV2 : register(u1);
#endif
struct v2f
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
v2f main(uint vid : SV_VertexID)
{
float2 positions[] = {
float2(-1.0f, 1.0f),
float2( 1.0f, 1.0f),
float2(-1.0f, -1.0f),
float2( 1.0f, -1.0f),
};
float a = asfloat(testUAV.Load(16));
float b = asfloat(testUAV2.Load(16));
v2f ret;
ret.pos = float4(positions[vid] * float2(a, b), 0, 1);
ret.col = float4(a, b, 0, 1);
ret.uv = float2(a, b);
return ret;
}
)EOSHADER";
int main()
{
// initialise, create window, create device, etc
if(!Init())
return 3;
ID3D12ResourcePtr vb = MakeBuffer().Data(DefaultTri);
ID3D12RootSignaturePtr sig = MakeSig({
uavParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0), uavParam(D3D12_SHADER_VISIBILITY_VERTEX, 0, 1),
});
// 105202922 is the magic space renderdoc tries to use to avoid collisions
ID3D12RootSignaturePtr collidesig = MakeSig({
uavParam(D3D12_SHADER_VISIBILITY_ALL, 105202922, 0),
uavParam(D3D12_SHADER_VISIBILITY_VERTEX, 105202922, 1),
});
ID3D12PipelineStatePtr pso[3];
ID3D12PipelineStatePtr collidepso[3];
std::string smstring[] = {"5_0", "5_1", "6_0"};
int smval[] = {50, 51, 60};
for(int i = 0; i < 3; i++)
{
if(smval[i] == 60 && !m_DXILSupport)
continue;
std::string sm = smstring[i];
std::string header = "#define SM " + std::to_string(smval[i]) + "\n\n";
ID3DBlobPtr vsblob = Compile(header + vertex, "main", "vs_" + sm);
header += "#define SPACE space105202922\n\n";
ID3DBlobPtr collidevsblob = Compile(header + vertex, "main", "vs_" + sm);
ID3DBlobPtr psblob = Compile(D3DDefaultPixel, "main", "ps_" + sm);
pso[i] = MakePSO().RootSig(sig).InputLayout().VS(vsblob).PS(psblob);
if(smval[i] >= 51)
collidepso[i] = MakePSO().RootSig(collidesig).InputLayout().VS(collidevsblob).PS(psblob);
}
ResourceBarrier(vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
ID3D12ResourcePtr uav = MakeBuffer().Data(DefaultTri).UAV();
ResourceBarrier(uav, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
while(Running())
{
ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer();
Reset(cmd);
ID3D12ResourcePtr bb = StartUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12_CPU_DESCRIPTOR_HANDLE rtv =
MakeRTV(bb).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(0);
ClearRenderTargetView(cmd, rtv, {0.2f, 0.2f, 0.2f, 1.0f});
cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0);
RSSetViewport(cmd, {0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f});
RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight});
OMSetRenderTargets(cmd, {rtv}, {});
for(int i = 0; i < 3; i++)
{
if(pso[i] == NULL)
continue;
setMarker(cmd, "Normal_" + smstring[i]);
cmd->SetPipelineState(pso[i]);
cmd->SetGraphicsRootSignature(sig);
cmd->SetGraphicsRootUnorderedAccessView(0, uav->GetGPUVirtualAddress());
cmd->SetGraphicsRootUnorderedAccessView(1, uav->GetGPUVirtualAddress());
cmd->DrawInstanced(3, 1, 0, 0);
if(collidepso[i] == NULL)
continue;
setMarker(cmd, "Collide_" + smstring[i]);
cmd->SetPipelineState(collidepso[i]);
cmd->SetGraphicsRootSignature(collidesig);
cmd->SetGraphicsRootUnorderedAccessView(0, uav->GetGPUVirtualAddress());
cmd->SetGraphicsRootUnorderedAccessView(1, uav->GetGPUVirtualAddress());
cmd->DrawInstanced(3, 1, 0, 0);
}
FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET);
cmd->Close();
Submit({cmd});
Present();
}
return 0;
}
};
REGISTER_TEST();
+74
View File
@@ -0,0 +1,74 @@
import rdtest
import renderdoc as rd
class D3D12_Vertex_UAV(rdtest.TestCase):
demos_test_name = 'D3D12_Vertex_UAV'
def check_capture(self):
out: rd.ReplayOutput = self.controller.CreateOutput(rd.CreateHeadlessWindowingData(100, 100), rd.ReplayOutputType.Texture)
quad_seen = []
for pass_name in ["Normal", "Collide"]:
for base_event_name in ["5_0", "5_1", "6_0"]:
name = pass_name + "_" + base_event_name
marker = self.find_action(name)
if marker is None:
continue
rdtest.log.print("Checking quad overdraw on {}".format(name))
self.controller.SetFrameEvent(marker.next.eventId, True)
pipe: rd.PipeState = self.controller.GetPipelineState()
tex = rd.TextureDisplay()
tex.resourceId = pipe.GetOutputTargets()[0].resourceId
tex.overlay = rd.DebugOverlay.QuadOverdrawPass
out.SetTextureDisplay(tex)
out.Display()
overlay_id: rd.ResourceId = out.GetDebugOverlayTexID()
picked = self.controller.PickPixel(overlay_id, 5, 5, rd.Subresource(0,0,0), rd.CompType.Float).floatValue
if any([p != picked[0] for p in picked]):
raise rdtest.TestFailureException("Quad overdraw isn't correct: {}".format(picked))
quad_seen.append(picked[0])
rdtest.log.success("Quad overdraw is good on {}".format(name))
if not pipe.GetShaderReflection(rd.ShaderStage.Pixel).debugInfo.debuggable:
rdtest.log.print("Skipping undebuggable shader.")
continue
# Debug the shader
trace = self.controller.DebugPixel(50, 50, rd.ReplayController.NoPreference,
rd.ReplayController.NoPreference)
if trace.debugger is None:
raise rdtest.TestFailureException("Pixel shader at {} could not be debugged.".format(name))
self.controller.FreeTrace(trace)
cycles, variables = self.process_trace(trace)
output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0)
debugged = self.evaluate_source_var(output, variables)
self.controller.FreeTrace(trace)
if not rdtest.value_compare(debugged.value.f32v[0:4], [1.0, 1.0, 0.0, 1.0]):
raise rdtest.TestFailureException("Pixel shader at {} did not debug correctly.".format(name))
rdtest.log.success("Shader debugging at {} was successful".format(name))
quad_seen = sorted(quad_seen)
if quad_seen != [float(a) for a in range(1, len(quad_seen) + 1)]:
raise rdtest.TestFailureException("Quad overdraw values are inconsistent: {}".format(quad_seen))
out.Shutdown()