From 2f5c7562c2aa6d889b5439439ef74e085943938a Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 23 Aug 2021 16:36:39 +0200 Subject: [PATCH] [dxvk] Track transform feedback counter hazards properly If we avoid needlessly pausing and resuming transform feedback with the same counters, we can use existing barrier tracking to insert counter barriers without requiring an invalid render pass self-dependency. --- src/dxvk/dxvk_context.cpp | 31 ++++++++++++------------------- src/dxvk/dxvk_context_state.h | 1 - 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 526ab3083..ce21a242b 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2146,10 +2146,10 @@ namespace dxvk { DxvkCmdBuffer cmdBuffer; if (replaceBuffer) { - // Pause transform feedback so that we don't mess - // with the currently bound counter buffers + // Suspend render pass so that we don't mess with the + // currently bound transform feedback counter buffers if (m_flags.test(DxvkContextFlag::GpXfbActive)) - this->pauseTransformFeedback(); + this->spillRenderPass(true); // As an optimization, allocate a free slice and perform // the copy in the initialization command buffer instead @@ -3925,8 +3925,6 @@ namespace dxvk { m_gfxBarriers.recordCommands(m_cmd); this->unbindGraphicsPipeline(); - - m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters); } else if (!suspend) { // We may end a previously suspended render pass if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) { @@ -4023,16 +4021,6 @@ namespace dxvk { if (!m_flags.test(DxvkContextFlag::GpXfbActive)) { m_flags.set(DxvkContextFlag::GpXfbActive); - if (m_flags.test(DxvkContextFlag::GpDirtyXfbCounters)) { - m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters); - - this->emitMemoryBarrier(0, - VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, /* XXX */ - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT); - } - VkBuffer ctrBuffers[MaxNumXfbBuffers]; VkDeviceSize ctrOffsets[MaxNumXfbBuffers]; @@ -4077,8 +4065,6 @@ namespace dxvk { m_cmd->cmdEndTransformFeedback( 0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets); - - m_flags.set(DxvkContextFlag::GpDirtyXfbCounters); } } @@ -4171,8 +4157,6 @@ namespace dxvk { bool DxvkContext::updateGraphicsPipelineState() { - this->pauseTransformFeedback(); - // Set up vertex buffer strides for active bindings for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) { const uint32_t binding = m_state.gp.state.ilBindings[i].binding(); @@ -5105,11 +5089,20 @@ namespace dxvk { && m_state.gp.flags.test(DxvkGraphicsPipelineFlag::HasTransformFeedback)) { for (uint32_t i = 0; i < MaxNumXfbBuffers && !requiresBarrier; i++) { const auto& xfbBufferSlice = m_state.xfb.buffers[i]; + const auto& xfbCounterSlice = m_state.xfb.counters[i]; if (xfbBufferSlice.defined()) { requiresBarrier = this->checkGfxBufferBarrier(xfbBufferSlice, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT) != 0; + + if (xfbCounterSlice.defined()) { + requiresBarrier |= this->checkGfxBufferBarrier(xfbCounterSlice, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT | + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT) != 0; + } } } } diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index f3fb1bf68..9252c4334 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -32,7 +32,6 @@ namespace dxvk { GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date GpDirtyIndexBuffer, ///< Index buffer binding are out of date GpDirtyXfbBuffers, ///< Transform feedback buffer bindings are out of date - GpDirtyXfbCounters, ///< Counter buffer values are dirty GpDirtyBlendConstants, ///< Blend constants have changed GpDirtyDepthBias, ///< Depth bias has changed GpDirtyDepthBounds, ///< Depth bounds have changed