From 9271dde9e8ceffc9158206cf18500318df6b0d80 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Wed, 27 Nov 2024 07:22:18 +0000 Subject: [PATCH] D3D12 Pixel History do not crash when processing an unknown fragment This could happen with non-deterministic replay --- renderdoc/driver/d3d12/d3d12_pixelhistory.cpp | 83 +++++++++++-------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_pixelhistory.cpp b/renderdoc/driver/d3d12/d3d12_pixelhistory.cpp index e4c0aee31..e1e1ffbc9 100644 --- a/renderdoc/driver/d3d12/d3d12_pixelhistory.cpp +++ b/renderdoc/driver/d3d12/d3d12_pixelhistory.cpp @@ -2416,6 +2416,7 @@ struct D3D12PixelHistoryPerFragmentCallback : D3D12PixelHistoryCallback void PreCloseCommandList(ID3D12GraphicsCommandListX *cmd) {} void AliasEvent(uint32_t primary, uint32_t alias) {} + bool ContainsEvent(uint32_t eid) { return (m_EventIndices.count(eid) > 0); } uint32_t GetEventOffset(uint32_t eid) { auto it = m_EventIndices.find(eid); @@ -3107,14 +3108,22 @@ rdcarray D3D12Replay::PixelHistory(rdcarray event uint32_t eid = history[h].eventId; if(eventsWithFrags.find(eid) == eventsWithFrags.end()) continue; - uint32_t f = history[h].fragIndex; - bool someFragsClipped = (history[h].primitiveID == 1); - int32_t primId = fragInfo[perFragmentCB.GetEventOffset(eid) + f].primitiveID; - history[h].primitiveID = primId; - if(someFragsClipped) + if(perFragmentCB.ContainsEvent(eid)) { - discardedPrimsEvents[eid].push_back(primId); - primitivesToCheck++; + uint32_t f = history[h].fragIndex; + bool someFragsClipped = (history[h].primitiveID == 1); + int32_t primId = fragInfo[perFragmentCB.GetEventOffset(eid) + f].primitiveID; + history[h].primitiveID = primId; + if(someFragsClipped) + { + discardedPrimsEvents[eid].push_back(primId); + primitivesToCheck++; + } + } + else + { + RDCWARN("Failed to find fragment data for event %d", eid); + eventsWithFrags.erase(eid); } } @@ -3167,37 +3176,45 @@ rdcarray D3D12Replay::PixelHistory(rdcarray event history[h].postMod = history[h - 1].postMod; continue; } - uint32_t offset = perFragmentCB.GetEventOffset(eid) + f - discardOffset; - if(multisampled) - memcpy(history[h].shaderOut.col.floatValue.data(), &fragInfo[offset].shaderOut.color[0], - history[h].shaderOut.col.floatValue.byteSize()); - else - FillInColor(shaderOutFormat, fragInfo[offset].shaderOut, history[h].shaderOut); - - if(multisampled) - history[h].shaderOut.depth = fragInfo[offset].shaderOut.depth.fdepth; - else - history[h].shaderOut.depth = - GetDepthValue(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, fragInfo[offset].shaderOut); - - if((h < history.size() - 1) && (history[h].eventId == history[h + 1].eventId)) + if(perFragmentCB.ContainsEvent(eid)) { - // Get post-modification value if this is not the last fragment for the event. - ConvertAndFillInColor(shaderOutFormat, fragInfo[offset].postMod, fmt, history[h].postMod); - - // MSAA depth is expanded out to floats in the compute shader + uint32_t offset = perFragmentCB.GetEventOffset(eid) + f - discardOffset; if(multisampled) - history[h].postMod.depth = fragInfo[offset].postMod.depth.fdepth; + memcpy(history[h].shaderOut.col.floatValue.data(), &fragInfo[offset].shaderOut.color[0], + history[h].shaderOut.col.floatValue.byteSize()); else - history[h].postMod.depth = - GetDepthValue(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, fragInfo[offset].postMod); - history[h].postMod.stencil = -2; + FillInColor(shaderOutFormat, fragInfo[offset].shaderOut, history[h].shaderOut); + + if(multisampled) + history[h].shaderOut.depth = fragInfo[offset].shaderOut.depth.fdepth; + else + history[h].shaderOut.depth = + GetDepthValue(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, fragInfo[offset].shaderOut); + + if((h < history.size() - 1) && (history[h].eventId == history[h + 1].eventId)) + { + // Get post-modification value if this is not the last fragment for the event. + ConvertAndFillInColor(shaderOutFormat, fragInfo[offset].postMod, fmt, history[h].postMod); + + // MSAA depth is expanded out to floats in the compute shader + if(multisampled) + history[h].postMod.depth = fragInfo[offset].postMod.depth.fdepth; + else + history[h].postMod.depth = + GetDepthValue(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, fragInfo[offset].postMod); + history[h].postMod.stencil = -2; + } + // If it is not the first fragment for the event, set the preMod to the + // postMod of the previous fragment. + if(h > 0 && (history[h].eventId == history[h - 1].eventId)) + { + history[h].preMod = history[h - 1].postMod; + } } - // If it is not the first fragment for the event, set the preMod to the - // postMod of the previous fragment. - if(h > 0 && (history[h].eventId == history[h - 1].eventId)) + else { - history[h].preMod = history[h - 1].postMod; + RDCWARN("Failed to find fragment data for event %d", eid); + eventsWithFrags.erase(eid); } }