mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Post-process DXBC to remove vendor extension UAV and format instructions
This commit is contained in:
@@ -994,7 +994,8 @@ public:
|
||||
{
|
||||
if(m_DXBCFile == NULL && !m_Bytecode.empty())
|
||||
{
|
||||
m_DXBCFile = new DXBC::DXBCContainer(m_Bytecode, m_DebugInfoPath, m_ShaderExtSlot, ~0U);
|
||||
m_DXBCFile = new DXBC::DXBCContainer(m_Bytecode, m_DebugInfoPath, GraphicsAPI::D3D11,
|
||||
m_ShaderExtSlot, ~0U);
|
||||
m_Bytecode.clear();
|
||||
}
|
||||
return m_DXBCFile;
|
||||
|
||||
@@ -762,7 +762,8 @@ public:
|
||||
{
|
||||
if(m_DXBCFile == NULL && !m_Bytecode.empty())
|
||||
{
|
||||
m_DXBCFile = new DXBC::DXBCContainer(m_Bytecode, rdcstr(), m_ShaderExtSlot, m_ShaderExtSpace);
|
||||
m_DXBCFile = new DXBC::DXBCContainer(m_Bytecode, rdcstr(), GraphicsAPI::D3D12,
|
||||
m_ShaderExtSlot, m_ShaderExtSpace);
|
||||
}
|
||||
return m_DXBCFile;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ bool SupportedOpcode(NvShaderOpcode opcode)
|
||||
{
|
||||
if(NV_nvapi_AllowUnknownShaderOpcodes())
|
||||
return true;
|
||||
return opcode == NvShaderOpcode::UINT64Atomic;
|
||||
return opcode == NvShaderOpcode::U64Atomic;
|
||||
}
|
||||
|
||||
// try to initialise nvapi for replay
|
||||
|
||||
@@ -29,11 +29,39 @@
|
||||
|
||||
enum class NvShaderOpcode : uint32_t
|
||||
{
|
||||
UINT64Atomic = 20,
|
||||
Unknown = 0,
|
||||
Shuffle = 1,
|
||||
ShuffleUp = 2,
|
||||
ShuffleDown = 3,
|
||||
ShuffleXor = 4,
|
||||
VoteAll = 5,
|
||||
VoteAny = 6,
|
||||
VoteBallot = 7,
|
||||
GetLaneId = 8,
|
||||
FP16Atomic = 12,
|
||||
FP32Atomic = 13,
|
||||
GetSpecial = 19,
|
||||
U64Atomic = 20,
|
||||
MatchAny = 21,
|
||||
Footprint = 28,
|
||||
FootprintBias = 29,
|
||||
GetShadingRate = 30,
|
||||
FootprintLevel = 31,
|
||||
FootprintGrad = 32,
|
||||
ShuffleGeneric = 33,
|
||||
VPRSEvalAttribAtSample = 51,
|
||||
VPRSEvalAttribSnapped = 52,
|
||||
};
|
||||
|
||||
enum class NvShaderAtomic : uint32_t
|
||||
enum class NvShaderSpecial
|
||||
{
|
||||
ThreadLtMask = 4,
|
||||
FootprintSingleLOD = 5,
|
||||
};
|
||||
|
||||
enum class NvShaderAtomic
|
||||
{
|
||||
Unknown = -1,
|
||||
And = 0,
|
||||
Or = 1,
|
||||
Xor = 2,
|
||||
|
||||
@@ -400,6 +400,33 @@ DXBC::Reflection *Program::GuessReflection()
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdcstr Program::GetDebugStatus()
|
||||
{
|
||||
// if there are no vendor extensions this is always debuggable
|
||||
if(m_ShaderExt.second == ~0U)
|
||||
return rdcstr();
|
||||
|
||||
// otherwise we need to check that no unsupported vendor extensions are used
|
||||
DisassembleHexDump();
|
||||
|
||||
for(const Operation &op : m_Instructions)
|
||||
{
|
||||
if(op.operation >= OPCODE_VENDOR_FIRST)
|
||||
{
|
||||
bool supported = false;
|
||||
|
||||
// whitelist supported instructions here
|
||||
|
||||
if(!supported)
|
||||
return StringFormat::Fmt("Unsupported shader extension '%s' used",
|
||||
ToStr(op.operation).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// no unsupported instructions used
|
||||
return rdcstr();
|
||||
}
|
||||
|
||||
D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
|
||||
{
|
||||
DisassembleHexDump();
|
||||
|
||||
@@ -316,7 +316,59 @@ enum OpcodeType
|
||||
|
||||
OPCODE_CHECK_ACCESS_FULLY_MAPPED,
|
||||
|
||||
NUM_OPCODES,
|
||||
NUM_REAL_OPCODES,
|
||||
|
||||
OPCODE_VENDOR_REMOVED,
|
||||
|
||||
OPCODE_VENDOR_FIRST,
|
||||
|
||||
OPCODE_AMD_READFIRSTLANE,
|
||||
OPCODE_AMD_READLANE,
|
||||
OPCODE_AMD_LANEID,
|
||||
OPCODE_AMD_SWIZZLE,
|
||||
OPCODE_AMD_BALLOT,
|
||||
OPCODE_AMD_MBCNT,
|
||||
OPCODE_AMD_MIN3U,
|
||||
OPCODE_AMD_MIN3F,
|
||||
OPCODE_AMD_MED3U,
|
||||
OPCODE_AMD_MED3F,
|
||||
OPCODE_AMD_MAX3U,
|
||||
OPCODE_AMD_MAX3F,
|
||||
OPCODE_AMD_BARYCOORD,
|
||||
OPCODE_AMD_VTXPARAM,
|
||||
OPCODE_AMD_GET_VIEWPORTINDEX,
|
||||
OPCODE_AMD_GET_RTARRAYSLICE,
|
||||
OPCODE_AMD_WAVE_REDUCE,
|
||||
OPCODE_AMD_WAVE_SCAN,
|
||||
OPCODE_AMD_LOADDWATADDR,
|
||||
OPCODE_AMD_GET_DRAWINDEX,
|
||||
OPCODE_AMD_U64_ATOMIC,
|
||||
OPCODE_AMD_GET_WAVESIZE,
|
||||
OPCODE_AMD_GET_BASEINSTANCE,
|
||||
OPCODE_AMD_GET_BASEVERTEX,
|
||||
|
||||
OPCODE_NV_SHUFFLE,
|
||||
OPCODE_NV_SHUFFLE_UP,
|
||||
OPCODE_NV_SHUFFLE_DOWN,
|
||||
OPCODE_NV_SHUFFLE_XOR,
|
||||
OPCODE_NV_VOTE_ALL,
|
||||
OPCODE_NV_VOTE_ANY,
|
||||
OPCODE_NV_VOTE_BALLOT,
|
||||
OPCODE_NV_GET_LANEID,
|
||||
OPCODE_NV_FP16_ATOMIC,
|
||||
OPCODE_NV_FP32_ATOMIC,
|
||||
OPCODE_NV_GET_THREADLTMASK,
|
||||
OPCODE_NV_GET_FOOTPRINT_SINGLELOD,
|
||||
OPCODE_NV_U64_ATOMIC,
|
||||
OPCODE_NV_MATCH_ANY,
|
||||
OPCODE_NV_FOOTPRINT,
|
||||
OPCODE_NV_FOOTPRINT_BIAS,
|
||||
OPCODE_NV_GET_SHADING_RATE,
|
||||
OPCODE_NV_FOOTPRINT_LEVEL,
|
||||
OPCODE_NV_FOOTPRINT_GRAD,
|
||||
OPCODE_NV_SHUFFLE_GENERIC,
|
||||
OPCODE_NV_VPRS_EVAL_ATTRIB_SAMPLE,
|
||||
OPCODE_NV_VPRS_EVAL_ATTRIB_SNAPPED,
|
||||
};
|
||||
|
||||
size_t NumOperands(OpcodeType op);
|
||||
@@ -622,6 +674,39 @@ enum ResourceDimension
|
||||
NUM_DIMENSIONS,
|
||||
};
|
||||
|
||||
enum VendorAtomicOp
|
||||
{
|
||||
ATOMIC_OP_NONE = 0,
|
||||
ATOMIC_OP_AND,
|
||||
ATOMIC_OP_OR,
|
||||
ATOMIC_OP_XOR,
|
||||
ATOMIC_OP_ADD,
|
||||
ATOMIC_OP_MAX,
|
||||
ATOMIC_OP_MIN,
|
||||
ATOMIC_OP_SWAP,
|
||||
ATOMIC_OP_CAS,
|
||||
};
|
||||
|
||||
enum VendorWaveOp
|
||||
{
|
||||
WAVE_OP_NONE = 0,
|
||||
WAVE_OP_ADD_FLOAT,
|
||||
WAVE_OP_ADD_SINT,
|
||||
WAVE_OP_ADD_UINT,
|
||||
WAVE_OP_MUL_FLOAT,
|
||||
WAVE_OP_MUL_SINT,
|
||||
WAVE_OP_MUL_UINT,
|
||||
WAVE_OP_MIN_FLOAT,
|
||||
WAVE_OP_MIN_SINT,
|
||||
WAVE_OP_MIN_UINT,
|
||||
WAVE_OP_MAX_FLOAT,
|
||||
WAVE_OP_MAX_SINT,
|
||||
WAVE_OP_MAX_UINT,
|
||||
WAVE_OP_AND,
|
||||
WAVE_OP_OR,
|
||||
WAVE_OP_XOR,
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Main structures
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@@ -671,9 +756,13 @@ struct Operand
|
||||
|
||||
///////////////////////////////////////
|
||||
|
||||
OperandType
|
||||
type; // temp register, constant buffer, input, output, other more specialised types
|
||||
NumOperandComponents numComponents; // scalar, 4-vector or N-vector (currently unused)
|
||||
// operands can be given names to make the assembly easier to read.
|
||||
// mostly used on vendor extensions where the syntax is non-standard/undocumented
|
||||
rdcstr name;
|
||||
// temp register, constant buffer, input, output, other more specialised types
|
||||
OperandType type;
|
||||
// scalar, 4-vector or N-vector (currently unused)
|
||||
NumOperandComponents numComponents;
|
||||
|
||||
uint8_t comps[4]; // the components. each is 0,1,2,3 for x,y,z,w or 0xff if unused.
|
||||
// e.g. .x = { 0, -1, -1, -1 }
|
||||
@@ -683,12 +772,50 @@ struct Operand
|
||||
// .xyzw = { 0, 1, 2, 3 }
|
||||
// .wzyx = { 3, 2, 1, 0 }
|
||||
|
||||
rdcarray<RegIndex> indices; // indices for this register.
|
||||
// 0 means this is a special register, specified by type alone.
|
||||
Operand swizzle(uint8_t c)
|
||||
{
|
||||
Operand ret = *this;
|
||||
ret.numComponents = NUMCOMPS_1;
|
||||
ret.comps[0] = comps[c];
|
||||
ret.comps[1] = 0xff;
|
||||
ret.comps[2] = 0xff;
|
||||
ret.comps[3] = 0xff;
|
||||
ret.values[0] = values[c];
|
||||
ret.values[1] = 0;
|
||||
ret.values[2] = 0;
|
||||
ret.values[3] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Operand swizzle(uint8_t x, uint8_t y, uint8_t z, uint8_t w)
|
||||
{
|
||||
Operand ret = *this;
|
||||
ret.comps[0] = comps[x];
|
||||
ret.comps[1] = comps[y];
|
||||
ret.comps[2] = z < 4 ? comps[z] : 0xff;
|
||||
ret.comps[3] = w < 4 ? comps[w] : 0xff;
|
||||
ret.values[0] = values[x];
|
||||
ret.values[1] = values[y];
|
||||
ret.values[2] = z < 4 ? values[z] : 0;
|
||||
ret.values[3] = w < 4 ? values[w] : 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void setComps(uint8_t x, uint8_t y, uint8_t z, uint8_t w)
|
||||
{
|
||||
comps[0] = x;
|
||||
comps[1] = y;
|
||||
comps[2] = z;
|
||||
comps[3] = w;
|
||||
}
|
||||
|
||||
// indices for this register.
|
||||
// 0 means this is a special register, specified by type alone.
|
||||
// 1 is probably most common. Indicates RegIndex specifies the register
|
||||
// 2 is for constant buffers, array inputs etc. [0] indicates the cbuffer, [1] indicates the
|
||||
// cbuffer member
|
||||
// 3 is rare but follows the above pattern
|
||||
rdcarray<RegIndex> indices;
|
||||
|
||||
// the declaration of the resource in this operand (not always present)
|
||||
Declaration *declaration;
|
||||
@@ -748,7 +875,7 @@ struct Declaration
|
||||
offset = 0;
|
||||
length = 0;
|
||||
instruction = 0;
|
||||
declaration = NUM_OPCODES;
|
||||
declaration = NUM_REAL_OPCODES;
|
||||
refactoringAllowed = doublePrecisionFloats = forceEarlyDepthStencil =
|
||||
enableRawAndStructuredBuffers = skipOptimisation = enableMinPrecision =
|
||||
enableD3D11_1DoubleExtensions = enableD3D11_1ShaderExtensions =
|
||||
@@ -907,7 +1034,7 @@ struct Operation
|
||||
line = 0;
|
||||
length = 0;
|
||||
stride = 0;
|
||||
operation = NUM_OPCODES;
|
||||
operation = NUM_REAL_OPCODES;
|
||||
nonzero = false;
|
||||
saturate = false;
|
||||
preciseValues = 0;
|
||||
@@ -946,9 +1073,16 @@ class Program
|
||||
public:
|
||||
Program(const byte *bytes, size_t length);
|
||||
|
||||
void SetShaderEXTUAV(GraphicsAPI api, uint32_t space, uint32_t reg)
|
||||
{
|
||||
m_API = api;
|
||||
m_ShaderExt = {space, reg};
|
||||
}
|
||||
void FetchComputeProperties(DXBC::Reflection *reflection);
|
||||
DXBC::Reflection *GuessReflection();
|
||||
|
||||
rdcstr GetDebugStatus();
|
||||
|
||||
void SetReflection(const DXBC::Reflection *refl) { m_Reflection = refl; }
|
||||
void SetDebugInfo(const DXBC::IDebugInfo *debug) { m_DebugInfo = debug; }
|
||||
DXBC::ShaderType GetShaderType() const { return m_Type; }
|
||||
@@ -978,6 +1112,9 @@ public:
|
||||
private:
|
||||
void FetchTypeVersion();
|
||||
void DisassembleHexDump();
|
||||
|
||||
void PostprocessVendorExtensions();
|
||||
|
||||
void MakeDisassemblyString();
|
||||
|
||||
const DXBC::Reflection *m_Reflection = NULL;
|
||||
@@ -1003,6 +1140,9 @@ private:
|
||||
|
||||
bool m_Disassembled = false;
|
||||
|
||||
GraphicsAPI m_API = GraphicsAPI::D3D11;
|
||||
rdcpair<uint32_t, uint32_t> m_ShaderExt = {~0U, ~0U};
|
||||
|
||||
rdcstr m_Disassembly;
|
||||
|
||||
// declarations of inputs, outputs, constant buffers, temp registers etc.
|
||||
|
||||
@@ -556,6 +556,9 @@ const rdcstr &DXBCContainer::GetDisassembly()
|
||||
if(!m_DebugFileName.empty())
|
||||
m_Disassembly += StringFormat::Fmt("// Debug name: %s\n", m_DebugFileName.c_str());
|
||||
|
||||
if(m_ShaderExt.second != ~0U)
|
||||
m_Disassembly += "// Vendor shader extensions in use\n";
|
||||
|
||||
m_Disassembly += m_DXBCByteCode->GetDisassembly();
|
||||
}
|
||||
else if(m_DXILByteCode)
|
||||
@@ -568,6 +571,9 @@ const rdcstr &DXBCContainer::GetDisassembly()
|
||||
if(!m_DebugFileName.empty())
|
||||
m_Disassembly += StringFormat::Fmt("; shader debug name: %s\n", m_DebugFileName.c_str());
|
||||
|
||||
if(m_ShaderExt.second != ~0U)
|
||||
m_Disassembly += "; Vendor shader extensions in use\n";
|
||||
|
||||
m_Disassembly += "; shader hash: ";
|
||||
byte *hashBytes = (byte *)m_Hash;
|
||||
for(size_t i = 0; i < sizeof(m_Hash); i++)
|
||||
@@ -600,6 +606,8 @@ void DXBCContainer::FillTraceLineInfo(ShaderDebugTrace &trace) const
|
||||
uint32_t extraLines = 2;
|
||||
if(!m_DebugFileName.empty())
|
||||
extraLines++;
|
||||
if(m_ShaderExt.second != ~0U)
|
||||
extraLines++;
|
||||
|
||||
if(m_GlobalFlags != GlobalShaderFlags::None)
|
||||
extraLines += (uint32_t)Bits::CountOnes((uint32_t)m_GlobalFlags) + 2;
|
||||
@@ -951,8 +959,8 @@ void DXBCContainer::TryFetchSeparateDebugInfo(bytebuf &byteCode, const rdcstr &d
|
||||
}
|
||||
}
|
||||
|
||||
DXBCContainer::DXBCContainer(bytebuf &ByteCode, const rdcstr &debugInfoPath, uint32_t shaderExtReg,
|
||||
uint32_t shaderExtSpace)
|
||||
DXBCContainer::DXBCContainer(bytebuf &ByteCode, const rdcstr &debugInfoPath, GraphicsAPI api,
|
||||
uint32_t shaderExtReg, uint32_t shaderExtSpace)
|
||||
{
|
||||
RDCEraseEl(m_ShaderStats);
|
||||
|
||||
@@ -1838,6 +1846,26 @@ DXBCContainer::DXBCContainer(bytebuf &ByteCode, const rdcstr &debugInfoPath, uin
|
||||
if(m_DXBCByteCode || m_DXILByteCode)
|
||||
{
|
||||
RDCASSERT(m_Reflection);
|
||||
|
||||
if(shaderExtReg != ~0U)
|
||||
{
|
||||
bool found = false;
|
||||
const bool sm51 = (m_Version.Major == 5 && m_Version.Minor == 1);
|
||||
|
||||
// see if we can find the magic UAV. If so remove it from the reflection
|
||||
for(size_t i = 0; i < m_Reflection->UAVs.size(); i++)
|
||||
{
|
||||
const ShaderInputBind &uav = m_Reflection->UAVs[i];
|
||||
if(uav.reg == shaderExtReg && (!sm51 || shaderExtSpace == ~0U || shaderExtSpace == uav.space))
|
||||
{
|
||||
found = true;
|
||||
m_Reflection->UAVs.erase(i);
|
||||
m_DXBCByteCode->SetShaderEXTUAV(api, shaderExtSpace, shaderExtReg);
|
||||
m_ShaderExt = {shaderExtSpace, shaderExtReg};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2014,7 +2042,7 @@ TEST_CASE("DO NOT COMMIT - convenience test", "[dxbc]")
|
||||
bytebuf buf;
|
||||
FileIO::ReadAll("/path/to/container_file.dxbc", buf);
|
||||
|
||||
DXBC::DXBCContainer container(buf, rdcstr());
|
||||
DXBC::DXBCContainer container(buf, rdcstr(), GraphicsAPI::D3D11, ~0U, ~0U);
|
||||
|
||||
// the only thing fetched lazily is the disassembly, so grab that here
|
||||
|
||||
|
||||
@@ -142,8 +142,8 @@ ShaderCompileFlags EncodeFlags(const uint32_t flags, const rdcstr &profile);
|
||||
class DXBCContainer
|
||||
{
|
||||
public:
|
||||
DXBCContainer(bytebuf &ByteCode, const rdcstr &debugInfoPath, uint32_t shaderExtReg,
|
||||
uint32_t shaderExtSpace);
|
||||
DXBCContainer(bytebuf &ByteCode, const rdcstr &debugInfoPath, GraphicsAPI api,
|
||||
uint32_t shaderExtReg, uint32_t shaderExtSpace);
|
||||
~DXBCContainer();
|
||||
DXBC::ShaderType m_Type = DXBC::ShaderType::Max;
|
||||
struct
|
||||
@@ -190,6 +190,8 @@ private:
|
||||
|
||||
uint32_t m_Hash[4];
|
||||
|
||||
rdcpair<uint32_t, uint32_t> m_ShaderExt = {~0U, ~0U};
|
||||
|
||||
rdcstr m_DebugFileName;
|
||||
GlobalShaderFlags m_GlobalFlags = GlobalShaderFlags::None;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@
|
||||
#include "dxbc_reflect.h"
|
||||
#include "common/formatting.h"
|
||||
#include "core/core.h"
|
||||
#include "dxbc_bytecode.h"
|
||||
#include "dxbc_container.h"
|
||||
|
||||
static ShaderConstant MakeConstantBufferVariable(const DXBC::CBufferVariable &var);
|
||||
@@ -276,7 +277,9 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl,
|
||||
|
||||
if(dxbc->GetDXBCByteCode())
|
||||
{
|
||||
refl->debugInfo.debuggable = true;
|
||||
refl->debugInfo.debugStatus = dxbc->GetDXBCByteCode()->GetDebugStatus();
|
||||
|
||||
refl->debugInfo.debuggable = refl->debugInfo.debugStatus.empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user