From d523405a5a7cbfcabf3a5b56e16ce7b26b306fa2 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 15 Apr 2018 01:09:53 +0200 Subject: [PATCH] [dxvk] Implement bindRenderTargets method An alternative to manually creating a framebuffer object and binding it via bindFramebuffer. Future optmizations can use this to bring down the number of redundant render pass changes. --- src/d3d11/d3d11_context.cpp | 7 ++----- src/dxvk/dxvk_context.cpp | 35 ++++++++++++++++++++++++++++++++++- src/dxvk/dxvk_context.h | 11 +++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 9e6fbb455..bc2a8d2c3 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -2458,11 +2458,8 @@ namespace dxvk { } // Create and bind the framebuffer object to the context - EmitCs([attachments, dev = m_device] (DxvkContext* ctx) { - Rc framebuffer = nullptr; - if (attachments.hasAttachments()) - framebuffer = dev->createFramebuffer(attachments); - ctx->bindFramebuffer(framebuffer); + EmitCs([cAttachments = std::move(attachments)] (DxvkContext* ctx) { + ctx->bindRenderTargets(cAttachments); }); } diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index a66a3d1be..7f8379d0d 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -84,7 +84,7 @@ namespace dxvk { this->eraseActiveQuery(query); } - + void DxvkContext::bindFramebuffer(const Rc& fb) { if (m_state.om.framebuffer != fb) { this->renderPassEnd(); @@ -93,6 +93,39 @@ namespace dxvk { if (fb != nullptr) { m_state.gp.state.msSampleCount = fb->sampleCount(); m_state.gp.state.omRenderPass = fb->renderPass(); + + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } + } + } + + + void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) { + bool needsUpdate = false; + + if (m_state.om.framebuffer != nullptr) { + const DxvkRenderTargets& active = m_state.om.framebuffer->renderTargets(); + + needsUpdate |= active.getDepthTarget().view != targets.getDepthTarget().view + || active.getDepthTarget().layout != targets.getDepthTarget().layout; + + for (uint32_t i = 0; i < MaxNumRenderTargets && !needsUpdate; i++) { + needsUpdate |= active.getColorTarget(i).view != targets.getColorTarget(i).view + || active.getColorTarget(i).layout != targets.getColorTarget(i).layout; + } + } else { + needsUpdate = targets.hasAttachments(); + } + + if (needsUpdate) { + Rc fb = targets.hasAttachments() + ? m_device->createFramebuffer(targets) + : nullptr; + + if (fb != nullptr) { + m_state.gp.state.msSampleCount = fb->sampleCount(); + m_state.gp.state.omRenderPass = fb->renderPass(); + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); } } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index da9864ccd..5dd9b3377 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -78,6 +78,17 @@ namespace dxvk { void bindFramebuffer( const Rc& fb); + /** + * \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. + * \param [in] targets Render targets to bind + */ + void bindRenderTargets( + const DxvkRenderTargets& targets); + /** * \brief Binds index buffer *