From 654acb67f5b98ad2ce7032d1e63de2b0190e8da9 Mon Sep 17 00:00:00 2001 From: Steve Karolewics Date: Thu, 16 Jan 2020 21:47:08 -0800 Subject: [PATCH] Add register space support for shader global state UAV/SRV data Instead of fixed arrays, the global state stores a map of UAVs and SRVs, with the key being a pair of the shader register and register space. Switched D3D12 sampler/gather to use SM5.1 and handle register spaces. --- renderdoc/driver/d3d11/d3d11_shaderdebug.cpp | 71 +++++++------ renderdoc/driver/d3d12/d3d12_shaderdebug.cpp | 101 +++++++++++-------- renderdoc/driver/shaders/dxbc/dxbc_debug.cpp | 64 ++++++------ renderdoc/driver/shaders/dxbc/dxbc_debug.h | 51 ++++++---- 4 files changed, 161 insertions(+), 126 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp index ae71a8787..9e0153a53 100644 --- a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp +++ b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp @@ -1069,31 +1069,33 @@ bool D3D11DebugAPIWrapper::CalculateSampleGather( ID3D11SamplerState *usedSamp = NULL; // fetch SRV and sampler from the shader stage we're debugging that this opcode wants to load from + UINT texSlot = resourceData.binding.shaderRegister; + UINT samplerSlot = samplerData.binding.shaderRegister; switch(GetShaderType()) { case DXBC::ShaderType::Vertex: - context->VSGetShaderResources(resourceData.slot, 1, &usedSRV); - context->VSGetSamplers(samplerData.slot, 1, &usedSamp); + context->VSGetShaderResources(texSlot, 1, &usedSRV); + context->VSGetSamplers(samplerSlot, 1, &usedSamp); break; case DXBC::ShaderType::Hull: - context->HSGetShaderResources(resourceData.slot, 1, &usedSRV); - context->HSGetSamplers(samplerData.slot, 1, &usedSamp); + context->HSGetShaderResources(texSlot, 1, &usedSRV); + context->HSGetSamplers(samplerSlot, 1, &usedSamp); break; case DXBC::ShaderType::Domain: - context->DSGetShaderResources(resourceData.slot, 1, &usedSRV); - context->DSGetSamplers(samplerData.slot, 1, &usedSamp); + context->DSGetShaderResources(texSlot, 1, &usedSRV); + context->DSGetSamplers(samplerSlot, 1, &usedSamp); break; case DXBC::ShaderType::Geometry: - context->GSGetShaderResources(resourceData.slot, 1, &usedSRV); - context->GSGetSamplers(samplerData.slot, 1, &usedSamp); + context->GSGetShaderResources(texSlot, 1, &usedSRV); + context->GSGetSamplers(samplerSlot, 1, &usedSamp); break; case DXBC::ShaderType::Pixel: - context->PSGetShaderResources(resourceData.slot, 1, &usedSRV); - context->PSGetSamplers(samplerData.slot, 1, &usedSamp); + context->PSGetShaderResources(texSlot, 1, &usedSRV); + context->PSGetSamplers(samplerSlot, 1, &usedSamp); break; case DXBC::ShaderType::Compute: - context->CSGetShaderResources(resourceData.slot, 1, &usedSRV); - context->CSGetSamplers(samplerData.slot, 1, &usedSamp); + context->CSGetShaderResources(texSlot, 1, &usedSRV); + context->CSGetSamplers(samplerSlot, 1, &usedSamp); break; default: RDCERR("Unhandled shader type %d", GetShaderType()); break; } @@ -1414,7 +1416,8 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global ID3D11Resource *res = NULL; UAVs[i]->GetResource(&res); - global.uavs[dsti].hiddenCounter = GetStructCount(UAVs[i]); + ShaderDebug::BindingSlot slot(dsti, 0); + global.uavs[slot].hiddenCounter = GetStructCount(UAVs[i]); D3D11_UNORDERED_ACCESS_VIEW_DESC udesc; UAVs[i]->GetDesc(&udesc); @@ -1450,37 +1453,37 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global { ResourceFormat fmt = MakeResourceFormat(GetTypedFormat(udesc.Format)); - global.uavs[dsti].format.byteWidth = fmt.compByteWidth; - global.uavs[dsti].format.numComps = fmt.compCount; - global.uavs[dsti].format.fmt = fmt.compType; + global.uavs[slot].format.byteWidth = fmt.compByteWidth; + global.uavs[slot].format.numComps = fmt.compCount; + global.uavs[slot].format.fmt = fmt.compType; if(udesc.Format == DXGI_FORMAT_R11G11B10_FLOAT) - global.uavs[dsti].format.byteWidth = 11; + global.uavs[slot].format.byteWidth = 11; if(udesc.Format == DXGI_FORMAT_R10G10B10A2_UINT || udesc.Format == DXGI_FORMAT_R10G10B10A2_UNORM) - global.uavs[dsti].format.byteWidth = 10; + global.uavs[slot].format.byteWidth = 10; } if(udesc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER) { - global.uavs[dsti].firstElement = udesc.Buffer.FirstElement; - global.uavs[dsti].numElements = udesc.Buffer.NumElements; + global.uavs[slot].firstElement = udesc.Buffer.FirstElement; + global.uavs[slot].numElements = udesc.Buffer.NumElements; } if(res) { if(WrappedID3D11Buffer::IsAlloc(res)) { - GetBufferData((ID3D11Buffer *)res, 0, 0, global.uavs[dsti].data); + GetBufferData((ID3D11Buffer *)res, 0, 0, global.uavs[slot].data); } else { - global.uavs[dsti].tex = true; + global.uavs[slot].tex = true; - uint32_t &rowPitch = global.uavs[dsti].rowPitch; - uint32_t &depthPitch = global.uavs[dsti].depthPitch; + uint32_t &rowPitch = global.uavs[slot].rowPitch; + uint32_t &depthPitch = global.uavs[slot].depthPitch; - bytebuf &data = global.uavs[dsti].data; + bytebuf &data = global.uavs[slot].data; if(udesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1D || udesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY) @@ -1627,9 +1630,11 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global D3D11_SHADER_RESOURCE_VIEW_DESC sdesc; SRVs[i]->GetDesc(&sdesc); + ShaderDebug::BindingSlot slot(i, 0); + if(sdesc.Format != DXGI_FORMAT_UNKNOWN) { - ShaderDebug::FillViewFmt(sdesc.Format, global.srvs[i].format); + ShaderDebug::FillViewFmt(sdesc.Format, global.srvs[slot].format); } else { @@ -1642,11 +1647,11 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global D3D11_BUFFER_DESC bufdesc; buf->GetDesc(&bufdesc); - global.srvs[i].format.stride = bufdesc.StructureByteStride; + global.srvs[slot].format.stride = bufdesc.StructureByteStride; // if we didn't get a type from the SRV description, try to pull it from the declaration ShaderDebug::LookupSRVFormatFromShaderReflection(*dxbc->GetReflection(), (uint32_t)i, - global.srvs[i].format); + global.srvs[slot].format); } } @@ -1654,20 +1659,20 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global { // I know this isn't what the docs say, but as best as I can tell // this is how it's used. - global.srvs[i].firstElement = sdesc.Buffer.FirstElement; - global.srvs[i].numElements = sdesc.Buffer.NumElements; + global.srvs[slot].firstElement = sdesc.Buffer.FirstElement; + global.srvs[slot].numElements = sdesc.Buffer.NumElements; } else if(sdesc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) { - global.srvs[i].firstElement = sdesc.BufferEx.FirstElement; - global.srvs[i].numElements = sdesc.BufferEx.NumElements; + global.srvs[slot].firstElement = sdesc.BufferEx.FirstElement; + global.srvs[slot].numElements = sdesc.BufferEx.NumElements; } if(res) { if(WrappedID3D11Buffer::IsAlloc(res)) { - GetBufferData((ID3D11Buffer *)res, 0, 0, global.srvs[i].data); + GetBufferData((ID3D11Buffer *)res, 0, 0, global.srvs[slot].data); } } diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index fe20d5141..e39cab380 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -453,8 +453,10 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( rdcstr sampleProgram; - UINT texSlot = resourceData.slot; - UINT sampSlot = samplerData.slot; + rdcstr strResourceBinding = StringFormat::Fmt("t%u, space%u", resourceData.binding.shaderRegister, + resourceData.binding.registerSpace); + rdcstr strSamplerBinding = StringFormat::Fmt("s%u, space%u", samplerData.binding.shaderRegister, + samplerData.binding.registerSpace); if(opcode == OPCODE_SAMPLE || opcode == OPCODE_SAMPLE_B || opcode == OPCODE_SAMPLE_D) { @@ -476,8 +478,9 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( ddy = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.i.x, ddyCalc.value.i.y, ddyCalc.value.i.z, ddyCalc.value.i.w); - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", - textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); + sampleProgram = StringFormat::Fmt("%s : register(%s);\n%s : register(%s);\n\n", + textureDecl.c_str(), strResourceBinding.c_str(), + samplerDecl.c_str(), strSamplerBinding.c_str()); sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; sampleProgram += StringFormat::Fmt("t.SampleGrad(s, %s, %s, %s %s)%s;\n", texcoords.c_str(), ddx.c_str(), ddy.c_str(), offsets.c_str(), strSwizzle.c_str()); @@ -486,8 +489,9 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( else if(opcode == OPCODE_SAMPLE_L) { // lod selection - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", - textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); + sampleProgram = StringFormat::Fmt("%s : register(%s);\n%s : register(%s);\n\n", + textureDecl.c_str(), strResourceBinding.c_str(), + samplerDecl.c_str(), strSamplerBinding.c_str()); sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; sampleProgram += StringFormat::Fmt("t.SampleLevel(s, %s, %.10f %s)%s;\n", texcoords.c_str(), lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); @@ -522,8 +526,9 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( if(opcode == OPCODE_SAMPLE_C) { // comparison value - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", - textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); + sampleProgram = StringFormat::Fmt("%s : register(%s);\n%s : register(%s);\n\n", + textureDecl.c_str(), strResourceBinding.c_str(), + samplerDecl.c_str(), strSamplerBinding.c_str()); sampleProgram += funcRet + " main(float4 pos : SV_Position, " + uvdecl + ") : SV_Target0\n{\n"; sampleProgram += StringFormat::Fmt("t.SampleCmpLevelZero(s, uv, %.10f %s).xxxx;\n", @@ -532,8 +537,9 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( } else if(opcode == OPCODE_LOD) { - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", - textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); + sampleProgram = StringFormat::Fmt("%s : register(%s);\n%s : register(%s);\n\n", + textureDecl.c_str(), strResourceBinding.c_str(), + samplerDecl.c_str(), strSamplerBinding.c_str()); sampleProgram += funcRet + " main(float4 pos : SV_Position, " + uvdecl + ") : SV_Target0\n{\n"; sampleProgram += @@ -546,8 +552,9 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( else if(opcode == OPCODE_SAMPLE_C_LZ) { // comparison value - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", - textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); + sampleProgram = StringFormat::Fmt("%s : register(%s);\n%s : register(%s);\n\n", + textureDecl.c_str(), strResourceBinding.c_str(), + samplerDecl.c_str(), strSamplerBinding.c_str()); sampleProgram += funcRet + " main() : SV_Target0\n{\n"; sampleProgram += StringFormat::Fmt("return t.SampleCmpLevelZero(s, %s, %.10f %s)%s;\n", texcoords.c_str(), @@ -556,14 +563,16 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( } else if(opcode == OPCODE_LD) { - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n\n", textureDecl.c_str(), texSlot); + sampleProgram = + StringFormat::Fmt("%s : register(%s);\n\n", textureDecl.c_str(), strResourceBinding.c_str()); sampleProgram += funcRet + " main() : SV_Target0\n{\n"; sampleProgram += "return t.Load(" + texcoords + offsets + ")" + strSwizzle + ";"; sampleProgram += "\n}\n"; } else if(opcode == OPCODE_LD_MS) { - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n\n", textureDecl.c_str(), texSlot); + sampleProgram = + StringFormat::Fmt("%s : register(%s);\n\n", textureDecl.c_str(), strResourceBinding.c_str()); sampleProgram += funcRet + " main() : SV_Target0\n{\n"; sampleProgram += StringFormat::Fmt("t.Load(%s, int(%d) %s)%s;\n", texcoords.c_str(), multisampleIndex, offsets.c_str(), strSwizzle.c_str()); @@ -571,8 +580,9 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( } else if(opcode == OPCODE_GATHER4 || opcode == OPCODE_GATHER4_PO) { - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", - textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); + sampleProgram = StringFormat::Fmt("%s : register(%s);\n%s : register(%s);\n\n", + textureDecl.c_str(), strResourceBinding.c_str(), + samplerDecl.c_str(), strSamplerBinding.c_str()); sampleProgram += funcRet + " main() : SV_Target0\n{\n"; sampleProgram += StringFormat::Fmt("return t.Gather%s(s, %s %s)%s;\n", strGatherChannel.c_str(), texcoords.c_str(), offsets.c_str(), strSwizzle.c_str()); @@ -581,8 +591,9 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( else if(opcode == OPCODE_GATHER4_C || opcode == OPCODE_GATHER4_PO_C) { // comparison value - sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", - textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); + sampleProgram = StringFormat::Fmt("%s : register(%s);\n%s : register(%s);\n\n", + textureDecl.c_str(), strResourceBinding.c_str(), + samplerDecl.c_str(), strSamplerBinding.c_str()); sampleProgram += funcRet + " main() : SV_Target0\n{\n"; sampleProgram += StringFormat::Fmt("return t.GatherCmp%s(s, %s, %.10f %s)%s;\n", strGatherChannel.c_str(), texcoords.c_str(), @@ -590,17 +601,19 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( sampleProgram += "}\n"; } - // Create VS/PS to fetch the sample + // Create VS/PS to fetch the sample. Because the program being debugged might be using SM 5.1, we + // need to do that too, to support reusing the existing root signature that may use a non-zero + // register space for the resource or sampler. ID3DBlob *vsBlob = NULL; ID3DBlob *psBlob = NULL; UINT flags = D3DCOMPILE_DEBUG | D3DCOMPILE_WARNINGS_ARE_ERRORS; - if(m_pDevice->GetShaderCache()->GetShaderBlob(vsProgram.c_str(), "main", flags, "vs_5_0", + if(m_pDevice->GetShaderCache()->GetShaderBlob(vsProgram.c_str(), "main", flags, "vs_5_1", &vsBlob) != "") { RDCERR("Failed to create shader to extract inputs"); return false; } - if(m_pDevice->GetShaderCache()->GetShaderBlob(sampleProgram.c_str(), "main", flags, "ps_5_0", + if(m_pDevice->GetShaderCache()->GetShaderBlob(sampleProgram.c_str(), "main", flags, "ps_5_1", &psBlob) != "") { RDCERR("Failed to create shader to extract inputs"); @@ -769,34 +782,36 @@ void D3D12DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV && element.type == eRootSRV) { UINT shaderReg = param.Descriptor.ShaderRegister; + ShaderDebug::BindingSlot slot(shaderReg, param.Descriptor.RegisterSpace); ID3D12Resource *pResource = rm->GetCurrentAs(element.id); D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); // TODO: Root buffers can be 32-bit UINT/SINT/FLOAT. Using UINT for now, but the // resource desc format or the DXBC reflection info might be more correct. - ShaderDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, global.srvs[shaderReg].format); - global.srvs[shaderReg].firstElement = (uint32_t)(element.offset / sizeof(uint32_t)); - global.srvs[shaderReg].numElements = + ShaderDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, global.srvs[slot].format); + global.srvs[slot].firstElement = (uint32_t)(element.offset / sizeof(uint32_t)); + global.srvs[slot].numElements = (uint32_t)((resDesc.Width - element.offset) / sizeof(uint32_t)); if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - GetBufferData(pResource, 0, 0, global.srvs[shaderReg].data); + GetBufferData(pResource, 0, 0, global.srvs[slot].data); } else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV && element.type == eRootUAV) { UINT shaderReg = param.Descriptor.ShaderRegister; + ShaderDebug::BindingSlot slot(shaderReg, param.Descriptor.RegisterSpace); ID3D12Resource *pResource = rm->GetCurrentAs(element.id); D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); // TODO: Root buffers can be 32-bit UINT/SINT/FLOAT. Using UINT for now, but the // resource desc format or the DXBC reflection info might be more correct. - ShaderDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, global.uavs[shaderReg].format); - global.uavs[shaderReg].firstElement = (uint32_t)(element.offset / sizeof(uint32_t)); - global.uavs[shaderReg].numElements = + ShaderDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, global.uavs[slot].format); + global.uavs[slot].firstElement = (uint32_t)(element.offset / sizeof(uint32_t)); + global.uavs[slot].numElements = (uint32_t)((resDesc.Width - element.offset) / sizeof(uint32_t)); if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - GetBufferData(pResource, 0, 0, global.uavs[shaderReg].data); + GetBufferData(pResource, 0, 0, global.uavs[slot].data); } else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && element.type == eRootTable) @@ -838,34 +853,36 @@ void D3D12DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global { if(desc) { + ShaderDebug::BindingSlot slot(shaderReg, range.RegisterSpace); + ResourceId srvId = desc->GetResResourceId(); ID3D12Resource *pResource = rm->GetCurrentAs(srvId); D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = desc->GetSRV(); if(srvDesc.Format != DXGI_FORMAT_UNKNOWN) { - ShaderDebug::FillViewFmt(srvDesc.Format, global.srvs[shaderReg].format); + ShaderDebug::FillViewFmt(srvDesc.Format, global.srvs[slot].format); } else { D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { - global.srvs[shaderReg].format.stride = srvDesc.Buffer.StructureByteStride; + global.srvs[slot].format.stride = srvDesc.Buffer.StructureByteStride; // If we didn't get a type from the SRV description, try to pull it from the // shader reflection info ShaderDebug::LookupSRVFormatFromShaderReflection( - *dxbc->GetReflection(), (uint32_t)shaderReg, global.srvs[shaderReg].format); + *dxbc->GetReflection(), (uint32_t)shaderReg, global.srvs[slot].format); } } if(srvDesc.ViewDimension == D3D12_SRV_DIMENSION_BUFFER) { - global.srvs[shaderReg].firstElement = (uint32_t)srvDesc.Buffer.FirstElement; - global.srvs[shaderReg].numElements = srvDesc.Buffer.NumElements; + global.srvs[slot].firstElement = (uint32_t)srvDesc.Buffer.FirstElement; + global.srvs[slot].numElements = srvDesc.Buffer.NumElements; - GetBufferData(pResource, 0, 0, global.srvs[shaderReg].data); + GetBufferData(pResource, 0, 0, global.srvs[slot].data); } // Textures are sampled via a pixel shader, so there's no need to copy their data @@ -879,6 +896,8 @@ void D3D12DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global { if(desc) { + ShaderDebug::BindingSlot slot(shaderReg, range.RegisterSpace); + ResourceId uavId = desc->GetResResourceId(); ID3D12Resource *pResource = rm->GetCurrentAs(uavId); @@ -887,14 +906,14 @@ void D3D12DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = desc->GetUAV(); if(uavDesc.Format != DXGI_FORMAT_UNKNOWN) { - ShaderDebug::FillViewFmt(uavDesc.Format, global.uavs[shaderReg].format); + ShaderDebug::FillViewFmt(uavDesc.Format, global.uavs[slot].format); } else { D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { - global.uavs[shaderReg].format.stride = uavDesc.Buffer.StructureByteStride; + global.uavs[slot].format.stride = uavDesc.Buffer.StructureByteStride; // TODO: Try looking up UAV from shader reflection info? } @@ -902,15 +921,15 @@ void D3D12DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global if(uavDesc.ViewDimension == D3D12_UAV_DIMENSION_BUFFER) { - global.uavs[shaderReg].firstElement = (uint32_t)uavDesc.Buffer.FirstElement; - global.uavs[shaderReg].numElements = uavDesc.Buffer.NumElements; + global.uavs[slot].firstElement = (uint32_t)uavDesc.Buffer.FirstElement; + global.uavs[slot].numElements = uavDesc.Buffer.NumElements; - GetBufferData(pResource, 0, 0, global.uavs[shaderReg].data); + GetBufferData(pResource, 0, 0, global.uavs[slot].data); } else { // TODO: Handle texture resources in UAVs - need to copy/map to fetch the data - global.uavs[shaderReg].tex = true; + global.uavs[slot].tex = true; } } } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 9f0bc6fb4..afa6d797e 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -2673,14 +2673,16 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua case OPCODE_IMM_ATOMIC_ALLOC: { - uint32_t count = global.uavs[srcOpers[0].value.u.x].hiddenCounter++; + ShaderDebug::BindingSlot slot(srcOpers[0].value.u.x, 0); + uint32_t count = global.uavs[slot].hiddenCounter++; s.SetDst(op.operands[0], op, ShaderVariable("", count, count, count, count)); break; } case OPCODE_IMM_ATOMIC_CONSUME: { - uint32_t count = --global.uavs[srcOpers[0].value.u.x].hiddenCounter; + ShaderDebug::BindingSlot slot(srcOpers[0].value.u.x, 0); + uint32_t count = --global.uavs[slot].hiddenCounter; s.SetDst(op.operands[0], op, ShaderVariable("", count, count, count, count)); break; } @@ -2794,9 +2796,10 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua } else { - offset = global.uavs[resIndex].firstElement; - numElems = global.uavs[resIndex].numElements; - data = &global.uavs[resIndex].data[0]; + ShaderDebug::BindingSlot slot(resIndex, 0); + offset = global.uavs[slot].firstElement; + numElems = global.uavs[slot].numElements; + data = &global.uavs[slot].data[0]; for(size_t i = 0; i < s.program->GetNumDeclarations(); i++) { @@ -3019,9 +3022,10 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua RDCASSERT(stride != 0); - uint32_t offset = srv ? global.srvs[resIndex].firstElement : global.uavs[resIndex].firstElement; - uint32_t numElems = srv ? global.srvs[resIndex].numElements : global.uavs[resIndex].numElements; - GlobalState::ViewFmt fmt = srv ? global.srvs[resIndex].format : global.uavs[resIndex].format; + ShaderDebug::BindingSlot slot(resIndex, 0); + uint32_t offset = srv ? global.srvs[slot].firstElement : global.uavs[slot].firstElement; + uint32_t numElems = srv ? global.srvs[slot].numElements : global.uavs[slot].numElements; + GlobalState::ViewFmt fmt = srv ? global.srvs[slot].format : global.uavs[slot].format; // indexing for raw views is in bytes, but firstElement/numElements is in format-sized // units. Multiply up by stride @@ -3031,10 +3035,10 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua numElems *= RDCMIN(4, fmt.byteWidth); } - byte *data = srv ? &global.srvs[resIndex].data[0] : &global.uavs[resIndex].data[0]; - bool texData = srv ? false : global.uavs[resIndex].tex; - uint32_t rowPitch = srv ? 0 : global.uavs[resIndex].rowPitch; - uint32_t depthPitch = srv ? 0 : global.uavs[resIndex].depthPitch; + byte *data = srv ? &global.srvs[slot].data[0] : &global.uavs[slot].data[0]; + bool texData = srv ? false : global.uavs[slot].tex; + uint32_t rowPitch = srv ? 0 : global.uavs[slot].rowPitch; + uint32_t depthPitch = srv ? 0 : global.uavs[slot].depthPitch; if(gsm) { @@ -3070,7 +3074,7 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua } if(!data || (!texData && elemIdx >= numElems) || - (texData && texOffset >= global.uavs[resIndex].data.size())) + (texData && texOffset >= global.uavs[slot].data.size())) { if(load) s.SetDst(op.operands[0], op, ShaderVariable("", 0U, 0U, 0U, 0U)); @@ -3560,6 +3564,10 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua DXBC::ResourceRetType resourceRetType = DXBC::RETURN_TYPE_UNKNOWN; int sampleCount = 0; + // Default assumptions for bindings + ShaderDebug::BindingSlot resourceBinding((uint32_t)op.operands[2].indices[0].index, 0); + ShaderDebug::BindingSlot samplerBinding(0, 0); + for(size_t i = 0; i < program->GetNumDeclarations(); i++) { const Declaration &decl = program->GetDeclaration(i); @@ -3568,6 +3576,7 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua decl.operand.indices == op.operands[3].indices) { samplerMode = decl.samplerMode; + samplerBinding.shaderRegister = (uint32_t)op.operands[3].indices[0].index; } if(decl.dim == RESOURCE_DIMENSION_BUFFER && op.operation == OPCODE_LD && decl.declaration == OPCODE_DCL_RESOURCE && decl.operand.type == TYPE_RESOURCE && @@ -3575,13 +3584,13 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua { resourceDim = decl.dim; - uint32_t resIndex = (uint32_t)decl.operand.indices[0].index; + resourceBinding.shaderRegister = (uint32_t)decl.operand.indices[0].index; - const byte *data = &global.srvs[resIndex].data[0]; - uint32_t offset = global.srvs[resIndex].firstElement; - uint32_t numElems = global.srvs[resIndex].numElements; + const byte *data = &global.srvs[resourceBinding].data[0]; + uint32_t offset = global.srvs[resourceBinding].firstElement; + uint32_t numElems = global.srvs[resourceBinding].numElements; - GlobalState::ViewFmt fmt = global.srvs[resIndex].format; + GlobalState::ViewFmt fmt = global.srvs[resourceBinding].format; data += fmt.Stride() * offset; @@ -3623,6 +3632,8 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua resourceRetType = decl.resType[0]; sampleCount = decl.sampleCount; + resourceBinding.shaderRegister = (uint32_t)decl.operand.indices[0].index; + // doesn't seem like these are ever less than four components, even if the texture is // declared for example. // shouldn't matter though is it just comes out in the wash. @@ -3675,16 +3686,6 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua ddyCalc = srcOpers[4]; } - UINT texSlot = (UINT)op.operands[2].indices[0].index; - UINT samplerSlot = 0; - - for(size_t i = 0; i < op.operands.size(); i++) - { - const Operand &operand = op.operands[i]; - if(operand.type == OperandType::TYPE_SAMPLER) - samplerSlot = (UINT)operand.indices[0].index; - } - int multisampleIndex = srcOpers[2].value.i.x; float lodOrCompareValue = srcOpers[3].value.f.x; if(op.operation == OPCODE_GATHER4_PO_C) @@ -3709,20 +3710,17 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua // for bias instruction we can't do a SampleGradBias, so add the bias into the sampler state. float samplerBias = 0.0f; if(op.operation == OPCODE_SAMPLE_B) - { - samplerSlot = (UINT)srcOpers[2].value.u.x; samplerBias = srcOpers[3].value.f.x; - } SampleGatherResourceData resourceData; resourceData.dim = resourceDim; resourceData.retType = resourceRetType; resourceData.sampleCount = sampleCount; - resourceData.slot = texSlot; + resourceData.binding = resourceBinding; SampleGatherSamplerData samplerData; samplerData.mode = samplerMode; - samplerData.slot = samplerSlot; + samplerData.binding = samplerBinding; samplerData.bias = samplerBias; ShaderVariable lookupResult("tex", 0.0f, 0.0f, 0.0f, 0.0f); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index ef3949148..4e9a23782 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -40,22 +40,27 @@ enum DXGI_FORMAT; namespace ShaderDebug { +struct BindingSlot +{ + BindingSlot() : shaderRegister(UINT32_MAX), registerSpace(UINT32_MAX) {} + BindingSlot(uint32_t shaderReg, uint32_t regSpace) + : shaderRegister(shaderReg), registerSpace(regSpace) + { + } + bool operator<(const BindingSlot &o) const + { + if(registerSpace != o.registerSpace) + return registerSpace < o.registerSpace; + return shaderRegister < o.shaderRegister; + } + uint32_t shaderRegister; + uint32_t registerSpace; +}; + struct GlobalState { public: - GlobalState() - { - for(int i = 0; i < 8; i++) - { - uavs[i].firstElement = uavs[i].numElements = uavs[i].hiddenCounter = 0; - uavs[i].rowPitch = uavs[i].depthPitch = 0; - uavs[i].tex = false; - } - - for(int i = 0; i < 128; i++) - srvs[i].firstElement = srvs[i].numElements = 0; - } - + GlobalState() {} void PopulateGroupshared(const DXBCBytecode::Program *pBytecode); struct ViewFmt @@ -77,8 +82,13 @@ public: } }; - struct + struct UAVData { + UAVData() + : firstElement(0), numElements(0), tex(false), rowPitch(0), depthPitch(0), hiddenCounter(0) + { + } + bytebuf data; uint32_t firstElement; uint32_t numElements; @@ -89,16 +99,19 @@ public: ViewFmt format; uint32_t hiddenCounter; - } uavs[64]; + }; + std::map uavs; - struct + struct SRVData { + SRVData() : firstElement(0), numElements(0) {} bytebuf data; uint32_t firstElement; uint32_t numElements; ViewFmt format; - } srvs[128]; + }; + std::map srvs; struct groupsharedMem { @@ -203,14 +216,14 @@ struct SampleGatherResourceData DXBCBytecode::ResourceDimension dim; DXBC::ResourceRetType retType; int sampleCount; - UINT slot; + ShaderDebug::BindingSlot binding; }; struct SampleGatherSamplerData { DXBCBytecode::SamplerMode mode; - UINT slot; float bias; + ShaderDebug::BindingSlot binding; }; enum class GatherChannel : uint8_t