diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index b27f69a5e..692f57b4b 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -1617,7 +1617,7 @@ protected: uint32_t GetMetaSlot(const DebugLocation *l) const; void AssignMetaSlot(rdcarray &metaSlots, uint32_t &nextMetaSlot, DebugLocation &l); - const ResourceReference *GetResourceReference(const rdcstr &handleStr) const; + const ResourceReference *GetResourceReference(const DXILDebug::Id handleId) const; rdcstr GetHandleAlias(const rdcstr &handleStr) const; static DXILDebug::Id GetResultSSAId(const DXIL::Instruction &inst); static void MakeResultId(const Instruction &inst, rdcstr &resultId); @@ -1693,7 +1693,7 @@ protected: rdcstr m_Triple, m_Datalayout; rdcarray m_EntryPointInterfaces; - std::map m_ResourceHandles; + std::map m_ResourceByIdHandles; std::map m_SsaAliases; std::map m_ResourceAnnotateCounts; rdcarray m_Locals; diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.cpp b/renderdoc/driver/shaders/dxil/dxil_debug.cpp index 727647478..b64f4dbb4 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debug.cpp @@ -1427,12 +1427,14 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, case DXOp::GetDimensions: { // GetDimensions(handle,mipLevel) - rdcstr handleId = GetArgumentName(1); - const ResourceReference *resRef = GetResource(handleId); + Id handleId = GetArgumentId(1); + ShaderBindIndex bindIndex; + const DXIL::ResourceReference *resRef = GetResource(handleId, bindIndex); if(!resRef) break; - BindingSlot binding(resRef->resourceBase.regBase, resRef->resourceBase.space); + BindingSlot binding(resRef->resourceBase.regBase + bindIndex.arrayElement, + resRef->resourceBase.space); ShaderVariable data; uint32_t mipLevel = 0; if(!isUndef(inst.args[2])) @@ -1460,12 +1462,14 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, case DXOp::Texture2DMSGetSamplePosition: { // Texture2DMSGetSamplePosition(srv,index) - rdcstr handleId = GetArgumentName(1); - const ResourceReference *resRef = GetResource(handleId); + Id handleId = GetArgumentId(1); + ShaderBindIndex bindIndex; + const DXIL::ResourceReference *resRef = GetResource(handleId, bindIndex); if(!resRef) break; - BindingSlot binding(resRef->resourceBase.regBase, resRef->resourceBase.space); + BindingSlot binding(resRef->resourceBase.regBase + bindIndex.arrayElement, + resRef->resourceBase.space); ShaderVariable arg; RDCASSERT(GetShaderVariable(inst.args[2], opCode, dxOpCode, arg)); const char *opString = ToStr(dxOpCode).c_str(); @@ -1528,12 +1532,14 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, case DXOp::TextureGather: case DXOp::TextureGatherCmp: { - rdcstr handleId = GetArgumentName(1); - const ResourceReference *resRef = GetResource(handleId); + Id handleId = GetArgumentId(1); + ShaderBindIndex bindIndex; + const DXIL::ResourceReference *resRef = GetResource(handleId, bindIndex); if(!resRef) break; - PerformGPUResourceOp(workgroups, opCode, dxOpCode, resRef, apiWrapper, inst, result); + PerformGPUResourceOp(workgroups, opCode, dxOpCode, resRef, bindIndex, apiWrapper, inst, + result); eventFlags |= ShaderEvents::SampleLoadGather; break; } @@ -1550,8 +1556,9 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, // BufferStore(uav,coord0,coord1,value0,value1,value2,value3,mask) // RawBufferLoad(srv,index,elementOffset,mask,alignment) // RawBufferStore(uav,index,elementOffset,value0,value1,value2,value3,mask,alignment) - rdcstr handleId = GetArgumentName(1); - const ResourceReference *resRef = GetResource(handleId); + Id handleId = GetArgumentId(1); + ShaderBindIndex bindIndex; + const DXIL::ResourceReference *resRef = GetResource(handleId, bindIndex); if(!resRef) break; @@ -1559,7 +1566,8 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, // SRV TextureLoad is done on the GPU if((dxOpCode == DXOp::TextureLoad) && (resClass == ResourceClass::SRV)) { - PerformGPUResourceOp(workgroups, opCode, dxOpCode, resRef, apiWrapper, inst, result); + PerformGPUResourceOp(workgroups, opCode, dxOpCode, resRef, bindIndex, apiWrapper, + inst, result); eventFlags |= ShaderEvents::SampleLoadGather; break; } @@ -1809,10 +1817,17 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, // CreateHandleFromBinding(bind,index,nonUniformIndex) rdcstr baseResource = result.name; result.name.clear(); + uint32_t resIndexArgId = ~0U; if(dxOpCode == DXOp::AnnotateHandle) baseResource = GetArgumentName(1); + else if(dxOpCode == DXOp::CreateHandle) + resIndexArgId = 3; + else if(dxOpCode == DXOp::CreateHandleFromBinding) + resIndexArgId = 2; + else + RDCERR("Unhandled DXOp %s", ToStr(dxOpCode).c_str()); - const ResourceReference *resRef = m_Program.GetResourceReference(baseResource); + const ResourceReference *resRef = m_Program.GetResourceReference(resultId); if(resRef) { const rdcarray *list = NULL; @@ -1843,35 +1858,41 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper, recordChange = false; if(result.name.isEmpty()) { - // TODO: support for dynamic handles i.e. array lookups - RDCERR("Unhandled dynamic handle %s", resName.c_str()); - // Need to make a shader variable for the return : it needs to have a binding point - // DescriptorCategory category; - // uint32_t index; - // uint32_t arrayElement = 0; - // result.SetBindIndex(ShaderBindIndex(category, index, arrayElement)); + if(resIndexArgId < inst.args.size()) + { + // Make the ShaderVariable to represent the dynamic binding + // The base binding exists : array index is in argument "resIndexArgId" + ShaderVariable arg; + RDCASSERT(GetShaderVariable(inst.args[resIndexArgId], opCode, dxOpCode, arg)); + uint32_t arrayIndex = arg.value.u32v[0]; + bool isSRV = (resRef->resourceBase.resClass == ResourceClass::SRV); + DescriptorCategory category = isSRV ? DescriptorCategory::ReadOnlyResource + : DescriptorCategory::ReadWriteResource; + result.SetBindIndex(ShaderBindIndex(category, resRef->resourceIndex, arrayIndex)); + baseResource = result.name = baseResource; + } + else + { + RDCERR("Unhandled dynamic handle %s with invalid resIndexArgId", resName.c_str(), + resIndexArgId); + } } } else { - RDCERR("Base Resource not found %s", baseResource.c_str()); + RDCERR("Unknown Base Resource %s", baseResource.c_str()); } break; } case DXOp::CBufferLoadLegacy: { // CBufferLoadLegacy(handle,regIndex) - // Need to find the resource - rdcstr handleName = GetArgumentName(1); - const ResourceReference *resRef = GetResource(handleName); - if(!resRef) - break; + Id handleId = GetArgumentId(1); ShaderVariable arg; RDCASSERT(GetShaderVariable(inst.args[2], opCode, dxOpCode, arg)); uint32_t regIndex = arg.value.u32v[0]; - Id handleId = GetArgumentId(1); RDCASSERT(m_Live.contains(handleId)); auto itVar = m_LiveVariables.find(handleId); RDCASSERT(itVar != m_LiveVariables.end()); @@ -3899,8 +3920,9 @@ bool ThreadState::GetShaderVariable(const DXIL::Value *dxilValue, Operation op, bool ThreadState::GetVariable(const Id &id, Operation op, DXOp dxOpCode, ShaderVariable &var) const { RDCASSERT(m_Live.contains(id)); - RDCASSERTEQUAL(m_LiveVariables.count(id), 1); - var = m_LiveVariables.at(id); + auto it = m_LiveVariables.find(id); + RDCASSERT(it != m_LiveVariables.end()); + var = it->second; bool flushDenorm = OperationFlushing(op, dxOpCode); if(var.type == VarType::Double) @@ -3934,39 +3956,32 @@ void ThreadState::SetResult(const Id &id, ShaderVariable &result, Operation op, } } -void ThreadState::MarkResourceAccess(const rdcstr &name, const DXIL::ResourceReference *resRef) +void ThreadState::MarkResourceAccess(const rdcstr &name, const ShaderBindIndex &bindIndex) { if(m_State == NULL) return; - ResourceClass resClass = resRef->resourceBase.resClass; - if(resClass != ResourceClass::UAV && resClass != ResourceClass::SRV) + if(bindIndex.category != DescriptorCategory::ReadOnlyResource && + bindIndex.category != DescriptorCategory::ReadWriteResource) return; - bool isSRV = (resClass == ResourceClass::SRV); + bool isSRV = (bindIndex.category == DescriptorCategory::ReadOnlyResource); + m_State->changes.push_back(ShaderVariableChange()); + ShaderVariableChange &change = m_State->changes.back(); change.after.rows = change.after.columns = 1; change.after.type = isSRV ? VarType::ReadOnlyResource : VarType::ReadWriteResource; - - const DXIL::EntryPointInterface::ResourceBase &resourceBase = resRef->resourceBase; + change.after.SetBindIndex(bindIndex); + // The resource name will already have the array index appended to it (perhaps unresolved) change.after.name = name; - // TODO: find the array index - uint32_t arrayIdx = 0; - if(resourceBase.regCount > 1) - change.after.name += StringFormat::Fmt("[%u]", arrayIdx); - - change.after.SetBindIndex(ShaderBindIndex( - isSRV ? DescriptorCategory::ReadOnlyResource : DescriptorCategory::ReadWriteResource, - resRef->resourceIndex, arrayIdx)); // Check whether this resource was visited before bool found = false; - ShaderBindIndex bp = change.after.GetBindIndex(); rdcarray &accessed = isSRV ? m_accessedSRVs : m_accessedUAVs; for(size_t i = 0; i < accessed.size(); ++i) { - if(accessed[i] == bp) + if(accessed[i] == bindIndex) { found = true; break; @@ -3976,7 +3991,7 @@ void ThreadState::MarkResourceAccess(const rdcstr &name, const DXIL::ResourceRef if(found) change.before = change.after; else - accessed.push_back(bp); + accessed.push_back(bindIndex); } void ThreadState::AllocateMemoryForType(const DXIL::Type *type, Id allocId, ShaderVariable &var) @@ -4030,8 +4045,8 @@ void ThreadState::UpdateMemoryVariableFromBackingMemory(Id memoryId, const void void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, Operation opCode, DXOp dxOpCode, const DXIL::ResourceReference *resRef, - DebugAPIWrapper *apiWrapper, const DXIL::Instruction &inst, - ShaderVariable &result) + const ShaderBindIndex &bindIndex, DebugAPIWrapper *apiWrapper, + const DXIL::Instruction &inst, ShaderVariable &result) { // TextureLoad(srv,mipLevelOrSampleCount,coord0,coord1,coord2,offset0,offset1,offset2) // Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp) @@ -4070,7 +4085,7 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, resourceData.sampleCount = srv.sampleCount; resourceData.binding.registerSpace = resRef->resourceBase.space; - resourceData.binding.shaderRegister = resRef->resourceBase.regBase; + resourceData.binding.shaderRegister = resRef->resourceBase.regBase + bindIndex.arrayElement; ShaderVariable uv; int8_t texelOffsets[3] = {0, 0, 0}; @@ -4117,8 +4132,9 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, else { // Sampler is in arg 2 - rdcstr samplerId = GetArgumentName(2); - const ResourceReference *samplerRef = GetResource(samplerId); + Id samplerId = GetArgumentId(2); + ShaderBindIndex samplerBindIndex; + const DXIL::ResourceReference *samplerRef = GetResource(samplerId, samplerBindIndex); if(!samplerRef) return; @@ -4127,7 +4143,8 @@ void ThreadState::PerformGPUResourceOp(const rdcarray &workgroups, const DXIL::EntryPointInterface::Sampler &sampler = samplerRef->resourceBase.samplerData; samplerData.bias = 0.0f; samplerData.binding.registerSpace = samplerRef->resourceBase.space; - samplerData.binding.shaderRegister = samplerRef->resourceBase.regBase; + samplerData.binding.shaderRegister = + samplerRef->resourceBase.regBase + samplerBindIndex.arrayElement; samplerData.mode = ConvertSamplerKindToSamplerMode(sampler.samplerType); int32_t biasArg = -1; @@ -4304,23 +4321,30 @@ rdcstr ThreadState::GetArgumentName(uint32_t i) const return m_Program.GetArgId(*m_CurrentInstruction, i); } -Id ThreadState::GetArgumentId(uint32_t i) const +DXILDebug::Id ThreadState::GetArgumentId(uint32_t i) const { DXIL::Value *arg = m_CurrentInstruction->args[i]; return GetSSAId(arg); } -const DXIL::ResourceReference *ThreadState::GetResource(rdcstr handle) +const DXIL::ResourceReference *ThreadState::GetResource(Id handleId, ShaderBindIndex &bindIndex) { - const DXIL::ResourceReference *resRef = m_Program.GetResourceReference(handle); - if(resRef) + RDCASSERT(m_Live.contains(handleId)); + auto it = m_LiveVariables.find(handleId); + if(it != m_LiveVariables.end()) { - rdcstr alias = m_Program.GetHandleAlias(handle); - MarkResourceAccess(alias, resRef); - return resRef; + const ShaderVariable &var = m_LiveVariables.at(handleId); + const DXIL::ResourceReference *resRef = m_Program.GetResourceReference(handleId); + if(resRef) + { + rdcstr alias = m_Program.GetHandleAlias(resRef->handleID); + bindIndex = var.GetBindIndex(); + MarkResourceAccess(alias, bindIndex); + return resRef; + } } - RDCERR("Unknown resource handle '%s'", handle.c_str()); + RDCERR("Unknown resource handle %u", handleId); return NULL; } @@ -5535,6 +5559,9 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain for(uint32_t i = 0; i < list.resources.size(); i++) { const ShaderResource &res = list.resources[i]; + // Ignore arrays the debugger execution will mark specific array elements used + if(res.bindArraySize > 1) + continue; // Fetch the resource name BindingSlot slot(res.fixedBindNumber, res.fixedBindSetOrSpace); diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.h b/renderdoc/driver/shaders/dxil/dxil_debug.h index 47992bf66..3f9443234 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.h +++ b/renderdoc/driver/shaders/dxil/dxil_debug.h @@ -146,12 +146,12 @@ struct ThreadState bool Finished() const; bool ExecuteInstruction(DebugAPIWrapper *apiWrapper, const rdcarray &workgroups); - void MarkResourceAccess(const rdcstr &name, const DXIL::ResourceReference *resRef); + void MarkResourceAccess(const rdcstr &name, const ShaderBindIndex &bindIndex); void SetResult(const Id &id, ShaderVariable &result, DXIL::Operation op, DXIL::DXOp dxOpCode, ShaderEvents flags); rdcstr GetArgumentName(uint32_t i) const; Id GetArgumentId(uint32_t i) const; - const DXIL::ResourceReference *GetResource(rdcstr handle); + const DXIL::ResourceReference *GetResource(Id handleId, ShaderBindIndex &bindIndex); bool GetShaderVariable(const DXIL::Value *dxilValue, DXIL::Operation op, DXIL::DXOp dxOpCode, ShaderVariable &var, bool flushDenormInput = true) const; bool GetVariable(const Id &id, DXIL::Operation opCode, DXIL::DXOp dxOpCode, @@ -162,8 +162,8 @@ struct ThreadState void PerformGPUResourceOp(const rdcarray &workgroups, DXIL::Operation opCode, DXIL::DXOp dxOpCode, const DXIL::ResourceReference *resRef, - DebugAPIWrapper *apiWrapper, const DXIL::Instruction &inst, - ShaderVariable &result); + const ShaderBindIndex &bindIndex, DebugAPIWrapper *apiWrapper, + const DXIL::Instruction &inst, ShaderVariable &result); void Sub(const ShaderVariable &a, const ShaderVariable &b, ShaderValue &ret) const; ShaderValue DDX(bool fine, DXIL::Operation opCode, DXIL::DXOp dxOpCode, diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index 34f4efc46..ef0bb2732 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -3189,6 +3189,7 @@ void Program::MakeRDDisassemblyString(const DXBC::Reflection *reflection) } rdcstr resultIdStr; MakeResultId(inst, resultIdStr); + DXILDebug::Id resultId = GetResultSSAId(inst); bool showDxFuncName = false; rdcstr commentStr; @@ -3299,7 +3300,7 @@ void Program::MakeRDDisassemblyString(const DXBC::Reflection *reflection) nonUniformIndexArgId = 3; } - const ResourceReference *resRef = GetResourceReference(resultIdStr); + const ResourceReference *resRef = GetResourceReference(resultId); if(resRef) { uint32_t index = 0; @@ -3534,8 +3535,9 @@ void Program::MakeRDDisassemblyString(const DXBC::Reflection *reflection) { // CBufferLoad(handle,byteOffset,alignment) // CBufferLoadLegacy(handle,regIndex) + DXILDebug::Id handleId = GetSSAId(inst.args[1]); + const ResourceReference *resRef = GetResourceReference(handleId); rdcstr handleStr = GetArgId(inst, 1); - const ResourceReference *resRef = GetResourceReference(handleStr); bool useFallback = true; if(entryPoint && resRef) { @@ -3683,8 +3685,9 @@ void Program::MakeRDDisassemblyString(const DXBC::Reflection *reflection) case DXOp::TextureLoad: { // TextureLoad(srv,mipLevelOrSampleCount,coord0,coord1,coord2,offset0,offset1,offset2) + DXILDebug::Id handleId = GetSSAId(inst.args[1]); + const ResourceReference *resRef = GetResourceReference(handleId); rdcstr handleStr = GetArgId(inst, 1); - const ResourceReference *resRef = GetResourceReference(handleStr); uint32_t sampleCount = 0; if(entryPoint && resRef) { @@ -4928,6 +4931,7 @@ void Program::ParseReferences(const DXBC::Reflection *reflection) { rdcstr resultIdStr; MakeResultId(inst, resultIdStr); + DXILDebug::Id resultId = GetResultSSAId(inst); DXOp dxOpCode = DXOp::NumOpCodes; RDCASSERT(getival(inst.args[0], dxOpCode)); @@ -5085,9 +5089,9 @@ void Program::ParseReferences(const DXBC::Reflection *reflection) if(resourceBase) { - RDCASSERT(!GetResourceReference(resultIdStr)); + RDCASSERT(!GetResourceReference(resultId)); ResourceReference resRef(resultIdStr, *resourceBase, resIndex); - m_ResourceHandles[resultIdStr] = m_ResourceHandles.size(); + m_ResourceByIdHandles[resultId] = m_ResourceByIdHandles.size(); m_ResourceReferences.push_back(resRef); resName = resourceBase->name; uint32_t index = 0; @@ -5137,13 +5141,14 @@ void Program::ParseReferences(const DXBC::Reflection *reflection) // If the underlying handle points to a known resource then duplicate the resource // and register it as resultIdStr + DXILDebug::Id handleId = GetSSAId(inst.args[1]); + const ResourceReference *resRef = GetResourceReference(handleId); rdcstr baseResource = GetArgId(inst, 1); - const ResourceReference *resRef = GetResourceReference(baseResource); rdcstr resBaseName = "typed_descriptor"; if(resRef) { resBaseName = resRef->resourceBase.name; - m_ResourceHandles[resultIdStr] = m_ResourceHandles.size(); + m_ResourceByIdHandles[resultId] = m_ResourceByIdHandles.size(); m_ResourceReferences.push_back(*resRef); } uint32_t annotateHandleCount = m_ResourceAnnotateCounts[resBaseName]; diff --git a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp index 82fb30f0d..d4dc28c55 100644 --- a/renderdoc/driver/shaders/dxil/dxil_reflect.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_reflect.cpp @@ -2076,12 +2076,13 @@ void Program::GetLocals(const DXBC::DXBCContainer *dxbc, size_t instruction, uin } } -const ResourceReference *Program::GetResourceReference(const rdcstr &handleStr) const +const ResourceReference *Program::GetResourceReference(const DXILDebug::Id handleId) const { - if(m_ResourceHandles.count(handleStr) > 0) + auto it = m_ResourceByIdHandles.find(handleId); + if(it != m_ResourceByIdHandles.end()) { - size_t resRefIndex = m_ResourceHandles.find(handleStr)->second; - if(resRefIndex < m_ResourceHandles.size()) + size_t resRefIndex = it->second; + if(resRefIndex < m_ResourceReferences.size()) { return &m_ResourceReferences[resRefIndex]; }