mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -820,7 +820,7 @@ namespace DXCEnumerateAndCheck {
|
||||
<Exec Command=""$(DXCExecutable)" "$(ProjectDir)data\hlsl\fixedcol.hlsl" -T ps_6_0 -DVARIANT=1 -E main -Qstrip_reflect -Fo "$(DXILBakedDir)fixedcol_1.dxbc"" />
|
||||
<Exec Command=""$(DXCExecutable)" "$(ProjectDir)data\hlsl\fixedcol.hlsl" -T ps_6_0 -DVARIANT=2 -E main -Qstrip_reflect -Fo "$(DXILBakedDir)fixedcol_2.dxbc"" />
|
||||
<Exec Command=""$(DXCExecutable)" "$(ProjectDir)data\hlsl\fixedcol.hlsl" -T ps_6_0 -DVARIANT=3 -E main -Qstrip_reflect -Fo "$(DXILBakedDir)fixedcol_3.dxbc"" />
|
||||
<Exec Command=""$(DXCExecutable)" "$(ProjectDir)data\hlsl\quadoverdraw.hlsl" -T ps_6_0 -E RENDERDOC_QuadOverdrawPS -Qstrip_reflect -Fo "$(DXILBakedDir)quadwrite.dxbc"" />
|
||||
<Exec Command=""$(DXCExecutable)" "$(ProjectDir)data\hlsl\quadoverdraw.hlsl" -T ps_6_0 -DD3D12=1 -E RENDERDOC_QuadOverdrawPS -Qstrip_reflect -Fo "$(DXILBakedDir)quadwrite.dxbc"" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<Natvis Include="renderdoc.natvis" />
|
||||
|
||||
@@ -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();
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user