@@ -32,23 +32,22 @@ RDOC_CONFIG(bool, D3D12_DXILShaderDebugger_Logging, false,
32
32
" Debug logging for the DXIL shader debugger" );
33
33
34
34
// TODO: Remove asserts using ^
35
- // TODO: Support global shared memory pointers created as Constants using getElementPtr inside the constant
35
+ // TODO: Extend support for Compound Constants: arithmetic, logical ops
36
36
// TODO: re-implement callstacks using scopes and inlined at metadata
37
37
// TODO: Assert m_Block in ThreadState is correct per instruction
38
38
// TODO: Automatically execute phi instructions after a branch
39
39
// TODO: Support MSAA
40
40
// TODO: Support UAVs with counter
41
- // TODO: Extend support for Compound Constants: Vector, GetElementPtr
42
- // TODO: Extend debug data parsing for DW_TAG_array_type for the base element type
43
- // TODO: Extend debug data parsing: N-dimensional arrays, mapping covers whole sub-array
41
+ // TODO: Extend debug data parsing: DW_TAG_array_type for the base element type
42
+ // TODO: Extend debug data parsing: N-dimensional arrays, mapping covers whole sub-array
44
43
45
44
// Notes:
46
45
// The phi node capture variables are not shown in the UI
47
46
// LLVM poison values are not supported
48
47
// Does it make sense to use ShaderVariable GPU pointers
49
48
// ExtractVal: only handles one index
50
49
// ComputeDXILTypeByteSize does not consider byte alignment
51
- // GetElementPtr: only handles a two indexes
50
+ // GetElementPtr: only handles two indexes
52
51
// Sample*: Argument 10 which is called Clamp is not used
53
52
// ShuffleVector: mask entries might be undef meaning "don't care"
54
53
@@ -94,6 +93,36 @@ inline bool RDCISNORMAL(double input)
94
93
using namespace DXIL ;
95
94
using namespace DXDebug ;
96
95
96
+ const uint32_t POINTER_MAGIC = 0xBEAFDEAF ;
97
+
98
+ static void EncodePointer (DXILDebug::Id ptrId, uint64_t offset, uint64_t size, ShaderVariable &var)
99
+ {
100
+ var.type = VarType::GPUPointer;
101
+ var.value .u32v [0 ] = ptrId;
102
+ var.value .u32v [1 ] = POINTER_MAGIC;
103
+ var.value .u64v [1 ] = offset;
104
+ var.value .u64v [2 ] = size;
105
+ }
106
+
107
+ static bool DecodePointer (DXILDebug::Id &ptrId, uint64_t &offset, uint64_t &size,
108
+ const ShaderVariable &var)
109
+ {
110
+ if (var.type != VarType::GPUPointer)
111
+ {
112
+ RDCERR (" Calling DecodePointer on non-pointer type %s" , ToStr (var.type ).c_str ());
113
+ return false ;
114
+ }
115
+ if (var.value .u32v [1 ] != POINTER_MAGIC)
116
+ {
117
+ RDCERR (" Calling DecodePointer on non encoded pointer type %u" , var.value .u32v [1 ]);
118
+ return false ;
119
+ }
120
+ ptrId = var.value .u32v [0 ];
121
+ offset = var.value .u64v [1 ];
122
+ size = var.value .u64v [2 ];
123
+ return true ;
124
+ }
125
+
97
126
static bool OperationFlushing (const Operation op, DXOp dxOpCode)
98
127
{
99
128
if (dxOpCode != DXOp::NumOpCodes)
@@ -848,13 +877,98 @@ static bool ConvertDXILConstantToShaderVariable(const Constant *constant, Shader
848
877
const rdcarray<DXIL::Value *> &members = constant->getMembers ();
849
878
value = members[0 ];
850
879
}
851
- if (constant->op == Operation::GetElementPtr )
880
+ if (constant->op == Operation::NoOp )
852
881
{
853
- RDCLOG ( " Unsupported Constant Op %s " , ToStr (constant-> op ). c_str ( ));
882
+ RDCASSERT ( ConvertDXILValueToShaderValue (value, var. type , 0 , var. value ));
854
883
return true ;
855
884
}
856
- RDCASSERT (ConvertDXILValueToShaderValue (value, var.type , 0 , var.value ));
857
- return true ;
885
+ else if (constant->op == Operation::GetElementPtr)
886
+ {
887
+ const rdcarray<DXIL::Value *> &members = constant->getMembers ();
888
+ RDCASSERT (members.size () >= 3 , members.size ());
889
+ value = members[0 ];
890
+ const GlobalVar *gv = cast<GlobalVar>(value);
891
+ if (!gv)
892
+ {
893
+ RDCERR (" Constant GetElementPtr first member is not a GlobalVar" );
894
+ return false ;
895
+ }
896
+ const DXIL::Type *elementType = gv->type ;
897
+ if (elementType->type != Type::TypeKind::Pointer)
898
+ {
899
+ RDCERR (" Constant GetElementPtr global variable is not a Pointer" );
900
+ return false ;
901
+ }
902
+ elementType = elementType->inner ;
903
+ VarType baseType = ConvertDXILTypeToVarType (elementType);
904
+ uint32_t elementSize = GetElementByteSize (baseType);
905
+ uint32_t countElems = RDCMAX (1U , elementType->elemCount );
906
+ uint64_t size = countElems * GetElementByteSize (baseType);
907
+
908
+ DXILDebug::Id ptrId = gv->ssaId ;
909
+ // members[1..] : indices 1...N
910
+ rdcarray<uint64_t > indexes;
911
+ indexes.reserve (members.size () - 1 );
912
+ for (uint32_t a = 1 ; a < members.size (); ++a)
913
+ {
914
+ value = members[a];
915
+ VarType argType = ConvertDXILTypeToVarType (value->type );
916
+ ShaderValue argValue;
917
+ memset (&argValue, 0 , sizeof (argValue));
918
+ RDCASSERT (ConvertDXILValueToShaderValue (value, argType, 0 , argValue));
919
+ indexes.push_back (argValue.u64v [0 ]);
920
+ }
921
+ // Index 0 is in ptr terms as if pointer was an array of pointers
922
+ RDCASSERTEQUAL (indexes[0 ], 0 );
923
+ uint64_t offset = 0 ;
924
+
925
+ if (indexes.size () > 1 )
926
+ offset += indexes[1 ] * elementSize;
927
+ RDCASSERT (indexes.size () <= 2 );
928
+ // Encode the pointer allocation: ptrId, offset, size
929
+ EncodePointer (ptrId, offset, size, var);
930
+ return true ;
931
+ }
932
+ // case Operation::Trunc:
933
+ // case Operation::ZExt:
934
+ // case Operation::SExt:
935
+ // case Operation::FToU:
936
+ // case Operation::FToS:
937
+ // case Operation::UToF:
938
+ // case Operation::SToF:
939
+ // case Operation::FPTrunc:
940
+ // case Operation::FPExt:
941
+ // case Operation::PtrToI:
942
+ // case Operation::IToPtr:
943
+ // case Operation::Bitcast:
944
+ // case Operation::AddrSpaceCast:
945
+ // case Operation::Select:
946
+ // case Operation::IEqual:
947
+ // plus other integer comparisons
948
+ // case Operation::FOrdEqual:
949
+ // plus other fp comparisons
950
+ // case Operation::ExtractElement:
951
+ // case Operation::ExtractVal:
952
+ // case Operation::FAdd:
953
+ // case Operation::FSub:
954
+ // case Operation::FMul:
955
+ // case Operation::FDiv:
956
+ // case Operation::FRem:
957
+ // case Operation::Add:
958
+ // case Operation::Sub:
959
+ // case Operation::Mul:
960
+ // case Operation::UDiv:
961
+ // case Operation::SDiv:
962
+ // case Operation::URem:
963
+ // case Operation::SRem:
964
+ // case Operation::ShiftLeft:
965
+ // case Operation::LogicalShiftRight:
966
+ // case Operation::ArithShiftRight:
967
+ // case Operation::And:
968
+ // case Operation::Or:
969
+ // case Operation::Xor:
970
+ RDCLOG (" Unsupported Constant Op %s" , ToStr (constant->op ).c_str ());
971
+ return false ;
858
972
}
859
973
return false ;
860
974
}
@@ -4152,7 +4266,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
4152
4266
// Store(ptr, value)
4153
4267
Id baseMemoryId = DXILDebug::INVALID_ID;
4154
4268
void *baseMemoryBackingPtr = NULL ;
4155
- size_t allocSize = 0 ;
4269
+ uint64_t allocSize = 0 ;
4156
4270
void *allocMemoryBackingPtr = NULL ;
4157
4271
Id ptrId = GetArgumentId (0 );
4158
4272
if (ptrId == DXILDebug::INVALID_ID)
@@ -4267,8 +4381,8 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
4267
4381
backingMemory += offset;
4268
4382
m_Memory.m_AllocPointers [resultId] = {ptrId, backingMemory, size};
4269
4383
4270
- RDCASSERT (size < sizeof (result. value . f32v ));
4271
- if (size < sizeof (ShaderValue))
4384
+ RDCASSERT (size <= sizeof (ShaderValue ));
4385
+ if (size <= sizeof (ShaderValue))
4272
4386
memcpy (&result.value , backingMemory, size);
4273
4387
else
4274
4388
RDCERR (" Size %u too large MAX %u for GetElementPtr" , size, sizeof (ShaderValue));
@@ -5133,7 +5247,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
5133
5247
case Operation::AtomicUMin:
5134
5248
case Operation::CompareExchange:
5135
5249
{
5136
- size_t allocSize = 0 ;
5250
+ uint64_t allocSize = 0 ;
5137
5251
void *allocMemoryBackingPtr = NULL ;
5138
5252
void *baseMemoryBackingPtr = NULL ;
5139
5253
Id baseMemoryId = DXILDebug::INVALID_ID;
@@ -5617,7 +5731,7 @@ void ThreadState::MarkResourceAccess(const rdcstr &name, const ResourceReference
5617
5731
accessed.push_back (resRefInfo.binding );
5618
5732
}
5619
5733
5620
- void ThreadState::UpdateBackingMemoryFromVariable (void *ptr, size_t &allocSize,
5734
+ void ThreadState::UpdateBackingMemoryFromVariable (void *ptr, uint64_t &allocSize,
5621
5735
const ShaderVariable &var)
5622
5736
{
5623
5737
// Memory copy from value to backing memory
@@ -5626,7 +5740,7 @@ void ThreadState::UpdateBackingMemoryFromVariable(void *ptr, size_t &allocSize,
5626
5740
RDCASSERTEQUAL (var.rows , 1 );
5627
5741
const size_t elementSize = GetElementByteSize (var.type );
5628
5742
RDCASSERT (elementSize <= allocSize);
5629
- RDCASSERT (elementSize < sizeof (var. value . f32v ));
5743
+ RDCASSERT (elementSize <= sizeof (ShaderValue ));
5630
5744
const size_t varMemSize = var.columns * elementSize;
5631
5745
memcpy (ptr, &var.value .f32v [0 ], varMemSize);
5632
5746
allocSize -= varMemSize;
@@ -5654,7 +5768,7 @@ void ThreadState::UpdateMemoryVariableFromBackingMemory(Id memoryId, const void
5654
5768
{
5655
5769
RDCASSERTEQUAL (baseMemory.rows , 1 );
5656
5770
RDCASSERTEQUAL (baseMemory.columns , 1 );
5657
- if (elementSize < sizeof (ShaderValue))
5771
+ if (elementSize <= sizeof (ShaderValue))
5658
5772
memcpy (&baseMemory.value , src, elementSize);
5659
5773
else
5660
5774
RDCERR (" Updating MemoryVariable elementSize %u too large max %u" , elementSize,
@@ -5664,7 +5778,7 @@ void ThreadState::UpdateMemoryVariableFromBackingMemory(Id memoryId, const void
5664
5778
{
5665
5779
for (uint32_t i = 0 ; i < baseMemory.members .size (); ++i)
5666
5780
{
5667
- if (elementSize < sizeof (ShaderValue))
5781
+ if (elementSize <= sizeof (ShaderValue))
5668
5782
memcpy (&baseMemory.members [i].value , src, elementSize);
5669
5783
else
5670
5784
RDCERR (" Updating MemoryVariable member %u elementSize %u too large max %u" , i, elementSize,
@@ -6131,6 +6245,7 @@ ShaderValue ThreadState::DDY(bool fine, Operation opCode, DXOp dxOpCode,
6131
6245
}
6132
6246
6133
6247
ShaderValue ret;
6248
+ memset (&ret, 0 , sizeof (ret));
6134
6249
ShaderVariable a;
6135
6250
ShaderVariable b;
6136
6251
RDCASSERT (quad[index + 2 ].GetShaderVariable (dxilValue, opCode, dxOpCode, a));
@@ -7633,10 +7748,6 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
7633
7748
MemoryTracking &globalMemory = m_GlobalState.memory ;
7634
7749
for (const DXIL::GlobalVar *gv : m_Program->m_GlobalVars )
7635
7750
{
7636
- // Ignore DXIL global variables which start with "dx.nothing."
7637
- if (gv->name .beginsWith (" dx.nothing." ))
7638
- continue ;
7639
-
7640
7751
GlobalVariable globalVar;
7641
7752
rdcstr n = DXBC::BasicDemangle (gv->name );
7642
7753
DXIL::SanitiseName (n);
@@ -7656,7 +7767,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
7656
7767
RDCASSERT (itAlloc != globalMemory.m_Allocs .end ());
7657
7768
const MemoryTracking::Alloc &alloc = itAlloc->second ;
7658
7769
void *allocMemoryBackingPtr = alloc.backingMemory ;
7659
- size_t allocSize = alloc.size ;
7770
+ uint64_t allocSize = alloc.size ;
7660
7771
state.UpdateBackingMemoryFromVariable (allocMemoryBackingPtr, allocSize, globalVar.var );
7661
7772
RDCASSERTEQUAL (allocSize, 0 );
7662
7773
}
@@ -7672,6 +7783,8 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
7672
7783
{
7673
7784
for (Instruction *inst : f->instructions )
7674
7785
{
7786
+ if (IsNopInstruction (*inst))
7787
+ continue ;
7675
7788
for (const Value *arg : inst->args )
7676
7789
{
7677
7790
if (arg && arg->kind () == ValueKind::Constant)
@@ -7684,14 +7797,44 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
7684
7797
}
7685
7798
7686
7799
GlobalConstant constantVar;
7687
- ConvertDXILTypeToShaderVariable (c-> type , constantVar.var ) ;
7688
- ConvertDXILConstantToShaderVariable (c, constantVar. var );
7689
- constantVar. var . name = m_Program-> GetArgumentName (c );
7690
- constantVar. id = c-> ssaId ;
7800
+ ShaderVariable &var = constantVar.var ;
7801
+ ConvertDXILTypeToShaderVariable (c-> type , var);
7802
+ ConvertDXILConstantToShaderVariable (c, var );
7803
+ var. name = m_Program-> GetArgumentName (c) ;
7691
7804
Id id = c->ssaId ;
7692
7805
RDCASSERTNOTEQUAL (id, DXILDebug::INVALID_ID);
7806
+ constantVar.id = id;
7807
+ if (var.type == VarType::GPUPointer)
7808
+ {
7809
+ Id ptrId;
7810
+ uint64_t offset;
7811
+ uint64_t size;
7812
+ // Decode the pointer allocation: ptrId, offset, size
7813
+ RDCASSERT (DecodePointer (ptrId, offset, size, var));
7814
+
7815
+ auto it = globalMemory.m_Allocs .find (ptrId);
7816
+ if (it != globalMemory.m_Allocs .end ())
7817
+ {
7818
+ const MemoryTracking::Alloc &alloc = it->second ;
7819
+ uint8_t *backingMemory = (uint8_t *)alloc.backingMemory ;
7820
+ RDCASSERT (offset + size <= alloc.size );
7821
+ if (offset + size <= alloc.size )
7822
+ {
7823
+ backingMemory += offset;
7824
+ globalMemory.m_AllocPointers [id] = {ptrId, backingMemory, size};
7825
+ }
7826
+ else
7827
+ {
7828
+ RDCERR (" Invalid GEP offset %u size %u for alloc size %u" , offset, size, alloc.size );
7829
+ }
7830
+ }
7831
+ else
7832
+ {
7833
+ RDCERR (" Failed to find allocation for Constant global variable pointer %u" , ptrId);
7834
+ }
7835
+ }
7693
7836
m_GlobalState.constants .push_back (constantVar);
7694
- m_LiveGlobals[constantVar. id ] = true ;
7837
+ m_LiveGlobals[id] = true ;
7695
7838
}
7696
7839
}
7697
7840
}
0 commit comments