From 249638820f6755b576979c655fd20d4e27d3ab49 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 11 Jan 2015 01:53:32 +0000 Subject: [PATCH] Tweak render state invalid output merger handling, and log warnings * We were allowing *any* difference between depth and render targets, but that's not quite right. Oversized depth is fine, but e.g. mismatched multisampled and not is invalid. * We also take frame references on invalid attempted OM sets, so that the targets don't get trimmed from the log and potentially make the set valid --- renderdoc/driver/d3d11/d3d11_context.cpp | 2 + renderdoc/driver/d3d11/d3d11_context_wrap.cpp | 46 +++++++++++++++++ renderdoc/driver/d3d11/d3d11_device.cpp | 2 + renderdoc/driver/d3d11/d3d11_renderstate.cpp | 51 ++++++++++++++++--- renderdoc/driver/d3d11/d3d11_renderstate.h | 1 + 5 files changed, 94 insertions(+), 8 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index f7d0c3dc3..47a98d142 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -165,6 +165,7 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device* real } else { + m_CurrentPipelineState->SetDevice(m_pDevice); m_pDevice->SoftRef(); if(m_State >= WRITING && RenderDoc::Inst().GetCaptureOptions().CaptureAllCmdLists) @@ -229,6 +230,7 @@ bool WrappedID3D11DeviceContext::Serialise_BeginCaptureFrame(bool applyInitialSt m_DoStateVerify = false; { *m_CurrentPipelineState = state; + m_CurrentPipelineState->SetDevice(m_pDevice); state.ApplyState(this); } m_DoStateVerify = true; diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index 1c98f01cf..75640d44b 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -2910,6 +2910,29 @@ void WrappedID3D11DeviceContext::OMSetRenderTargets(UINT NumViews, ID3D11RenderT m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.DepthView, pDepthStencilView); m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.UAVStartSlot, NumViews); } + else if(m_State >= WRITING) + { + // make sure to mark resources referenced if the OM state is invalid, so they aren't eliminated from the + // log (which might make this combination valid on replay without some of the targets!) + for(UINT i=0; i < NumViews; i++) + { + if(ppRenderTargetViews && ppRenderTargetViews[i]) + { + ID3D11Resource *res = NULL; + ppRenderTargetViews[i]->GetResource(&res); + MarkResourceReferenced(GetIDForResource(res), eFrameRef_Read); + SAFE_RELEASE(res); + } + } + + if(pDepthStencilView) + { + ID3D11Resource *res = NULL; + pDepthStencilView->GetResource(&res); + MarkResourceReferenced(GetIDForResource(res), eFrameRef_Read); + SAFE_RELEASE(res); + } + } ID3D11UnorderedAccessView *UAVs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0}; m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.UAVs, UAVs, 0, D3D11_PS_CS_UAV_REGISTER_COUNT); @@ -3086,6 +3109,29 @@ void WrappedID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(UINT m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.RenderTargets, RTs, 0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT); m_CurrentPipelineState->ChangeRefWrite(m_CurrentPipelineState->OM.DepthView, pDepthStencilView); } + else if(m_State >= WRITING) + { + // make sure to mark resources referenced if the OM state is invalid, so they aren't eliminated from the + // log (which might make this combination valid on replay without some of the targets!) + for(UINT i=0; i < NumRTVs; i++) + { + if(ppRenderTargetViews && ppRenderTargetViews[i]) + { + ID3D11Resource *res = NULL; + ppRenderTargetViews[i]->GetResource(&res); + MarkResourceReferenced(GetIDForResource(res), eFrameRef_Read); + SAFE_RELEASE(res); + } + } + + if(pDepthStencilView) + { + ID3D11Resource *res = NULL; + pDepthStencilView->GetResource(&res); + MarkResourceReferenced(GetIDForResource(res), eFrameRef_Read); + SAFE_RELEASE(res); + } + } } if(NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index ec11b42e8..c8d58bb3b 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -2234,6 +2234,8 @@ void WrappedID3D11Device::ReplayLog(uint32_t frameID, uint32_t startEventID, uin GetResourceManager()->ApplyInitialContents(); GetResourceManager()->ReleaseInFrameResources(); } + + m_State = EXECUTING; if(m_ReplayDefCtx == ResourceId()) { diff --git a/renderdoc/driver/d3d11/d3d11_renderstate.cpp b/renderdoc/driver/d3d11/d3d11_renderstate.cpp index ec07ea697..b3af98b02 100644 --- a/renderdoc/driver/d3d11/d3d11_renderstate.cpp +++ b/renderdoc/driver/d3d11/d3d11_renderstate.cpp @@ -1272,6 +1272,8 @@ bool D3D11RenderState::ValidOutputMerger(ID3D11RenderTargetView **RTs, ID3D11Dep if(renderdim[i] != dim) { valid = false; + m_pDevice->AddDebugMessage(eDbgCategory_State_Setting, eDbgSeverity_High, eDbgSource_IncorrectAPIUse, + "Invalid output merger - Render targets of different type"); break; } } @@ -1280,6 +1282,8 @@ bool D3D11RenderState::ValidOutputMerger(ID3D11RenderTargetView **RTs, ID3D11Dep dim != D3D11_RESOURCE_DIMENSION_UNKNOWN && depthdim != dim) { + m_pDevice->AddDebugMessage(eDbgCategory_State_Setting, eDbgSeverity_High, eDbgSource_IncorrectAPIUse, + "Invalid output merger - Render target(s) and depth target of different type"); valid = false; } @@ -1368,6 +1372,8 @@ bool D3D11RenderState::ValidOutputMerger(ID3D11RenderTargetView **RTs, ID3D11Dep desc2.SampleDesc.Count != d2.SampleDesc.Count || desc2.SampleDesc.Quality != d2.SampleDesc.Quality) { + m_pDevice->AddDebugMessage(eDbgCategory_State_Setting, eDbgSeverity_High, eDbgSource_IncorrectAPIUse, + "Invalid output merger - Render targets are different dimensions"); valid = false; break; } @@ -1392,19 +1398,37 @@ bool D3D11RenderState::ValidOutputMerger(ID3D11RenderTargetView **RTs, ID3D11Dep else if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) { ((ID3D11Texture2D *)DepthResource)->GetDesc(&d2); - d3.Width = RDCMAX(1U, d2.Width >> DepthDesc.Texture2D.MipSlice); - d3.Height = RDCMAX(1U, d2.Height >> DepthDesc.Texture2D.MipSlice); if(DepthDesc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2D) + { + d3.Width = RDCMAX(1U, d2.Width >> DepthDesc.Texture2D.MipSlice); + d3.Height = RDCMAX(1U, d2.Height >> DepthDesc.Texture2D.MipSlice); d3.Depth = 1; + } else if(DepthDesc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2DARRAY) + { + d3.Width = RDCMAX(1U, d2.Width >> DepthDesc.Texture2DArray.MipSlice); + d3.Height = RDCMAX(1U, d2.Height >> DepthDesc.Texture2DArray.MipSlice); d3.Depth = RDCMIN(d2.ArraySize, DepthDesc.Texture2DArray.ArraySize); + } + else if(DepthDesc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2DMS) + { + d3.Width = d2.Width; + d3.Height = d2.Height; + d3.Depth = 1; + } else if(DepthDesc.ViewDimension == D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY) + { + d3.Width = d2.Width; + d3.Height = d2.Height; d3.Depth = RDCMIN(d2.ArraySize, DepthDesc.Texture2DMSArray.ArraySize); + } } else if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D || dim == D3D11_RESOURCE_DIMENSION_BUFFER) { + m_pDevice->AddDebugMessage(eDbgCategory_State_Setting, eDbgSeverity_High, eDbgSource_IncorrectAPIUse, + "Invalid output merger - Depth target is Texture3D or Buffer (shouldn't be possible! How did you create this view?!)"); valid = false; } @@ -1417,15 +1441,26 @@ bool D3D11RenderState::ValidOutputMerger(ID3D11RenderTargetView **RTs, ID3D11Dep desc2.SampleDesc.Quality != d2.SampleDesc.Quality) { valid = false; + + // explicitly allow over-sized depth targets + if(desc.Width < d3.Width && + desc.Height < d3.Height && + desc.Depth < d3.Depth && + desc2.SampleDesc.Count == d2.SampleDesc.Count && + desc2.SampleDesc.Quality == d2.SampleDesc.Quality) + { + valid = true; + m_pDevice->AddDebugMessage(eDbgCategory_State_Setting, eDbgSeverity_High, eDbgSource_IncorrectAPIUse, + "Valid but unusual output merger - Depth target is larger than render target(s)"); + } + else + { + m_pDevice->AddDebugMessage(eDbgCategory_State_Setting, eDbgSeverity_High, eDbgSource_IncorrectAPIUse, + "Invalid output merger - Depth target is different size or MS count to render target(s)"); + } } } } - - if(!valid) - { - //RDCDEBUG("Different effective dimensions between output views"); - valid = true; - } } for(int i=0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) diff --git a/renderdoc/driver/d3d11/d3d11_renderstate.h b/renderdoc/driver/d3d11/d3d11_renderstate.h index 710f33566..e9d74b4d8 100644 --- a/renderdoc/driver/d3d11/d3d11_renderstate.h +++ b/renderdoc/driver/d3d11/d3d11_renderstate.h @@ -421,6 +421,7 @@ struct D3D11RenderState void Serialise(LogState state, WrappedID3D11Device *device); void SetImmediatePipeline(WrappedID3D11Device *device) { m_ImmediatePipeline = true; m_pDevice = device; } + void SetDevice(WrappedID3D11Device *device) { m_pDevice = device; } void MarkReferenced(WrappedID3D11DeviceContext *ctx, bool initial) const; void MarkDirty(D3D11ResourceManager *manager) const;