Mesa (main): tu: delay decision of forcing sysmem due to subpass self-dependencies
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Jul 28 15:52:33 UTC 2021
Module: Mesa
Branch: main
Commit: 20547a110edb7913fc1176b9605498a58e691cb5
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=20547a110edb7913fc1176b9605498a58e691cb5
Author: Danylo Piliaiev <dpiliaiev at igalia.com>
Date: Fri Jul 23 16:50:27 2021 +0300
tu: delay decision of forcing sysmem due to subpass self-dependencies
DXVK always inserts vertex stage subpass self-dependency for every
subpass regardless of whether there actually would be a barrier.
This effectively disabled gmem rendering with DXVK.
Thus we delay the decision to disable gmem rendering until we
see a barrier with vertex stages.
Signed-off-by: Danylo Piliaiev <dpiliaiev at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12038>
---
src/freedreno/vulkan/tu_cmd_buffer.c | 42 +++++++++++++++++++++++++++++++++++-
src/freedreno/vulkan/tu_pass.c | 9 +++++---
src/freedreno/vulkan/tu_private.h | 1 +
3 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c
index ee69aa6d94c..f9bf3e14f61 100644
--- a/src/freedreno/vulkan/tu_cmd_buffer.c
+++ b/src/freedreno/vulkan/tu_cmd_buffer.c
@@ -540,6 +540,9 @@ use_sysmem_rendering(struct tu_cmd_buffer *cmd)
if (cmd->state.has_tess)
return true;
+ if (cmd->state.disable_gmem)
+ return true;
+
return false;
}
@@ -4391,6 +4394,7 @@ tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
cmd_buffer->state.framebuffer = NULL;
cmd_buffer->state.has_tess = false;
cmd_buffer->state.has_subpass_predication = false;
+ cmd_buffer->state.disable_gmem = false;
/* LRZ is not valid next time we use it */
cmd_buffer->state.lrz.valid = false;
@@ -4402,6 +4406,7 @@ struct tu_barrier_info
uint32_t eventCount;
const VkEvent *pEvents;
VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
};
static void
@@ -4418,6 +4423,39 @@ tu_barrier(struct tu_cmd_buffer *cmd,
VkAccessFlags srcAccessMask = 0;
VkAccessFlags dstAccessMask = 0;
+ if (cmd->state.pass) {
+ const VkPipelineStageFlags framebuffer_space_stages =
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+
+ /* We cannot have non-by-region "fb-space to fb-space" barriers.
+ *
+ * From the Vulkan 1.2.185 spec, section 7.6.1 "Subpass Self-dependency":
+ *
+ * If the source and destination stage masks both include
+ * framebuffer-space stages, then dependencyFlags must include
+ * VK_DEPENDENCY_BY_REGION_BIT.
+ * [...]
+ * Each of the synchronization scopes and access scopes of a
+ * vkCmdPipelineBarrier2KHR or vkCmdPipelineBarrier command inside
+ * a render pass instance must be a subset of the scopes of one of
+ * the self-dependencies for the current subpass.
+ *
+ * If the self-dependency has VK_DEPENDENCY_BY_REGION_BIT or
+ * VK_DEPENDENCY_VIEW_LOCAL_BIT set, then so must the pipeline barrier.
+ *
+ * By-region barriers are ok for gmem. All other barriers would involve
+ * vtx stages which are NOT ok for gmem rendering.
+ * See dep_invalid_for_gmem().
+ */
+ if ((info->srcStageMask & ~framebuffer_space_stages) ||
+ (info->dstStageMask & ~framebuffer_space_stages)) {
+ cmd->state.disable_gmem = true;
+ }
+ }
+
for (uint32_t i = 0; i < memoryBarrierCount; i++) {
srcAccessMask |= pMemoryBarriers[i].srcAccessMask;
dstAccessMask |= pMemoryBarriers[i].dstAccessMask;
@@ -4490,6 +4528,7 @@ tu_CmdPipelineBarrier(VkCommandBuffer commandBuffer,
info.eventCount = 0;
info.pEvents = NULL;
info.srcStageMask = srcStageMask;
+ info.dstStageMask = dstStageMask;
tu_barrier(cmd_buffer, memoryBarrierCount, pMemoryBarriers,
bufferMemoryBarrierCount, pBufferMemoryBarriers,
@@ -4567,7 +4606,8 @@ tu_CmdWaitEvents(VkCommandBuffer commandBuffer,
info.eventCount = eventCount;
info.pEvents = pEvents;
- info.srcStageMask = 0;
+ info.srcStageMask = srcStageMask;
+ info.dstStageMask = dstStageMask;
tu_barrier(cmd, memoryBarrierCount, pMemoryBarriers,
bufferMemoryBarrierCount, pBufferMemoryBarriers,
diff --git a/src/freedreno/vulkan/tu_pass.c b/src/freedreno/vulkan/tu_pass.c
index ef2cf4cfee1..7df0060c0d4 100644
--- a/src/freedreno/vulkan/tu_pass.c
+++ b/src/freedreno/vulkan/tu_pass.c
@@ -86,16 +86,19 @@ tu_render_pass_add_subpass_dep(struct tu_render_pass *pass,
uint32_t src = dep->srcSubpass;
uint32_t dst = dep->dstSubpass;
- if (dep_invalid_for_gmem(dep))
- pass->gmem_pixels = 0;
-
/* Ignore subpass self-dependencies as they allow the app to call
* vkCmdPipelineBarrier() inside the render pass and the driver should only
* do the barrier when called, not when starting the render pass.
+ *
+ * We cannot decide whether to allow gmem rendering before a barrier
+ * is actually emitted, so we delay the decision until then.
*/
if (src == dst)
return;
+ if (dep_invalid_for_gmem(dep))
+ pass->gmem_pixels = 0;
+
struct tu_subpass_barrier *src_barrier;
if (src == VK_SUBPASS_EXTERNAL) {
src_barrier = &pass->subpasses[0].start_barrier;
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index e15b690c38b..e00463d1921 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -971,6 +971,7 @@ struct tu_cmd_state
bool has_tess;
bool has_subpass_predication;
bool predication_active;
+ bool disable_gmem;
struct tu_lrz_state lrz;
More information about the mesa-commit
mailing list