Handle overlap between UAVs/RTVs when 'keeping' one or the other

* OMSetRenderTargetsAndUnorderedAccessViews can 'keep' either RTVs and
  UAVs and bind the other type when being called, but it's legal to
  'keep' UAVs and bind more RTVs than were there before, or else 'keep'
  RTVs and bind UAVs at an earlier start slot than before.
* In each of these cases, any conflicting older binds are unbound, so
  for UAVs this means we unbound one or more from the start slot, and
  move the start slot up. For RTVs we just unbind any old RTVs that
  overlap with the new UAV start slot.
This commit is contained in:
Baldur Karlsson
2018-03-12 11:16:20 +00:00
parent 43ed987214
commit 62660ce096
+61 -5
View File
@@ -3223,9 +3223,23 @@ bool WrappedID3D11DeviceContext::Serialise_OMSetRenderTargetsAndUnorderedAccessV
if(ModifyRTVs)
{
ID3D11UnorderedAccessView *const *srcUAVs =
ModifyUAVs ? ppUnorderedAccessViews : m_CurrentPipelineState->OM.UAVs;
UINT srcUAVcount = ModifyUAVs ? NumUAVs : D3D11_1_UAV_SLOT_COUNT;
ID3D11UnorderedAccessView *const *srcUAVs = ppUnorderedAccessViews;
UINT srcUAVcount = NumUAVs;
if(!ModifyUAVs)
{
srcUAVs = m_CurrentPipelineState->OM.UAVs;
srcUAVcount = D3D11_1_UAV_SLOT_COUNT;
// if we're not modifying the UAVs but NumRTVs > oldUAVStartSlot then we unbind any
// overlapped UAVs.
if(NumRTVs > m_CurrentPipelineState->OM.UAVStartSlot)
{
UINT diff = NumRTVs - m_CurrentPipelineState->OM.UAVStartSlot;
srcUAVcount -= diff;
srcUAVs += diff;
}
}
if(m_CurrentPipelineState->ValidOutputMerger(ppRenderTargetViews, NumRTVs, pDepthStencilView,
srcUAVs, srcUAVcount))
@@ -3234,6 +3248,37 @@ bool WrappedID3D11DeviceContext::Serialise_OMSetRenderTargetsAndUnorderedAccessV
D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.DepthView,
pDepthStencilView);
if(!ModifyUAVs)
{
// set UAVStartSlot to NumRTVs
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, NumRTVs);
if(NumRTVs > m_CurrentPipelineState->OM.UAVStartSlot)
{
UINT diff = NumRTVs - m_CurrentPipelineState->OM.UAVStartSlot;
// release and unbind any UAVs that were unbound
for(UINT i = 0; i < diff; i++)
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs[i],
(ID3D11UnorderedAccessView *)NULL);
// move the array down *without* changing any refs
for(UINT i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++)
{
if(i < D3D11_1_UAV_SLOT_COUNT - diff)
{
m_CurrentPipelineState->OM.UAVs[i] = m_CurrentPipelineState->OM.UAVs[i + diff];
}
else
{
// NULL without ref'ing, since we just moved this down lower in the array
m_CurrentPipelineState->OM.UAVs[i] = NULL;
}
}
}
}
}
}
@@ -3241,18 +3286,29 @@ bool WrappedID3D11DeviceContext::Serialise_OMSetRenderTargetsAndUnorderedAccessV
{
bool valid = false;
if(ModifyRTVs)
{
valid = m_CurrentPipelineState->ValidOutputMerger(
ppRenderTargetViews, NumRTVs, pDepthStencilView, ppUnorderedAccessViews, NumUAVs);
}
else
{
// if we're not modifying RTVs, any that are < UAVStartSlot get unbound so don't consider
// for validity
valid = m_CurrentPipelineState->ValidOutputMerger(
m_CurrentPipelineState->OM.RenderTargets, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT,
m_CurrentPipelineState->OM.RenderTargets, UAVStartSlot,
m_CurrentPipelineState->OM.DepthView, ppUnorderedAccessViews, NumUAVs);
}
if(valid)
{
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs, UAVs, 0,
D3D11_1_UAV_SLOT_COUNT);
m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, UAVStartSlot);
// unbind any conflicting RTVS
for(UINT i = UAVStartSlot; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets[i],
(ID3D11RenderTargetView *)NULL);
}
}
@@ -7658,4 +7714,4 @@ void WrappedID3D11DeviceContext::Unmap(ID3D11Resource *pResource, UINT Subresour
func(WriteSerialiser &ser, __VA_ARGS__));
SERIALISED_ID3D11CONTEXT_FUNCTIONS();
SERIALISED_ID3D11CONTEXT_MARKER_FUNCTIONS();
SERIALISED_ID3D11CONTEXT_MARKER_FUNCTIONS();