diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index b73df31eb..df3a2504e 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -605,7 +605,7 @@ bool D3D12DebugManager::CreateShaderDebugResources() { // MathOp is 2, SampleGatherOp is 6 const uint64_t resultMaxElementSize = sizeof(Vec4f) * (2 + 6); - const uint32_t maxQueuedResults = D3D12DebugManager::MAX_SHADER_DEBUG_QUEUED_OPS; + const uint32_t maxQueuedResults = ShaderDebugConstants::MAX_SHADER_DEBUG_QUEUED_OPS; const uint64_t shaderDebugReadbackSize = resultMaxElementSize * maxQueuedResults; RDCCOMPILE_ASSERT(shaderDebugReadbackSize < m_ReadbackSize, "Readback buffer is not big enough"); diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index a6264f325..45c6e7d6a 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -42,6 +42,13 @@ class DXBCContainer; #define D3D12_MSAA_SAMPLECOUNT 4 +enum ShaderDebugConstants +{ + MAX_SHADER_DEBUG_QUEUED_OPS = 128, + COUNT_SRVS_PER_DEBUG = 25, + COUNT_SAMPLERS_PER_DEBUG = 2, +}; + // baked indices in descriptor heaps enum CBVUAVSRVSlot { @@ -81,7 +88,8 @@ enum CBVUAVSRVSlot STENCIL_MSAA_SRV32x, FIRST_SHADDEBUG_SRV, - LAST_SHADDEBUG_SRV = FIRST_SHADDEBUG_SRV + 25, + LAST_SHADDEBUG_SRV = FIRST_SHADDEBUG_SRV + ShaderDebugConstants::COUNT_SRVS_PER_DEBUG * + ShaderDebugConstants::MAX_SHADER_DEBUG_QUEUED_OPS, FIRST_PIXELHISTORY_SRV, LAST_PIXELHISTORY_SRV = FIRST_PIXELHISTORY_SRV + 10, @@ -116,7 +124,8 @@ enum SamplerSlot FIRST_SAMP = POINT_SAMP, LINEAR_SAMP, SHADDEBUG_SAMPLER0, - SHADDEBUG_SAMPLER1, + LAST_SHADDEBUG_SAMPLER = SHADDEBUG_SAMPLER0 + ShaderDebugConstants::COUNT_SAMPLERS_PER_DEBUG * + ShaderDebugConstants::MAX_SHADER_DEBUG_QUEUED_OPS, }; enum DSVSlot @@ -152,11 +161,6 @@ public: D3D12DebugManager(WrappedID3D12Device *wrapper); ~D3D12DebugManager(); - enum - { - MAX_SHADER_DEBUG_QUEUED_OPS = 128 - }; - void GetBufferData(ID3D12Resource *buff, uint64_t offset, uint64_t length, bytebuf &retData); ID3D12Resource *MakeCBuffer(UINT64 size); diff --git a/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp b/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp index 539010c84..2f49fc475 100644 --- a/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp @@ -575,8 +575,8 @@ D3D12APIWrapper::D3D12APIWrapper(WrappedID3D12Device *device, const DXIL::Progra m_QueuedMathOpIndex(0), m_QueuedSampleGatherOpIndex(0), m_MathOpResultOffset(0), - m_MaxQueuedOps(D3D12DebugManager::MAX_SHADER_DEBUG_QUEUED_OPS), - m_SampleGatherOpResultsStart(D3D12DebugManager::MAX_SHADER_DEBUG_QUEUED_OPS * + m_MaxQueuedOps(ShaderDebugConstants::MAX_SHADER_DEBUG_QUEUED_OPS), + m_SampleGatherOpResultsStart(ShaderDebugConstants::MAX_SHADER_DEBUG_QUEUED_OPS * m_MathOpResultByteSize) { // Create the storage layout for the constant buffers @@ -1626,8 +1626,13 @@ bool D3D12APIWrapper::QueueMathIntrinsic(DXIL::DXOp dxOp, const ShaderVariable & return false; } - return D3D12ShaderDebug::QueueMathIntrinsic(false, m_Device, cmdList, mathOp, input, - m_QueuedMathOpIndex++); + if(D3D12ShaderDebug::QueueMathIntrinsic(false, m_Device, cmdList, mathOp, input, + m_QueuedMathOpIndex)) + { + m_QueuedMathOpIndex++; + return true; + } + return false; } // Must be called from the replay manager thread (the debugger thread) @@ -1682,10 +1687,15 @@ bool D3D12APIWrapper::QueueSampleGather(DXIL::DXOp dxOp, SampleGatherResourceDat const char *opString = ToStr(dxOp).c_str(); uint8_t swizzle[4] = {0, 1, 2, 3}; - return D3D12ShaderDebug::QueueSampleGather( - true, m_Device, m_QueuedOpCmdList, sampleOp, resourceData, samplerData, uv, ddxCalc, ddyCalc, - texelOffsets, multisampleIndex, lodValue, compareValue, swizzle, gatherChannel, m_ShaderType, - instructionIdx, opString, m_QueuedSampleGatherOpIndex++, sampleRetType); + if(D3D12ShaderDebug::QueueSampleGather( + true, m_Device, m_QueuedOpCmdList, sampleOp, resourceData, samplerData, uv, ddxCalc, + ddyCalc, texelOffsets, multisampleIndex, lodValue, compareValue, swizzle, gatherChannel, + m_ShaderType, instructionIdx, opString, m_QueuedSampleGatherOpIndex, sampleRetType)) + { + m_QueuedSampleGatherOpIndex++; + return true; + } + return false; } // Must be called from the replay manager thread (the debugger thread) diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index d93360534..b34575819 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -29,6 +29,7 @@ #include "driver/shaders/dxbc/dxbc_debug.h" #include "driver/shaders/dxil/dxil_debug.h" #include "maths/formatpacking.h" +#include "replay/common/var_dispatch_helpers.h" #include "strings/string_utils.h" #include "d3d12_command_queue.h" #include "d3d12_debug.h" @@ -252,6 +253,43 @@ bool D3D12ShaderDebug::QueueSampleGather( cbufferData.debugSampleLod = lodValue; cbufferData.debugSampleCompare = compareValue; + uint32_t srvStart = FIRST_SHADDEBUG_SRV; + srvStart += ShaderDebugConstants::COUNT_SRVS_PER_DEBUG * queueIndex; + CBVUAVSRVSlot srvSlot = (CBVUAVSRVSlot)srvStart; + D3D12_CPU_DESCRIPTOR_HANDLE srv = device->GetDebugManager()->GetCPUHandle(srvSlot); + srv.ptr += ((cbufferData.debugSampleTexDim - 1) + 5 * (cbufferData.debugSampleRetType - 1)) * + sizeof(D3D12Descriptor); + { + D3D12Descriptor descriptor = + FindDescriptor(device, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, resourceData.binding, shaderType); + + descriptor.Create(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, device, srv); + } + + uint32_t samplerStart = SHADDEBUG_SAMPLER0; + samplerStart += ShaderDebugConstants::COUNT_SAMPLERS_PER_DEBUG * queueIndex; + SamplerSlot samplerSlot = (SamplerSlot)samplerStart; + if(samplerData.mode != SamplerMode::NUM_SAMPLERS) + { + D3D12Descriptor descriptor = + FindDescriptor(device, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, samplerData.binding, shaderType); + + D3D12_CPU_DESCRIPTOR_HANDLE samp = device->GetDebugManager()->GetCPUHandle(samplerSlot); + + if(sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_CMP || sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_CMP_LEVEL_ZERO || + sampleOp == DEBUG_SAMPLE_TEX_GATHER4_CMP || sampleOp == DEBUG_SAMPLE_TEX_GATHER4_PO_CMP) + samp.ptr += sizeof(D3D12Descriptor); + + if((sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_BIAS || sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_CMP_BIAS) && + samplerData.bias != 0.0f) + { + D3D12_SAMPLER_DESC2 desc = descriptor.GetSampler(); + desc.MipLODBias = RDCCLAMP(desc.MipLODBias + samplerData.bias, -15.99f, 15.99f); + descriptor.Init(&desc); + } + descriptor.Create(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, device, samp); + } + // Store a copy of the event's render state to restore later D3D12RenderState &rs = device->GetQueue()->GetCommandData()->m_RenderState; D3D12RenderState prevState = rs; @@ -269,37 +307,6 @@ bool D3D12ShaderDebug::QueueSampleGather( rs.scissors.clear(); rs.scissors.push_back({0, 0, 1, 1}); - D3D12_CPU_DESCRIPTOR_HANDLE srv = device->GetDebugManager()->GetCPUHandle(FIRST_SHADDEBUG_SRV); - srv.ptr += ((cbufferData.debugSampleTexDim - 1) + 5 * (cbufferData.debugSampleRetType - 1)) * - sizeof(D3D12Descriptor); - { - D3D12Descriptor descriptor = - FindDescriptor(device, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, resourceData.binding, shaderType); - - descriptor.Create(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, device, srv); - } - - if(samplerData.mode != SamplerMode::NUM_SAMPLERS) - { - D3D12Descriptor descriptor = - FindDescriptor(device, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, samplerData.binding, shaderType); - - D3D12_CPU_DESCRIPTOR_HANDLE samp = device->GetDebugManager()->GetCPUHandle(SHADDEBUG_SAMPLER0); - - if(sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_CMP || sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_CMP_LEVEL_ZERO || - sampleOp == DEBUG_SAMPLE_TEX_GATHER4_CMP || sampleOp == DEBUG_SAMPLE_TEX_GATHER4_PO_CMP) - samp.ptr += sizeof(D3D12Descriptor); - - if((sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_BIAS || sampleOp == DEBUG_SAMPLE_TEX_SAMPLE_CMP_BIAS) && - samplerData.bias != 0.0f) - { - D3D12_SAMPLER_DESC2 desc = descriptor.GetSampler(); - desc.MipLODBias = RDCCLAMP(desc.MipLODBias + samplerData.bias, -15.99f, 15.99f); - descriptor.Init(&desc); - } - descriptor.Create(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, device, samp); - } - device->GetDebugManager()->SetDescriptorHeaps(rs.heaps, true, true); // Set our modified root signature, and transfer sigelems if we're debugging a compute shader @@ -315,10 +322,9 @@ bool D3D12ShaderDebug::QueueSampleGather( D3D12RenderState::SignatureElement( eRootCBV, device->GetDebugManager()->UploadConstants(&cbufferData, sizeof(cbufferData))), D3D12RenderState::SignatureElement(eRootUAV, pResultBuffer->GetGPUVirtualAddress()), - D3D12RenderState::SignatureElement( - eRootTable, device->GetDebugManager()->GetCPUHandle(FIRST_SHADDEBUG_SRV)), - D3D12RenderState::SignatureElement( - eRootTable, device->GetDebugManager()->GetCPUHandle(SHADDEBUG_SAMPLER0)), + D3D12RenderState::SignatureElement(eRootTable, device->GetDebugManager()->GetCPUHandle(srvSlot)), + D3D12RenderState::SignatureElement(eRootTable, + device->GetDebugManager()->GetCPUHandle(samplerSlot)), }; rs.topo = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; @@ -335,7 +341,7 @@ bool D3D12ShaderDebug::QueueSampleGather( barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; cmdList->ResourceBarrier(1, &barrier); - const uint64_t sampleGatherOpResultsStart(D3D12DebugManager::MAX_SHADER_DEBUG_QUEUED_OPS * + const uint64_t sampleGatherOpResultsStart(ShaderDebugConstants::MAX_SHADER_DEBUG_QUEUED_OPS * s_MathOpResultByteSize); uint64_t destOffset = sampleGatherOpResultsStart + queueIndex * s_SampleGatherOpResultByteSize; @@ -408,7 +414,7 @@ bool D3D12ShaderDebug::GetQueuedResults(WrappedID3D12Device *device, gpuMathOpResults += s_MathOpResultByteSize; } - const uint64_t sampleGatherOpResultsStart(D3D12DebugManager::MAX_SHADER_DEBUG_QUEUED_OPS * + const uint64_t sampleGatherOpResultsStart(ShaderDebugConstants::MAX_SHADER_DEBUG_QUEUED_OPS * s_MathOpResultByteSize); byte *gpuSampleGatherOpResults = gpuResults + sampleGatherOpResultsStart; for(uint32_t s = 0; s < sampleGatherResults.size(); ++s) @@ -564,8 +570,8 @@ D3D12Descriptor D3D12ShaderDebug::FindDescriptor(WrappedID3D12Device *device, srvDesc.Format = DXGI_FORMAT_UNKNOWN; srvDesc.Buffer.FirstElement = 0; // we don't know the real length or structure stride from a root descriptor, so set - // defaults. This behaviour seems undefined in drivers, so returning 1 as the number - // of elements is as sensible as anything else + // defaults. This behaviour seems undefined in drivers, so returning 1 as the number of + // elements is as sensible as anything else srvDesc.Buffer.NumElements = 1; srvDesc.Buffer.StructureByteStride = 4; srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE; @@ -586,8 +592,8 @@ D3D12Descriptor D3D12ShaderDebug::FindDescriptor(WrappedID3D12Device *device, uavDesc.Format = DXGI_FORMAT_UNKNOWN; uavDesc.Buffer.FirstElement = 0; // we don't know the real length or structure stride from a root descriptor, so set - // defaults. This behaviour seems undefined in drivers, so returning 1 as the number - // of elements is as sensible as anything else + // defaults. This behaviour seems undefined in drivers, so returning 1 as the number of + // elements is as sensible as anything else uavDesc.Buffer.NumElements = 1; uavDesc.Buffer.StructureByteStride = 4; uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE; @@ -607,9 +613,8 @@ D3D12Descriptor D3D12ShaderDebug::FindDescriptor(WrappedID3D12Device *device, { const D3D12_DESCRIPTOR_RANGE1 &range = param.ranges[r]; - // For every range, check the number of descriptors so that we are accessing the - // correct data for append descriptor tables, even if the range type doesn't match - // what we need to fetch + // For every range, check the number of descriptors so that we are accessing the correct + // data for append descriptor tables, even if the range type doesn't match what we need to fetch UINT offset = range.OffsetInDescriptorsFromTableStart; if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) offset = prevTableOffset; @@ -620,8 +625,8 @@ D3D12Descriptor D3D12ShaderDebug::FindDescriptor(WrappedID3D12Device *device, // Find out how many descriptors are left after numDescriptors = heap->GetNumDescriptors() - offset - (UINT)element.offset; - // TODO: Should we look up the bind point in the D3D12 state to try to get - // a better guess at the number of descriptors? + // TODO: Should we look up the bind point in the D3D12 state to try to get a better + // guess at the number of descriptors? } prevTableOffset = offset + numDescriptors; @@ -890,8 +895,7 @@ ShaderVariable D3D12ShaderDebug::GetResourceInfo(WrappedID3D12Device *device, case D3D12_SRV_DIMENSION_TEXTURECUBE: case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: { - // Even though it's a texture cube, an individual face's dimensions are - // returned + // Even though it's a texture cube, an individual face's dimensions are returned dim = 2; bool isarray = srvDesc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; @@ -899,8 +903,8 @@ ShaderVariable D3D12ShaderDebug::GetResourceInfo(WrappedID3D12Device *device, result.value.u32v[0] = RDCMAX(1U, (uint32_t)(resDesc.Width >> mipLevel)); result.value.u32v[1] = RDCMAX(1U, (uint32_t)(resDesc.Height >> mipLevel)); - // the spec says "If srcResource is a TextureCubeArray, [...]. dest.z is set - // to an undefined value." + // the spec says + // "If srcResource is a TextureCubeArray, [...]. dest.z is set to an undefined value." // but that's stupid, and implementations seem to return the number of cubes result.value.u32v[2] = isarray ? srvDesc.TextureCubeArray.NumCubes : 0; result.value.u32v[3] = @@ -1061,8 +1065,8 @@ D3D12DebugAPIWrapper::D3D12DebugAPIWrapper(WrappedID3D12Device *device, D3D12DebugAPIWrapper::~D3D12DebugAPIWrapper() { - // if we replayed to before the action for fetching some UAVs, replay back to after the action - // to keep the state consistent. + // if we replayed to before the action for fetching some UAVs, replay back to after the action to + // keep the state consistent. if(m_DidReplay) { D3D12MarkerRegion region(m_pDevice->GetQueue()->GetReal(), "ResetReplay"); @@ -1123,17 +1127,15 @@ void D3D12DebugAPIWrapper::FetchSRV(const DXBCDebug::BindingSlot &slot) { D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); - // DXBC allows root buffers to have a stride of up to 16 bytes in the shader, which - // means encoding the byte offset into the first element here is wrong without - // knowing what the actual accessed stride is. Instead we only fetch the data from - // that offset onwards. + // DXBC allows root buffers to have a stride of up to 16 bytes in the shader, which means + // encoding the byte offset into the first element here is wrong without knowing what + // the actual accessed stride is. Instead we only fetch the data from that offset onwards. // 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. DXBCDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, srvData.format); srvData.firstElement = 0; - // root arguments have no bounds checking, so use the most conservative number of - // elements + // root arguments have no bounds checking, so use the most conservative number of elements srvData.numElements = uint32_t(resDesc.Width - element.offset); if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) @@ -1156,9 +1158,8 @@ void D3D12DebugAPIWrapper::FetchSRV(const DXBCDebug::BindingSlot &slot) { const D3D12_DESCRIPTOR_RANGE1 &range = param.ranges[r]; - // For every range, check the number of descriptors so that we are accessing the - // correct data for append descriptor tables, even if the range type doesn't match - // what we need to fetch + // For every range, check the number of descriptors so that we are accessing the correct + // data for append descriptor tables, even if the range type doesn't match what we need to fetch UINT offset = range.OffsetInDescriptorsFromTableStart; if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) offset = prevTableOffset; @@ -1173,8 +1174,8 @@ void D3D12DebugAPIWrapper::FetchSRV(const DXBCDebug::BindingSlot &slot) // Find out how many descriptors are left after numDescriptors = heap->GetNumDescriptors() - offset - (UINT)element.offset; - // TODO: Should we look up the bind point in the D3D12 state to try to get - // a better guess at the number of descriptors? + // TODO: Should we look up the bind point in the D3D12 state to try to get a better + // guess at the number of descriptors? } prevTableOffset = offset + numDescriptors; @@ -1297,17 +1298,15 @@ void D3D12DebugAPIWrapper::FetchUAV(const DXBCDebug::BindingSlot &slot) { D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); - // DXBC allows root buffers to have a stride of up to 16 bytes in the shader, which - // means encoding the byte offset into the first element here is wrong without - // knowing what the actual accessed stride is. Instead we only fetch the data from - // that offset onwards. + // DXBC allows root buffers to have a stride of up to 16 bytes in the shader, which means + // encoding the byte offset into the first element here is wrong without knowing what + // the actual accessed stride is. Instead we only fetch the data from that offset onwards. // 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. DXBCDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, uavData.format); uavData.firstElement = 0; - // root arguments have no bounds checking, so use the most conservative number of - // elements + // root arguments have no bounds checking, so use the most conservative number of elements uavData.numElements = uint32_t(resDesc.Width - element.offset); if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) @@ -1451,7 +1450,14 @@ bool D3D12DebugAPIWrapper::CalculateMathIntrinsic(DXBCBytecode::OpcodeType opcod const uint32_t queueIndex = 0; if(!D3D12ShaderDebug::QueueMathIntrinsic(false, m_pDevice, m_QueuedOpCmdList, mathOp, input, queueIndex)) + { + HRESULT hr = m_QueuedOpCmdList->Close(); + if(FAILED(hr)) + RDCERR("Failed to close command list HRESULT: %s", ToStr(hr).c_str()); + + m_QueuedOpCmdList = NULL; return false; + } rdcarray mathOpResults; mathOpResults.push_back(&output1); @@ -1586,7 +1592,15 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( false, m_pDevice, m_QueuedOpCmdList, sampleOp, resourceData, samplerData, uv, ddxCalc, ddyCalc, texelOffsets, multisampleIndex, lodOrCompareValue, lodOrCompareValue, swizzle, gatherChannel, GetShaderType(), m_instruction, opString, queueIndex, sampleRetType)) - return false; + { + HRESULT hr = m_QueuedOpCmdList->Close(); + if(FAILED(hr)) + RDCERR("Failed to close command list HRESULT: %s", ToStr(hr).c_str()); + + m_QueuedOpCmdList = NULL; + set0001(output); + return true; + } rdcarray mathOpResults; rdcarray sampleGatherResults; @@ -3048,11 +3062,11 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t return new ShaderDebugTrace; } - // if we encounter multiple hits at our destination pixel co-ord (or any other) we check to see - // if a specific primitive was requested (via primitive parameter not being set to ~0U). If it - // was, debug that pixel, otherwise do a best-estimate of which fragment was the last to - // successfully depth test and debug that, just by checking if the depth test is ordered and - // picking the final fragment in the series + // if we encounter multiple hits at our destination pixel co-ord (or any other) we check to see if + // a specific primitive was requested (via primitive parameter not being set to ~0U). If it was, + // debug that pixel, otherwise do a best-estimate of which fragment was the last to successfully + // depth test and debug that, just by checking if the depth test is ordered and picking the final + // fragment in the series // Get depth func and determine "winner" pixel DXDebug::DebugHit *pWinnerHit = NULL; @@ -3853,9 +3867,9 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId, ShaderVariable(rdcstr(), groupid[0], groupid[1], groupid[2], 0U); // if we have workgroup scope that means we need to simulate the whole workgroup but don't - // have subgroup ops. We assume the layout of this is irrelevant and don't attempt to read - // it back from the GPU like we do with subgroups. We lay things out in plain linear order, - // along X and then Y and then Z, with groups iterated together. + // have subgroup ops. We assume the layout of this is irrelevant and don't attempt to read it + // back from the GPU like we do with subgroups. We lay things out in plain linear order, along + // X and then Y and then Z, with groups iterated together. uint32_t i = 0; for(uint32_t tz = 0; tz < threadDim[2]; tz++)