Fix access to render state in D3D12

* We need to copy the external-facing m_RenderState into the partial command
  buffer's state for partial replay, in case it was modified externally.
* Also when accessing the render state inside a drawcall callback we need to use
  the command buffer's local state, not m_RenderState which isn't updated until
  the replay completes.
This commit is contained in:
baldurk
2020-07-14 14:08:54 +01:00
parent ec6627af03
commit 1df39247fa
6 changed files with 32 additions and 10 deletions
@@ -543,14 +543,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetViewInstanceMask(SerialiserT
m_Cmd->m_LastCmdListID = GetResourceManager()->GetOriginalID(GetResID(pCommandList));
bool stateUpdate = false;
if(IsActiveReplaying(m_State))
{
if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID))
{
Unwrap1(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->SetViewInstanceMask(Mask);
if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID))
m_Cmd->m_RenderState.viewInstMask = Mask;
stateUpdate = true;
}
else if(!m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID))
{
stateUpdate = true;
}
}
else
@@ -558,8 +563,11 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetViewInstanceMask(SerialiserT
Unwrap1(pCommandList)->SetViewInstanceMask(Mask);
GetCrackedList1()->SetViewInstanceMask(Mask);
m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].state.viewInstMask = Mask;
stateUpdate = true;
}
if(stateUpdate)
m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].state.viewInstMask = Mask;
}
return true;
+5
View File
@@ -241,6 +241,11 @@ struct D3D12CommandData
D3D12RenderState m_RenderState;
D3D12RenderState &GetCurRenderState()
{
return m_LastCmdListID == ResourceId() ? m_RenderState
: m_BakedCmdListInfo[m_LastCmdListID].state;
}
enum PartialReplayIndex
{
Primary,
+8 -3
View File
@@ -3470,6 +3470,12 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,
cmd.m_RenderState.m_ResourceManager = GetResourceManager();
cmd.m_RenderState.m_DebugManager = m_Replay->GetDebugManager();
}
else
{
// Copy the state in case m_RenderState was modified externally for the partial replay.
cmd.m_BakedCmdListInfo[cmd.m_Partial[D3D12CommandData::Primary].partialParent].state =
cmd.m_RenderState;
}
// we'll need our own command list if we're replaying just a subsection
// of events within a single command list record - always if it's only
@@ -3506,9 +3512,8 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,
cmd.m_OutsideCmdList = NULL;
}
if(!partial)
cmd.m_RenderState =
cmd.m_BakedCmdListInfo[cmd.m_Partial[D3D12CommandData::Primary].partialParent].state;
cmd.m_RenderState =
cmd.m_BakedCmdListInfo[cmd.m_Partial[D3D12CommandData::Primary].partialParent].state;
#if ENABLED(SINGLE_FLUSH_VALIDATE)
FlushLists(true);
+3 -3
View File
@@ -66,7 +66,7 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback
// and substitute our quad calculation fragment shader that writes to a storage image
// that is bound in a new root signature element.
D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState;
D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->GetCurRenderState();
m_PrevState = rs;
// check cache first
@@ -181,10 +181,10 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback
return false;
// restore the render state and go ahead with the real draw
m_pDevice->GetQueue()->GetCommandData()->m_RenderState = m_PrevState;
m_pDevice->GetQueue()->GetCommandData()->GetCurRenderState() = m_PrevState;
RDCASSERT(cmd);
m_pDevice->GetQueue()->GetCommandData()->m_RenderState.ApplyState(m_pDevice, cmd);
m_pDevice->GetQueue()->GetCommandData()->GetCurRenderState().ApplyState(m_pDevice, cmd);
return true;
}
+1 -1
View File
@@ -173,7 +173,7 @@ void D3D12Replay::InitPostVSBuffers(uint32_t eventId)
D3D12MarkerRegion postvs(m_pDevice->GetQueue(), StringFormat::Fmt("PostVS for %u", eventId));
D3D12CommandData *cmd = m_pDevice->GetQueue()->GetCommandData();
const D3D12RenderState &rs = cmd->m_RenderState;
const D3D12RenderState &rs = cmd->GetCurRenderState();
if(rs.pipe == ResourceId())
return;
+4
View File
@@ -362,6 +362,8 @@ class Overlay_Test(rdtest.TestCase):
rdtest.log.success("Picked pixels are as expected for {}".format(str(overlay)))
rdtest.log.success("All normal overlays are as expected")
# Now check clear-before-X by hand, for colour and for depth
depth_tex: rd.ResourceId = pipe.GetDepthTarget().resourceId
@@ -387,6 +389,8 @@ class Overlay_Test(rdtest.TestCase):
self.check_pixel_value(depth_tex, 250, 250, [0.95, 0.0/255.0, 0.0, 1.0], eps=eps)
self.check_pixel_value(depth_tex, 50, 50, [1.0, 0.0/255.0, 0.0, 1.0], eps=eps)
rdtest.log.success("Colour and depth at end are correct")
# Check clear before pass
tex.resourceId = col_tex
tex.overlay = rd.DebugOverlay.ClearBeforePass