anv/pass: Record required pipe flushes
authorJason Ekstrand <jason.ekstrand@intel.com>
Sat, 11 Mar 2017 01:29:24 +0000 (17:29 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Sat, 8 Apr 2017 02:24:14 +0000 (19:24 -0700)
Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
src/intel/vulkan/anv_pass.c
src/intel/vulkan/anv_private.h

index 15c42758f009d393f0c0705a9937f656fd035eb8..dcd9aafc64508884fd7cd5c0c51b16ba34cbcf40 100644 (file)
@@ -45,11 +45,13 @@ VkResult anv_CreateRenderPass(
    struct anv_render_pass *pass;
    struct anv_subpass *subpasses;
    struct anv_render_pass_attachment *attachments;
+   enum anv_pipe_bits *subpass_flushes;
 
    ANV_MULTIALLOC(ma);
    anv_multialloc_add(&ma, &pass, 1);
    anv_multialloc_add(&ma, &subpasses, pCreateInfo->subpassCount);
    anv_multialloc_add(&ma, &attachments, pCreateInfo->attachmentCount);
+   anv_multialloc_add(&ma, &subpass_flushes, pCreateInfo->subpassCount + 1);
 
    VkAttachmentReference *subpass_attachments;
    uint32_t subpass_attachment_count = 0;
@@ -74,6 +76,7 @@ VkResult anv_CreateRenderPass(
    pass->attachment_count = pCreateInfo->attachmentCount;
    pass->subpass_count = pCreateInfo->subpassCount;
    pass->attachments = attachments;
+   pass->subpass_flushes = subpass_flushes;
 
    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
       struct anv_render_pass_attachment *att = &pass->attachments[i];
@@ -90,6 +93,7 @@ VkResult anv_CreateRenderPass(
       subpass_usages += pass->subpass_count;
    }
 
+   bool has_color = false, has_depth = false, has_input = false;
    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
       const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
       struct anv_subpass *subpass = &pass->subpasses[i];
@@ -107,6 +111,7 @@ VkResult anv_CreateRenderPass(
             uint32_t a = desc->pInputAttachments[j].attachment;
             subpass->input_attachments[j] = desc->pInputAttachments[j];
             if (a != VK_ATTACHMENT_UNUSED) {
+               has_input = true;
                pass->attachments[a].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
                pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_INPUT;
                pass->attachments[a].last_subpass_idx = i;
@@ -126,6 +131,7 @@ VkResult anv_CreateRenderPass(
             uint32_t a = desc->pColorAttachments[j].attachment;
             subpass->color_attachments[j] = desc->pColorAttachments[j];
             if (a != VK_ATTACHMENT_UNUSED) {
+               has_color = true;
                pass->attachments[a].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
                pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW;
                pass->attachments[a].last_subpass_idx = i;
@@ -162,6 +168,7 @@ VkResult anv_CreateRenderPass(
          *subpass_attachments++ = subpass->depth_stencil_attachment =
             *desc->pDepthStencilAttachment;
          if (a != VK_ATTACHMENT_UNUSED) {
+            has_depth = true;
             pass->attachments[a].usage |=
                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
             pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW;
@@ -173,6 +180,87 @@ VkResult anv_CreateRenderPass(
       }
    }
 
+   for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
+      const VkSubpassDependency *dep = &pCreateInfo->pDependencies[i];
+      if (dep->dstSubpass == VK_SUBPASS_EXTERNAL) {
+         pass->subpass_flushes[pass->subpass_count] |=
+            anv_pipe_invalidate_bits_for_access_flags(dep->dstAccessMask);
+      } else {
+         assert(dep->dstSubpass < pass->subpass_count);
+         pass->subpass_flushes[dep->dstSubpass] |=
+            anv_pipe_invalidate_bits_for_access_flags(dep->dstAccessMask);
+      }
+
+      if (dep->srcSubpass == VK_SUBPASS_EXTERNAL) {
+         pass->subpass_flushes[0] |=
+            anv_pipe_flush_bits_for_access_flags(dep->srcAccessMask);
+      } else {
+         assert(dep->srcSubpass < pass->subpass_count);
+         pass->subpass_flushes[dep->srcSubpass + 1] |=
+            anv_pipe_flush_bits_for_access_flags(dep->srcAccessMask);
+      }
+   }
+
+   /* From the Vulkan 1.0.39 spec:
+    *
+    *    If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
+    *    first subpass that uses an attachment, then an implicit subpass
+    *    dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is
+    *    used in. The subpass dependency operates as if defined with the
+    *    following parameters:
+    *
+    *    VkSubpassDependency implicitDependency = {
+    *        .srcSubpass = VK_SUBPASS_EXTERNAL;
+    *        .dstSubpass = firstSubpass; // First subpass attachment is used in
+    *        .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+    *        .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+    *        .srcAccessMask = 0;
+    *        .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
+    *                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+    *                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
+    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+    *        .dependencyFlags = 0;
+    *    };
+    *
+    *    Similarly, if there is no subpass dependency from the last subpass
+    *    that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit
+    *    subpass dependency exists from the last subpass it is used in to
+    *    VK_SUBPASS_EXTERNAL. The subpass dependency operates as if defined
+    *    with the following parameters:
+    *
+    *    VkSubpassDependency implicitDependency = {
+    *        .srcSubpass = lastSubpass; // Last subpass attachment is used in
+    *        .dstSubpass = VK_SUBPASS_EXTERNAL;
+    *        .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+    *        .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+    *        .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
+    *                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+    *                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
+    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+    *                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+    *        .dstAccessMask = 0;
+    *        .dependencyFlags = 0;
+    *    };
+    *
+    * We could implement this by walking over all of the attachments and
+    * subpasses and checking to see if any of them don't have an external
+    * dependency.  Or, we could just be lazy and add a couple extra flushes.
+    * We choose to be lazy.
+    */
+   if (has_input) {
+      pass->subpass_flushes[0] |=
+         ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT;
+   }
+   if (has_color) {
+      pass->subpass_flushes[pass->subpass_count] |=
+         ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT;
+   }
+   if (has_depth) {
+      pass->subpass_flushes[pass->subpass_count] |=
+         ANV_PIPE_DEPTH_CACHE_FLUSH_BIT;
+   }
+
    *pRenderPass = anv_render_pass_to_handle(pass);
 
    return VK_SUCCESS;
index 217c86c29297ddaba2e840f56a90c97253c5f47e..7d079000b0c766e759c2c7a5c2c3701a22480df8 100644 (file)
@@ -2181,6 +2181,8 @@ struct anv_render_pass {
    uint32_t                                     attachment_count;
    uint32_t                                     subpass_count;
    VkAttachmentReference *                      subpass_attachments;
+   /* An array of subpass_count+1 flushes, one per subpass boundary */
+   enum anv_pipe_bits *                         subpass_flushes;
    struct anv_render_pass_attachment *          attachments;
    struct anv_subpass                           subpasses[0];
 };