Mesa (main): vulkan/render_pass: Pass sample locations to barriers

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 24 23:08:44 UTC 2022


Module: Mesa
Branch: main
Commit: 7e11cdc77a6ac186bdce0b98cc2e5d4ca5857999
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7e11cdc77a6ac186bdce0b98cc2e5d4ca5857999

Author: Jason Ekstrand <jason.ekstrand at collabora.com>
Date:   Fri May  6 18:14:26 2022 -0500

vulkan/render_pass: Pass sample locations to barriers

This is required for depth/stencil images created with
VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16953>

---

 src/vulkan/runtime/vk_command_buffer.h |   3 +
 src/vulkan/runtime/vk_render_pass.c    | 168 +++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/src/vulkan/runtime/vk_command_buffer.h b/src/vulkan/runtime/vk_command_buffer.h
index 36099d03a56..4a9b3385a30 100644
--- a/src/vulkan/runtime/vk_command_buffer.h
+++ b/src/vulkan/runtime/vk_command_buffer.h
@@ -46,6 +46,7 @@ struct vk_render_pass;
 struct vk_attachment_view_state {
    VkImageLayout layout;
    VkImageLayout stencil_layout;
+   const VkSampleLocationsInfoEXT *sample_locations;
 };
 
 struct vk_attachment_state {
@@ -130,6 +131,8 @@ struct vk_command_buffer {
    /* This uses the same trick as STACK_ARRAY */
    struct vk_attachment_state *attachments;
    struct vk_attachment_state _attachments[8];
+
+   VkRenderPassSampleLocationsBeginInfoEXT *pass_sample_locations;
 };
 
 VK_DEFINE_HANDLE_CASTS(vk_command_buffer, base, VkCommandBuffer,
diff --git a/src/vulkan/runtime/vk_render_pass.c b/src/vulkan/runtime/vk_render_pass.c
index 41fe532e1d1..048a1875df6 100644
--- a/src/vulkan/runtime/vk_render_pass.c
+++ b/src/vulkan/runtime/vk_render_pass.c
@@ -980,6 +980,103 @@ vk_common_GetRenderAreaGranularity(VkDevice device,
    *pGranularity = (VkExtent2D) { 1, 1 };
 }
 
+static VkRenderPassSampleLocationsBeginInfoEXT *
+clone_rp_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT *loc)
+{
+   uint32_t sl_count = 0;
+
+   for (uint32_t i = 0; i < loc->attachmentInitialSampleLocationsCount; i++) {
+      const VkAttachmentSampleLocationsEXT *att_sl_in =
+         &loc->pAttachmentInitialSampleLocations[i];
+      sl_count += att_sl_in->sampleLocationsInfo.sampleLocationsCount;
+   }
+   for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
+      const VkSubpassSampleLocationsEXT *sp_sl_in =
+         &loc->pPostSubpassSampleLocations[i];
+      sl_count += sp_sl_in->sampleLocationsInfo.sampleLocationsCount;
+   }
+
+   VK_MULTIALLOC(ma);
+   VK_MULTIALLOC_DECL(&ma, VkRenderPassSampleLocationsBeginInfoEXT, new_loc, 1);
+   VK_MULTIALLOC_DECL(&ma, VkAttachmentSampleLocationsEXT, new_att_sl,
+                      loc->attachmentInitialSampleLocationsCount);
+   VK_MULTIALLOC_DECL(&ma, VkSubpassSampleLocationsEXT, new_sp_sl,
+                      loc->postSubpassSampleLocationsCount);
+   VK_MULTIALLOC_DECL(&ma, VkSampleLocationEXT, sl, sl_count);
+   if (!vk_multialloc_alloc(&ma, vk_default_allocator(),
+                            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
+      return NULL;
+
+   VkSampleLocationEXT *next_sl = sl;
+   for (uint32_t i = 0; i < loc->attachmentInitialSampleLocationsCount; i++) {
+      const VkAttachmentSampleLocationsEXT *att_sl_in =
+         &loc->pAttachmentInitialSampleLocations[i];
+      const VkSampleLocationsInfoEXT *sli_in = &att_sl_in->sampleLocationsInfo;
+
+      typed_memcpy(next_sl, sli_in->pSampleLocations,
+                   sli_in->sampleLocationsCount);
+
+      new_att_sl[i] = (VkAttachmentSampleLocationsEXT) {
+         .attachmentIndex = att_sl_in->attachmentIndex,
+         .sampleLocationsInfo = {
+            .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
+            .sampleLocationsPerPixel = sli_in->sampleLocationsPerPixel,
+            .sampleLocationGridSize = sli_in->sampleLocationGridSize,
+            .sampleLocationsCount = sli_in->sampleLocationsCount,
+            .pSampleLocations = next_sl,
+         },
+      };
+
+      next_sl += sli_in->sampleLocationsCount;
+   }
+
+   for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
+      const VkSubpassSampleLocationsEXT *sp_sl_in =
+         &loc->pPostSubpassSampleLocations[i];
+      const VkSampleLocationsInfoEXT *sli_in = &sp_sl_in->sampleLocationsInfo;
+
+      typed_memcpy(next_sl, sli_in->pSampleLocations,
+                   sli_in->sampleLocationsCount);
+
+      new_sp_sl[i] = (VkSubpassSampleLocationsEXT) {
+         .subpassIndex = sp_sl_in->subpassIndex,
+         .sampleLocationsInfo = {
+            .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
+            .sampleLocationsPerPixel = sli_in->sampleLocationsPerPixel,
+            .sampleLocationGridSize = sli_in->sampleLocationGridSize,
+            .sampleLocationsCount = sli_in->sampleLocationsCount,
+            .pSampleLocations = next_sl,
+         },
+      };
+
+      next_sl += sli_in->sampleLocationsCount;
+   }
+
+   assert(next_sl == sl + sl_count);
+
+   *new_loc = (VkRenderPassSampleLocationsBeginInfoEXT) {
+      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT,
+      .attachmentInitialSampleLocationsCount = loc->attachmentInitialSampleLocationsCount,
+      .pAttachmentInitialSampleLocations = new_att_sl,
+      .postSubpassSampleLocationsCount = loc->postSubpassSampleLocationsCount,
+      .pPostSubpassSampleLocations = new_sp_sl,
+   };
+
+   return new_loc;
+}
+
+static const VkSampleLocationsInfoEXT *
+get_subpass_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT *loc,
+                             uint32_t subpass_idx)
+{
+   for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
+      if (loc->pPostSubpassSampleLocations[i].subpassIndex == subpass_idx)
+         return &loc->pPostSubpassSampleLocations[i].sampleLocationsInfo;
+   }
+
+   return NULL;
+}
+
 static bool
 vk_image_layout_supports_input_attachment(VkImageLayout layout)
 {
@@ -1072,6 +1169,7 @@ transition_image_range(const struct vk_image_view *image_view,
                        VkImageLayout new_layout,
                        VkImageLayout old_stencil_layout,
                        VkImageLayout new_stencil_layout,
+                       const VkSampleLocationsInfoEXT *sample_locations,
                        uint32_t *barrier_count,
                        uint32_t max_barrier_count,
                        VkImageMemoryBarrier2 *barriers)
@@ -1111,6 +1209,7 @@ transition_image_range(const struct vk_image_view *image_view,
          assert(*barrier_count < max_barrier_count);
          barriers[(*barrier_count)++] = (VkImageMemoryBarrier2) {
             .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+            .pNext = sample_locations,
             .srcStageMask = src_sa.stages,
             .srcAccessMask = src_sa.access,
             .dstStageMask = dst_sa.stages,
@@ -1320,6 +1419,7 @@ transition_attachment(struct vk_command_buffer *cmd_buffer,
       transition_image_range(image_view, range,
                              att_view_state->layout, layout,
                              att_view_state->stencil_layout, stencil_layout,
+                             att_view_state->sample_locations,
                              barrier_count, max_barrier_count, barriers);
 
       att_view_state->layout = layout;
@@ -1531,6 +1631,7 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
       .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
    };
 
+   const VkSampleLocationsInfoEXT *sample_locations = NULL;
    if (subpass->depth_stencil_attachment != NULL) {
       const struct vk_subpass_attachment *sp_att =
          subpass->depth_stencil_attachment;
@@ -1612,6 +1713,37 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
          stencil_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
       }
 
+      /* From the Vulkan 1.3.212 spec:
+       *
+       *    "If the current render pass does not use the attachment as a
+       *    depth/stencil attachment in any subpass that happens-before, the
+       *    automatic layout transition uses the sample locations state
+       *    specified in the sampleLocationsInfo member of the element of the
+       *    VkRenderPassSampleLocationsBeginInfoEXT::pAttachmentInitialSampleLocations
+       *    array for which the attachmentIndex member equals the attachment
+       *    index of the attachment, if one is specified. Otherwise, the
+       *    automatic layout transition uses the sample locations state
+       *    specified in the sampleLocationsInfo member of the element of the
+       *    VkRenderPassSampleLocationsBeginInfoEXT::pPostSubpassSampleLocations
+       *    array for which the subpassIndex member equals the index of the
+       *    subpass that last used the attachment as a depth/stencil
+       *    attachment, if one is specified."
+       *
+       * Unfortunately, this says nothing whatsoever about multiview.
+       * However, since multiview render passes are described as a single-view
+       * render pass repeated per-view, we assume this is per-view.
+       */
+      if (cmd_buffer->pass_sample_locations != NULL &&
+          (att_state->image_view->image->create_flags &
+           VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT)) {
+         sample_locations =
+            get_subpass_sample_locations(cmd_buffer->pass_sample_locations,
+                                         subpass_idx);
+
+         u_foreach_bit(view, subpass->view_mask)
+            att_state->views[view].sample_locations = sample_locations;
+      }
+
       if (sp_att->resolve != NULL) {
          const struct vk_subpass_attachment *res_sp_att = sp_att->resolve;
          assert(res_sp_att->attachment < pass->attachment_count);
@@ -1836,6 +1968,12 @@ begin_subpass(struct vk_command_buffer *cmd_buffer,
       __vk_append_struct(&rendering, &fsr_attachment);
    }
 
+   VkSampleLocationsInfoEXT sample_locations_tmp;
+   if (sample_locations) {
+      sample_locations_tmp = *sample_locations;
+      __vk_append_struct(&rendering, &sample_locations_tmp);
+   }
+
    disp->CmdBeginRendering(vk_command_buffer_to_handle(cmd_buffer),
                            &rendering);
 
@@ -1977,6 +2115,33 @@ vk_common_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
          att_state->clear_value = pRenderPassBeginInfo->pClearValues[a];
    }
 
+   const VkRenderPassSampleLocationsBeginInfoEXT *rp_sl_info =
+      vk_find_struct_const(pRenderPassBeginInfo->pNext,
+                           RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT);
+   if (rp_sl_info) {
+      cmd_buffer->pass_sample_locations = clone_rp_sample_locations(rp_sl_info);
+      assert(cmd_buffer->pass_sample_locations);
+
+      for (uint32_t i = 0; i < rp_sl_info->attachmentInitialSampleLocationsCount; i++) {
+         const VkAttachmentSampleLocationsEXT *att_sl =
+            &rp_sl_info->pAttachmentInitialSampleLocations[i];
+
+         assert(att_sl->attachmentIndex < pass->attachment_count);
+         struct vk_attachment_state *att_state =
+            &cmd_buffer->attachments[att_sl->attachmentIndex];
+
+         /* Sample locations only matter for depth/stencil images created with
+          * VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
+          */
+         if (vk_format_is_depth_or_stencil(att_state->image_view->format) &&
+             (att_state->image_view->image->create_flags &
+              VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT)) {
+            for (uint32_t v = 0; v < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT; v++)
+               att_state->views[v].sample_locations = &att_sl->sampleLocationsInfo;
+         }
+      }
+   }
+
    begin_subpass(cmd_buffer, pSubpassBeginInfo);
 }
 
@@ -1989,6 +2154,9 @@ vk_command_buffer_reset_render_pass(struct vk_command_buffer *cmd_buffer)
    if (cmd_buffer->attachments != cmd_buffer->_attachments)
       free(cmd_buffer->attachments);
    cmd_buffer->attachments = NULL;
+   if (cmd_buffer->pass_sample_locations != NULL)
+      vk_free(vk_default_allocator(), cmd_buffer->pass_sample_locations);
+   cmd_buffer->pass_sample_locations = NULL;
 }
 
 VKAPI_ATTR void VKAPI_CALL



More information about the mesa-commit mailing list