diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index bc9fb54a1..a7a8370a6 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -2069,20 +2069,8 @@ namespace dxvk { UINT NumViews, ID3D11RenderTargetView* const* ppRenderTargetViews, ID3D11DepthStencilView* pDepthStencilView) { - // Native D3D11 does not change the render targets if - // the parameters passed to this method are invalid. - if (!ValidateRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView)) - return; - - for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) { - m_state.om.renderTargetViews.at(i) = i < NumViews - ? static_cast(ppRenderTargetViews[i]) - : nullptr; - } - - m_state.om.depthStencilView = static_cast(pDepthStencilView); - - BindFramebuffer(); + SetRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView); + BindFramebuffer(std::exchange(m_state.om.isUavRendering, false)); } @@ -2094,14 +2082,17 @@ namespace dxvk { UINT NumUAVs, ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, const UINT* pUAVInitialCounts) { + bool spillOnBind = m_state.om.isUavRendering; + if (NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) - OMSetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView); + SetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView); if (NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) { - static std::atomic s_warningShown = { false }; + // Check whether there actually are any UAVs bound + m_state.om.isUavRendering = false; - if (NumUAVs != 0 && !s_warningShown.exchange(true)) - Logger::warn("D3D11: UAV rendering not properly implemented yet"); + for (uint32_t i = 0; i < NumUAVs && !m_state.om.isUavRendering; i++) + m_state.om.isUavRendering = ppUnorderedAccessViews[i] != nullptr; // UAVs are made available to all shader stages in // the graphics pipeline even though this code may @@ -2118,6 +2109,8 @@ namespace dxvk { ppUnorderedAccessViews, pUAVInitialCounts); } } + + BindFramebuffer(spillOnBind); } @@ -2554,7 +2547,7 @@ namespace dxvk { } - void D3D11DeviceContext::BindFramebuffer() { + void D3D11DeviceContext::BindFramebuffer(BOOL Spill) { // NOTE According to the Microsoft docs, we are supposed to // unbind overlapping shader resource views. Since this comes // with a large performance penalty we'll ignore this until an @@ -2579,8 +2572,11 @@ namespace dxvk { } // Create and bind the framebuffer object to the context - EmitCs([cAttachments = std::move(attachments)] (DxvkContext* ctx) { - ctx->bindRenderTargets(cAttachments); + EmitCs([ + cAttachments = std::move(attachments), + cSpill = Spill + ] (DxvkContext* ctx) { + ctx->bindRenderTargets(cAttachments, cSpill); }); } @@ -2786,6 +2782,25 @@ namespace dxvk { } } } + + + void D3D11DeviceContext::SetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView) { + // Native D3D11 does not change the render targets if + // the parameters passed to this method are invalid. + if (!ValidateRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView)) + return; + + for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) { + m_state.om.renderTargetViews.at(i) = i < NumViews + ? static_cast(ppRenderTargetViews[i]) + : nullptr; + } + + m_state.om.depthStencilView = static_cast(pDepthStencilView); + } void D3D11DeviceContext::InitUnorderedAccessViewCounters( @@ -2835,7 +2850,7 @@ namespace dxvk { void D3D11DeviceContext::RestoreState() { - BindFramebuffer(); + BindFramebuffer(m_state.om.isUavRendering); BindShader(m_state.vs.shader.ptr(), VK_SHADER_STAGE_VERTEX_BIT); BindShader(m_state.hs.shader.ptr(), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 1d073095b..576a152a2 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -667,7 +667,8 @@ namespace dxvk { void ApplyViewportState(); - void BindFramebuffer(); + void BindFramebuffer( + BOOL Spill); template void BindShader( @@ -739,6 +740,11 @@ namespace dxvk { UINT NumUAVs, ID3D11UnorderedAccessView* const* ppUnorderedAccessViews); + void SetRenderTargets( + UINT NumViews, + ID3D11RenderTargetView* const* ppRenderTargetViews, + ID3D11DepthStencilView* pDepthStencilView); + void InitUnorderedAccessViewCounters( UINT NumUAVs, ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, diff --git a/src/d3d11/d3d11_context_state.h b/src/d3d11/d3d11_context_state.h index 1a385a0ac..010988055 100644 --- a/src/d3d11/d3d11_context_state.h +++ b/src/d3d11/d3d11_context_state.h @@ -120,6 +120,8 @@ namespace dxvk { FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; UINT sampleMask = 0xFFFFFFFFu; UINT stencilRef = 0u; + + BOOL isUavRendering = FALSE; }; diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index e4bb397f8..b708119d1 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -180,7 +180,7 @@ namespace dxvk { DxvkRenderTargets renderTargets; renderTargets.color[0].view = swapImage; renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - m_context->bindRenderTargets(renderTargets); + m_context->bindRenderTargets(renderTargets, false); VkViewport viewport; viewport.x = 0.0f; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 521eb507c..d2457b4d3 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -87,7 +87,9 @@ namespace dxvk { } - void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) { + void DxvkContext::bindRenderTargets( + const DxvkRenderTargets& targets, + bool spill) { m_state.om.renderTargets = targets; // If necessary, perform clears on the active render targets @@ -108,6 +110,9 @@ namespace dxvk { // the same render targets are bound again m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); } + + if (spill) + this->spillRenderPass(); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index f198bd101..e2b3f6c3c 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -77,12 +77,15 @@ namespace dxvk { * \brief Sets render targets * * Creates a framebuffer on the fly if necessary - * and binds it using \c bindFramebuffer. Prefer - * this method over doing the same thing manually. + * and binds it using \c bindFramebuffer. Set the + * \c spill flag in order to make shader writes + * from previous rendering operations visible. * \param [in] targets Render targets to bind + * \param [in] spill Spill render pass if true */ void bindRenderTargets( - const DxvkRenderTargets& targets); + const DxvkRenderTargets& targets, + bool spill); /** * \brief Binds index buffer diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index 7d2908ab0..ee47e05c7 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -135,6 +135,8 @@ namespace dxvk { VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | @@ -144,6 +146,8 @@ namespace dxvk { VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_SHADER_READ_BIT | + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | diff --git a/src/dxvk/hud/dxvk_hud.cpp b/src/dxvk/hud/dxvk_hud.cpp index 8f55c43ff..c594cfc67 100644 --- a/src/dxvk/hud/dxvk_hud.cpp +++ b/src/dxvk/hud/dxvk_hud.cpp @@ -108,7 +108,7 @@ namespace dxvk::hud { clearRect.layerCount = 1; m_context->bindRenderTargets( - m_renderTargetInfo); + m_renderTargetInfo, false); m_context->clearRenderTarget( m_renderTargetView, clearRect,