[dxvk] Apply render target bindings at draw time

This should help reduce the number of redundant render pass spills,
especially in games which use deferred contexts for rendering. This
optimization mostly helps in GPU-bound scenarios.
This commit is contained in:
Philip Rebohle 2018-04-26 14:47:55 +02:00
parent 8606576d83
commit 1075990dbe
3 changed files with 31 additions and 12 deletions

View File

@ -98,19 +98,18 @@ namespace dxvk {
m_state.om.framebuffer = fb;
}
m_state.om.renderTargets = fb != nullptr
? fb->renderTargets()
: DxvkRenderTargets();
m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer);
}
void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) {
bool sameAsCurr = m_state.om.framebuffer != nullptr
&& m_state.om.framebuffer->renderTargets().matches(targets);
if (!sameAsCurr) {
Rc<DxvkFramebuffer> fb = targets.hasAttachments()
? m_device->createFramebuffer(targets)
: nullptr;
this->bindFramebuffer(fb);
if (m_state.om.framebuffer == nullptr || !m_state.om.framebuffer->renderTargets().matches(targets)) {
m_state.om.renderTargets = targets;
m_flags.set(DxvkContextFlag::GpDirtyFramebuffer);
}
}
@ -392,6 +391,8 @@ namespace dxvk {
const VkClearRect& clearRect,
VkImageAspectFlags clearAspects,
const VkClearValue& clearValue) {
this->updateFramebuffer();
// Check whether the render target view is an attachment
// of the current framebuffer. If not, we need to create
// a temporary framebuffer.
@ -1798,6 +1799,23 @@ namespace dxvk {
}
void DxvkContext::updateFramebuffer() {
if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) {
m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer);
this->spillRenderPass();
auto fb = m_device->createFramebuffer(m_state.om.renderTargets);
m_state.gp.state.msSampleCount = fb->sampleCount();
m_state.gp.state.omRenderPass = fb->renderPass();
m_state.om.framebuffer = fb;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
}
void DxvkContext::updateIndexBufferBinding() {
if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) {
m_flags.clr(DxvkContextFlag::GpDirtyIndexBuffer);
@ -1881,6 +1899,7 @@ namespace dxvk {
void DxvkContext::commitGraphicsState() {
this->updateFramebuffer();
this->startRenderPass();
this->updateGraphicsPipeline();
this->updateIndexBufferBinding();

View File

@ -662,9 +662,7 @@ namespace dxvk {
const DxvkBindingState& bindingState,
const Rc<DxvkPipelineLayout>& layout);
void updateViewports();
void updateBlendConstants();
void updateStencilReference();
void updateFramebuffer();
void updateIndexBufferBinding();
void updateVertexBufferBindings();

View File

@ -22,6 +22,7 @@ namespace dxvk {
*/
enum class DxvkContextFlag : uint64_t {
GpRenderPassBound, ///< Render pass is currently bound
GpDirtyFramebuffer, ///< Framebuffer binding is out of date
GpDirtyPipeline, ///< Graphics pipeline binding is out of date
GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled
GpDirtyResources, ///< Graphics pipeline resource bindings are out of date
@ -53,6 +54,7 @@ namespace dxvk {
struct DxvkOutputMergerState {
DxvkRenderTargets renderTargets;
Rc<DxvkFramebuffer> framebuffer = nullptr;
DxvkBlendConstants blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f };