From f538e91b05f7e9ef41d406486aeef083e40df7e8 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Thu, 24 Oct 2024 12:47:50 +0100 Subject: [PATCH] DXIL Debugger extended support for GPU Sampling instructions DXOp::Sample DXOp::SampleBias DXOp::SampleLevel DXOp::SampleGrad DXOp::SampleCmp DXOp::SampleCmpBias DXOp::SampleCmpLevel DXOp::SampleCmpGrad DXOp::SampleCmpLevelZero DXOp::TextureGather DXOp::TextureGatherCmp --- renderdoc/data/hlsl/hlsl_cbuffers.h | 18 +- renderdoc/data/hlsl/shaderdebug.hlsl | 98 +++++++- renderdoc/driver/d3d12/d3d12_debug.cpp | 6 +- renderdoc/driver/d3d12/d3d12_dxil_debug.cpp | 12 +- renderdoc/driver/shaders/dxil/dxil_debug.cpp | 231 ++++++++++++------ .../driver/shaders/dxil/dxil_reflect.cpp | 8 - 6 files changed, 276 insertions(+), 97 deletions(-) diff --git a/renderdoc/data/hlsl/hlsl_cbuffers.h b/renderdoc/data/hlsl/hlsl_cbuffers.h index 7ee878676..6491f4bdd 100644 --- a/renderdoc/data/hlsl/hlsl_cbuffers.h +++ b/renderdoc/data/hlsl/hlsl_cbuffers.h @@ -397,13 +397,17 @@ cbuffer DebugSampleOperation REG(b0) #define DEBUG_SAMPLE_TEX_SAMPLE_GRAD 103 #define DEBUG_SAMPLE_TEX_SAMPLE_CMP 104 #define DEBUG_SAMPLE_TEX_SAMPLE_CMP_LEVEL_ZERO 105 -#define DEBUG_SAMPLE_TEX_GATHER4 106 -#define DEBUG_SAMPLE_TEX_GATHER4_CMP 107 -#define DEBUG_SAMPLE_TEX_GATHER4_PO 108 -#define DEBUG_SAMPLE_TEX_GATHER4_PO_CMP 109 -#define DEBUG_SAMPLE_TEX_LOD 110 -#define DEBUG_SAMPLE_TEX_LOAD 111 -#define DEBUG_SAMPLE_TEX_LOAD_MS 112 +#define DEBUG_SAMPLE_TEX_SAMPLE_CMP_LEVEL 106 // SM 6.7 +#define DEBUG_SAMPLE_TEX_SAMPLE_CMP_BIAS 107 // SM 6.8 +#define DEBUG_SAMPLE_TEX_SAMPLE_CMP_GRAD 108 // SM 6.8 + +#define DEBUG_SAMPLE_TEX_GATHER4 109 +#define DEBUG_SAMPLE_TEX_GATHER4_CMP 110 +#define DEBUG_SAMPLE_TEX_GATHER4_PO 111 +#define DEBUG_SAMPLE_TEX_GATHER4_PO_CMP 112 +#define DEBUG_SAMPLE_TEX_LOD 113 +#define DEBUG_SAMPLE_TEX_LOAD 114 +#define DEBUG_SAMPLE_TEX_LOAD_MS 115 #define DEBUG_SAMPLE_TEX1D 1 #define DEBUG_SAMPLE_TEX2D 2 diff --git a/renderdoc/data/hlsl/shaderdebug.hlsl b/renderdoc/data/hlsl/shaderdebug.hlsl index 782184fc3..a3e612b46 100644 --- a/renderdoc/data/hlsl/shaderdebug.hlsl +++ b/renderdoc/data/hlsl/shaderdebug.hlsl @@ -269,7 +269,7 @@ float4 DoFloatOpcode(float4 uv) } } } - else if(opcode == DEBUG_SAMPLE_TEX_SAMPLE_CMP) + else if(opcode == DEBUG_SAMPLE_TEX_SAMPLE_CMP || opcode == DEBUG_SAMPLE_TEX_SAMPLE_CMP_BIAS) { switch(debugSampleTexDim) { @@ -660,6 +660,102 @@ float4 DoFloatOpcode(float4 uv) } } } +#if __SHADER_TARGET_MAJOR >= 6 +#if __SHADER_TARGET_MINOR >= 7 + else if(opcode == DEBUG_SAMPLE_TEX_SAMPLE_CMP_LEVEL) // SM6.7 + { + switch(debugSampleTexDim) + { + default: + case DEBUG_SAMPLE_TEX1D: + { + switch(debugSampleRetType) + { + case DEBUG_SAMPLE_UNORM: + return t1D_unorm.SampleCmpLevel(sc, uv.xy, compare, lod, offsets.x); + case DEBUG_SAMPLE_SNORM: + return t1D_snorm.SampleCmpLevel(sc, uv.xy, compare, lod, offsets.x); + default: return t1D_float.SampleCmpLevel(sc, uv.xy, compare, lod, offsets.x); + } + } + case DEBUG_SAMPLE_TEX2D: + { + switch(debugSampleRetType) + { + case DEBUG_SAMPLE_UNORM: + return t2D_unorm.SampleCmpLevel(sc, uv.xyz, compare, lod, offsets.xy); + case DEBUG_SAMPLE_SNORM: + return t2D_snorm.SampleCmpLevel(sc, uv.xyz, compare, lod, offsets.xy); + default: return t2D_float.SampleCmpLevel(sc, uv.xyz, compare, lod, offsets.xy); + } + } + case DEBUG_SAMPLE_TEXCUBE: + { + switch(debugSampleRetType) + { + case DEBUG_SAMPLE_UNORM: return tCube_unorm.SampleCmpLevel(sc, uv, compare, lod); + case DEBUG_SAMPLE_SNORM: return tCube_snorm.SampleCmpLevel(sc, uv, compare, lod); + default: return tCube_float.SampleCmpLevel(sc, uv, compare, lod); + } + } + } + } +#endif // #if __SHADER_TARGET_MINOR >= 7 +#if __SHADER_TARGET_MINOR >= 8 + else if(opcode == DEBUG_SAMPLE_TEX_SAMPLE_CMP_GRAD) // SM6.8 + { + switch(debugSampleTexDim) + { + default: + case DEBUG_SAMPLE_TEX1D: + { + switch(debugSampleRetType) + { + case DEBUG_SAMPLE_UNORM: + return t1D_unorm.SampleCmpGrad(s, uv.xy, compare, ddx_.x, ddy_.x, offsets.x); + case DEBUG_SAMPLE_SNORM: + return t1D_snorm.SampleCmpGrad(s, uv.xy, compare, ddx_.x, ddy_.x, offsets.x); + default: return t1D_float.SampleCmpGrad(s, uv.xy, compare, ddx_.x, ddy_.x, offsets.x); + } + } + case DEBUG_SAMPLE_TEX2D: + { + switch(debugSampleRetType) + { + case DEBUG_SAMPLE_UNORM: + return t2D_unorm.SampleCmpGrad(s, uv.xyz, compare, ddx_.xy, ddy_.xy, offsets.xy); + case DEBUG_SAMPLE_SNORM: + return t2D_snorm.SampleCmpGrad(s, uv.xyz, compare, ddx_.xy, ddy_.xy, offsets.xy); + default: return t2D_float.SampleCmpGrad(s, uv.xyz, compare, ddx_.xy, ddy_.xy, offsets.xy); + } + } + case DEBUG_SAMPLE_TEX3D: + { + switch(debugSampleRetType) + { + case DEBUG_SAMPLE_UNORM: + return t3D_unorm.SampleCmpGrad(s, uv.xyz, compare, ddx_.xyz, ddy_.xyz, offsets.xyz); + case DEBUG_SAMPLE_SNORM: + return t3D_snorm.SampleCmpGrad(s, uv.xyz, compare, ddx_.xyz, ddy_.xyz, offsets.xyz); + default: + return t3D_float.SampleCmpGrad(s, uv.xyz, compare, ddx_.xyz, ddy_.xyz, offsets.xyz); + } + } + case DEBUG_SAMPLE_TEXCUBE: + { + switch(debugSampleRetType) + { + case DEBUG_SAMPLE_UNORM: + return tCube_unorm.SampleCmpGrad(s, uv, compare, ddx_.xyz, ddy_.xyz); + case DEBUG_SAMPLE_SNORM: + return tCube_snorm.SampleCmpGrad(s, uv, compare, ddx_.xyz, ddy_.xyz); + default: return tCube_float.SampleCmpGrad(s, uv, compare, ddx_.xyz, ddy_.xyz); + } + } + } + } +#endif // #if __SHADER_TARGET_MINOR >= 8 +#endif // #if __SHADER_TARGET_MAJOR >= 6 else { return float4(0, 0, 0, 0); diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 0755c456a..9a2869a80 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -836,8 +836,12 @@ bool D3D12DebugManager::CreateShaderDebugResources() return false; } ID3DBlob *dxilPsBlob = NULL; + D3D12_FEATURE_DATA_SHADER_MODEL smMaxSupport = {D3D_SHADER_MODEL_6_8}; + m_pDevice->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &smMaxSupport, sizeof(smMaxSupport)); + D3D_SHADER_MODEL smModel = smMaxSupport.HighestShaderModel; + rdcstr psSM = StringFormat::Fmt("ps_%d_%d", (smModel >> 4), (smModel & 0xf)); if(m_pDevice->GetShaderCache()->GetShaderBlob(hlsl.c_str(), "RENDERDOC_DebugSamplePS", - D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "ps_6_0", + D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, psSM.c_str(), &dxilPsBlob) != "") { RDCASSERT(!dxilPsBlob); diff --git a/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp b/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp index 1e1af4ac2..315886011 100644 --- a/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp @@ -1118,23 +1118,23 @@ bool D3D12APIWrapper::CalculateSampleGather( switch(dxOp) { case DXOp::Sample: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE; break; - case DXOp::SampleLevel: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_LEVEL; break; case DXOp::SampleBias: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_BIAS; break; - case DXOp::SampleCmp: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_CMP; break; + case DXOp::SampleLevel: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_LEVEL; break; case DXOp::SampleGrad: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_GRAD; break; + case DXOp::SampleCmp: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_CMP; break; + case DXOp::SampleCmpBias: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_CMP_BIAS; break; + case DXOp::SampleCmpLevel: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_CMP_LEVEL; break; + case DXOp::SampleCmpGrad: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_CMP_GRAD; break; case DXOp::SampleCmpLevelZero: sampleOp = DEBUG_SAMPLE_TEX_SAMPLE_CMP_LEVEL_ZERO; break; case DXOp::TextureGather: sampleOp = DEBUG_SAMPLE_TEX_GATHER4; break; case DXOp::TextureGatherCmp: sampleOp = DEBUG_SAMPLE_TEX_GATHER4_CMP; break; case DXOp::CalculateLOD: sampleOp = DEBUG_SAMPLE_TEX_LOD; break; + // In the shader DEBUG_SAMPLE_TEX_LOAD and DEBUG_SAMPLE_TEX_LOAD_MS behave equivalently case DXOp::TextureLoad: sampleOp = DEBUG_SAMPLE_TEX_LOAD; break; // TODO: consider these DXIL opcode operations - // DXOp::SampleCmpBias - // DXOp::SampleCmpGrad - // DXOp::SampleCmpLevel // DXOp::TextureGatherRaw // TODO: consider these DXBC opcode operations // DEBUG_SAMPLE_TEX_GATHER4_PARAM_OFFSET_CMP - // DEBUG_SAMPLE_TEX_LOAD_MS default: // To support a new instruction, the shader created in // D3D12DebugManager::CreateShaderDebugResources will need updating diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.cpp b/renderdoc/driver/shaders/dxil/dxil_debug.cpp index c1ad0413b..140944168 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debug.cpp @@ -1389,16 +1389,17 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, break; } case DXOp::Sample: + case DXOp::SampleBias: case DXOp::SampleLevel: + case DXOp::SampleGrad: + case DXOp::SampleCmp: + case DXOp::SampleCmpBias: + case DXOp::SampleCmpLevel: + case DXOp::SampleCmpGrad: case DXOp::SampleCmpLevelZero: + case DXOp::TextureGather: + case DXOp::TextureGatherCmp: { - // TODO - // case DXOp::SampleBias: - // case DXOp::SampleGrad: - // case DXOp::SampleCmp: - // case DXOp::SampleCmpLevel: - // case DXOp::SampleCmpGrad: - // case DXOp::SampleCmpBias: rdcstr handleId = GetArgumentName(1); const ResourceReference *resRef = GetResource(handleId); if(!resRef) @@ -2067,13 +2068,8 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, case DXOp::Ubfe: case DXOp::Bfi: case DXOp::CBufferLoad: - case DXOp::SampleBias: - case DXOp::SampleGrad: - case DXOp::SampleCmp: case DXOp::BufferUpdateCounter: case DXOp::CheckAccessFullyMapped: - case DXOp::TextureGather: - case DXOp::TextureGatherCmp: case DXOp::AtomicBinOp: case DXOp::AtomicCompareExchange: case DXOp::Barrier: @@ -2210,7 +2206,6 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, case DXOp::IsHelperLane: case DXOp::QuadVote: case DXOp::TextureGatherRaw: - case DXOp::SampleCmpLevel: case DXOp::TextureStoreSample: case DXOp::WaveMatrix_Annotate: case DXOp::WaveMatrix_Depth: @@ -2240,8 +2235,6 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, case DXOp::AnnotateNodeRecordHandle: case DXOp::NodeOutputIsValid: case DXOp::GetRemainingRecursionLevels: - case DXOp::SampleCmpGrad: - case DXOp::SampleCmpBias: case DXOp::StartVertexLocation: case DXOp::StartInstanceLocation: case DXOp::NumOpCodes: @@ -2439,7 +2432,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, } RDCASSERT((resultType->type == DXIL::Type::TypeKind::Scalar) || (resultType->type == DXIL::Type::TypeKind::Struct)); - // TODO: NEED TO DEMANGLE THE NAME TO DEMANGLE TO MATCH DISASSEMBLY + // TODO: NEED TO DEMANGLE THE NAME TO MATCH DISASSEMBLY result.type = baseType; result.rows = (uint8_t)countElems; result.members.resize(countElems); @@ -3334,7 +3327,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, case Operation::AtomicUMax: case Operation::AtomicUMin: { - // JAKE TODO: full proper load and store from/to memory i.e. group shared + // TODO: full proper load and store from/to memory i.e. group shared // Currently only supporting Stack allocated pointers size_t allocSize = 0; void *allocMemoryBackingPtr = NULL; @@ -3810,16 +3803,18 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, { // TextureLoad(srv,mipLevelOrSampleCount,coord0,coord1,coord2,offset0,offset1,offset2) // Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp) - // SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD) - // SampleCmpLevelZero(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue) - - // TODO // SampleBias(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,bias,clamp) + // SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD) // SampleGrad(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,ddx0,ddx1,ddx2,ddy0,ddy1,ddy2,clamp) // SampleCmp(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue,clamp) + // SampleCmpBias(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue,bias,clamp) // SampleCmpLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue,lod) // SampleCmpGrad(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue,ddx0,ddx1,ddx2,ddy0,ddy1,ddy2,clamp) - // SampleCmpBias(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue,bias,clamp) + // SampleCmpLevelZero(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue) + // CalculateLOD(handle,sampler,coord0,coord1,coord2,clamped) + + // TextureGather(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,channel) + // TextureGatherCmp(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,channel,compareValue) // DXIL reports the vector result as a struct of N members of Element type, plus an int. const Type *retType = inst.type; @@ -3855,8 +3850,39 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, samplerData.mode = SamplerMode::NUM_SAMPLERS; bool uvDDXY[4] = {false, false, false, false}; + GatherChannel gatherChannel = GatherChannel::Red; - if(dxOpCode != DXOp::TextureLoad) + if(dxOpCode == DXOp::TextureLoad) + { + ShaderVariable arg; + // mipLevelOrSampleCount is in arg 2 + if(GetShaderVariable(inst.args[2], opCode, dxOpCode, arg, false)) + { + uint32_t mipLevelOrSampleCount = arg.value.u32v[0]; + // The debug shader uses arrays of resources for 1D, 2D textures + // mipLevel goes into UV[N] : N = 1D: 2, 2D: 3, 3D: 3 + switch(srv.shape) + { + case DXIL::ResourceKind::Texture1D: uv.value.u32v[2] = mipLevelOrSampleCount; break; + case DXIL::ResourceKind::Texture2D: uv.value.u32v[3] = mipLevelOrSampleCount; break; + case DXIL::ResourceKind::Texture3D: uv.value.u32v[3] = mipLevelOrSampleCount; break; + case DXIL::ResourceKind::Texture2DMS: msIndex = mipLevelOrSampleCount; break; + case DXIL::ResourceKind::Texture2DMSArray: msIndex = mipLevelOrSampleCount; break; + default: break; + } + } + + // UV is int data in args 3,4,5 + // Offset is int data in args 6,7,8 + for(uint32_t i = 0; i < 3; ++i) + { + if(GetShaderVariable(inst.args[3 + i], opCode, dxOpCode, arg, false)) + uv.value.s32v[i] = arg.value.s32v[0]; + if(GetShaderVariable(inst.args[6 + i], opCode, dxOpCode, arg, false)) + texelOffsets[i] = (int8_t)arg.value.s32v[0]; + } + } + else { // Sampler is in arg 2 rdcstr samplerId = GetArgumentName(2); @@ -3867,15 +3893,63 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, RDCASSERTEQUAL(samplerRef->resourceBase.resClass, ResourceClass::Sampler); // samplerRef->resourceBase must be a Sampler const DXIL::EntryPointInterface::Sampler &sampler = resRef->resourceBase.samplerData; - // TODO: BIAS COMES FROM THE Sample*Bias arguments samplerData.bias = 0.0f; samplerData.binding.registerSpace = samplerRef->resourceBase.space; samplerData.binding.shaderRegister = samplerRef->resourceBase.regBase; samplerData.mode = ConvertSamplerKindToSamplerMode(sampler.samplerType); + int32_t biasArg = -1; + int32_t lodArg = -1; + int32_t compareArg = -1; + int32_t gatherArg = -1; + uint32_t countOffset = 3; + uint32_t countUV = 4; + // TODO: Sample*: Clamp is in arg 10 + // TODO: CalculateLOD: clamped is in arg 6 + // CalculateSampleGather returns {CalculateLevelOfDetail(), CalculateLevelOfDetailUnclamped()} + + // SampleBias : bias is arg 10 + // SampleLevel: lod is in arg 10 + // SampleCmp: compare is in arg 10 + // SampleCmpBias: compare is in arg 10, bias is in arg 11 + // SampleCmpLevel: compare is in arg 10, LOD is in arg 11 + // SampleCmpGrad: compare is in arg 10 + // SampleCmpLevelZero: compare is in arg 10 + // TextureGather: compare is in arg 10, gather is in 9 + // TextureGatherCmp: compare is in arg 10, gather is in 9 + switch(dxOpCode) + { + case DXOp::Sample: break; + case DXOp::SampleBias: biasArg = 10; break; + case DXOp::SampleLevel: lodArg = 10; break; + case DXOp::SampleGrad: break; + case DXOp::SampleCmp: compareArg = 10; break; + case DXOp::SampleCmpBias: + compareArg = 10; + biasArg = 11; + break; + case DXOp::SampleCmpLevel: + compareArg = 10; + lodArg = 11; + break; + case DXOp::SampleCmpGrad: compareArg = 10; break; + case DXOp::SampleCmpLevelZero: compareArg = 10; break; + case DXOp::TextureGather: + countOffset = 2; + gatherArg = 9; + break; + case DXOp::CalculateLOD: countUV = 3; break; + case DXOp::TextureGatherCmp: + countOffset = 2; + gatherArg = 9; + compareArg = 10; + break; + default: RDCERR("Unhandled DX Operation %s", ToStr(dxOpCode).c_str()); break; + } + ShaderVariable arg; - // UV is float data in args 3,4,5,6 - for(uint32_t i = 0; i < 4; ++i) + // UV is float data in args: Sample* 3,4,5,6 ; CalculateLOD 3,4,5 + for(uint32_t i = 0; i < countUV; ++i) { if(GetShaderVariable(inst.args[3 + i], opCode, dxOpCode, arg)) { @@ -3886,62 +3960,54 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, } } - // Offset is int data in args 7,8,9 - if(GetShaderVariable(inst.args[7], opCode, dxOpCode, arg, false)) - texelOffsets[0] = (int8_t)arg.value.s32v[0]; - if(GetShaderVariable(inst.args[8], opCode, dxOpCode, arg, false)) - texelOffsets[1] = (int8_t)arg.value.s32v[0]; - if(GetShaderVariable(inst.args[9], opCode, dxOpCode, arg, false)) - texelOffsets[2] = (int8_t)arg.value.s32v[0]; - - // TODO: Sample: Clamp is in arg 10 - - // SampleLevel: LOD is in arg 10 - // SampleCmpLevelZero: compare is in arg 10 - if((dxOpCode == DXOp::SampleLevel) || (dxOpCode == DXOp::SampleCmpLevelZero)) + // Offset is int data in args: Sample* 7,8,9 ; Gather* 7,8 + for(uint32_t i = 0; i < countOffset; ++i) { - if(GetShaderVariable(inst.args[10], opCode, dxOpCode, arg)) + if(GetShaderVariable(inst.args[7 + i], opCode, dxOpCode, arg, false)) + texelOffsets[i] = (int8_t)arg.value.s32v[0]; + } + + if((lodArg > 0)) + { + if(GetShaderVariable(inst.args[lodArg], opCode, dxOpCode, arg)) { RDCASSERTEQUAL(arg.type, VarType::Float); lodValue = arg.value.f32v[0]; + } + } + if((compareArg > 0)) + { + if(GetShaderVariable(inst.args[compareArg], opCode, dxOpCode, arg)) + { + RDCASSERTEQUAL(arg.type, VarType::Float); compareValue = arg.value.f32v[0]; } } - } - else - { - ShaderVariable arg; - // TODO : mipLevelOrSampleCount is in arg 2 - if(GetShaderVariable(inst.args[2], opCode, dxOpCode, arg)) + + if(biasArg > 0) { - msIndex = arg.value.u32v[0]; - lodValue = arg.value.f32v[0]; - compareValue = arg.value.f32v[0]; + if(GetShaderVariable(inst.args[biasArg], opCode, dxOpCode, arg)) + { + RDCASSERTEQUAL(arg.type, VarType::Float); + samplerData.bias = arg.value.f32v[0]; + } } - // UV is int data in args 3,4,5 - if(GetShaderVariable(inst.args[3], opCode, dxOpCode, arg)) - uv.value.s32v[0] = arg.value.s32v[0]; - if(GetShaderVariable(inst.args[4], opCode, dxOpCode, arg)) - uv.value.s32v[1] = arg.value.s32v[0]; - if(GetShaderVariable(inst.args[5], opCode, dxOpCode, arg)) - uv.value.s32v[2] = arg.value.s32v[0]; - - // Offset is int data in args 6,7,8 - if(GetShaderVariable(inst.args[6], opCode, dxOpCode, arg)) - texelOffsets[0] = (int8_t)arg.value.s32v[0]; - if(GetShaderVariable(inst.args[7], opCode, dxOpCode, arg)) - texelOffsets[1] = (int8_t)arg.value.s32v[0]; - if(GetShaderVariable(inst.args[8], opCode, dxOpCode, arg)) - texelOffsets[2] = (int8_t)arg.value.s32v[0]; + if(gatherArg > 0) + { + if(GetShaderVariable(inst.args[gatherArg], opCode, dxOpCode, arg)) + { + RDCASSERTEQUAL(arg.type, VarType::SInt); + // Red = 0, Green = 1, Blue = 2, Alpha = 3 + gatherChannel = (DXILDebug::GatherChannel)arg.value.s32v[0]; + } + } } - // TODO: DDX & DDY ShaderVariable ddx; ShaderVariable ddy; - // Sample, SampleBias, SampleCmp, CalculateLOD need DDX, DDY - if((dxOpCode == DXOp::Sample) || (dxOpCode == DXOp::SampleBias) || - (dxOpCode == DXOp::SampleCmp) || (dxOpCode == DXOp::CalculateLOD)) + // Sample, SampleBias, CalculateLOD need DDX, DDY + if((dxOpCode == DXOp::Sample) || (dxOpCode == DXOp::SampleBias) || (dxOpCode == DXOp::CalculateLOD)) { if(m_ShaderType != DXBC::ShaderType::Pixel || workgroups.size() != 4) { @@ -3950,7 +4016,6 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, else { // texture samples use coarse derivatives - // TODO: the UV should be the ID per UV compponent ShaderValue delta; for(uint32_t i = 0; i < 4; i++) { @@ -3964,19 +4029,37 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, } } } - else if(dxOpCode == DXOp::SampleGrad) + else if((dxOpCode == DXOp::SampleGrad) || (dxOpCode == DXOp::SampleCmpGrad)) { - // TODO: get from arguments + // SampleGrad DDX is argument 10, DDY is argument 14 + // SampleCmpGrad DDX is argument 11, DDY is argument 15 + uint32_t ddx0 = dxOpCode == DXOp::SampleGrad ? 10 : 11; + uint32_t ddy0 = ddx0 + 4; + ShaderVariable arg; + for(uint32_t i = 0; i < 4; i++) + { + if(uvDDXY[i]) + { + RDCASSERT(GetShaderVariable(inst.args[ddx0 + i], opCode, dxOpCode, arg)); + ddx.value.f32v[i] = arg.value.f32v[0]; + RDCASSERT(GetShaderVariable(inst.args[ddy0 + i], opCode, dxOpCode, arg)); + ddy.value.f32v[i] = arg.value.f32v[0]; + } + } } uint8_t swizzle[4] = {0, 1, 2, 3}; - // TODO: GATHER CHANNEL - GatherChannel gatherChannel = GatherChannel::Red; uint32_t instructionIdx = m_FunctionInstructionIdx - 1; const char *opString = ToStr(dxOpCode).c_str(); - ShaderVariable data; + // TODO: TextureGatherRaw // SM 6.7 + // Return types for TextureGatherRaw + // DXGI_FORMAT_R16_UINT : u16 + // DXGI_FORMAT_R32_UINT : u32 + // DXGI_FORMAT_R32G32_UINT : u32x2 + + ShaderVariable data; apiWrapper->CalculateSampleGather(dxOpCode, resourceData, samplerData, uv, ddx, ddy, texelOffsets, msIndex, lodValue, compareValue, swizzle, gatherChannel, m_ShaderType, instructionIdx, opString, data); diff --git a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp index 758539df4..d20fe27f9 100644 --- a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp @@ -1806,13 +1806,8 @@ rdcstr Program::GetDebugStatus() case DXOp::Ubfe: case DXOp::Bfi: case DXOp::CBufferLoad: - case DXOp::SampleBias: - case DXOp::SampleGrad: - case DXOp::SampleCmp: case DXOp::BufferUpdateCounter: case DXOp::CheckAccessFullyMapped: - case DXOp::TextureGather: - case DXOp::TextureGatherCmp: case DXOp::AtomicBinOp: case DXOp::AtomicCompareExchange: case DXOp::Barrier: @@ -1949,7 +1944,6 @@ rdcstr Program::GetDebugStatus() case DXOp::IsHelperLane: case DXOp::QuadVote: case DXOp::TextureGatherRaw: - case DXOp::SampleCmpLevel: case DXOp::TextureStoreSample: case DXOp::WaveMatrix_Annotate: case DXOp::WaveMatrix_Depth: @@ -1979,8 +1973,6 @@ rdcstr Program::GetDebugStatus() case DXOp::AnnotateNodeRecordHandle: case DXOp::NodeOutputIsValid: case DXOp::GetRemainingRecursionLevels: - case DXOp::SampleCmpGrad: - case DXOp::SampleCmpBias: case DXOp::StartVertexLocation: case DXOp::StartInstanceLocation: case DXOp::NumOpCodes: