Mesa (main): dzn: Add support for dynamic rendering

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Apr 22 08:50:54 UTC 2022


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

Author: Boris Brezillon <boris.brezillon at collabora.com>
Date:   Tue Apr 12 15:01:10 2022 +0200

dzn: Add support for dynamic rendering

This is how D3D12 works, so nothing really complicated here. We just
add a bunch of states to the render state, patch the pipeline building
logic to support dynamic rendering, and add new functions to

Suggested-by: Jason Ekstrand <jason.ekstrand at collabora.com>
Reviewed-by: Jesse Natalie <jenatali at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15913>

---

 src/microsoft/vulkan/dzn_cmd_buffer.c | 284 ++++++++++++++++++++++++++++++++--
 src/microsoft/vulkan/dzn_device.c     |   1 +
 src/microsoft/vulkan/dzn_pipeline.c   |  48 ++++--
 src/microsoft/vulkan/dzn_private.h    |  22 ++-
 4 files changed, 331 insertions(+), 24 deletions(-)

diff --git a/src/microsoft/vulkan/dzn_cmd_buffer.c b/src/microsoft/vulkan/dzn_cmd_buffer.c
index ed4c847d144..0d10b9d9ea3 100644
--- a/src/microsoft/vulkan/dzn_cmd_buffer.c
+++ b/src/microsoft/vulkan/dzn_cmd_buffer.c
@@ -3380,23 +3380,40 @@ dzn_CmdClearAttachments(VkCommandBuffer commandBuffer,
                         const VkClearRect *pRects)
 {
    VK_FROM_HANDLE(dzn_cmd_buffer, cmdbuf, commandBuffer);
-
    struct dzn_render_pass *pass = cmdbuf->state.render.pass;
    const struct dzn_subpass *subpass =
-      &pass->subpasses[cmdbuf->state.render.subpass];
+      pass ? &pass->subpasses[cmdbuf->state.render.subpass] : NULL;
 
    for (unsigned i = 0; i < attachmentCount; i++) {
-      uint32_t idx;
-      if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
-         idx = subpass->colors[pAttachments[i].colorAttachment].idx;
-      else
-         idx = subpass->zs.idx;
+      struct dzn_image_view *view = NULL;
 
-      if (idx == VK_ATTACHMENT_UNUSED)
-         continue;
+      if (subpass) {
+         uint32_t idx =
+            (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) ?
+            subpass->colors[pAttachments[i].colorAttachment].idx :
+            subpass->zs.idx;
 
-      struct dzn_image_view *view =
-         cmdbuf->state.render.framebuffer->attachments[idx];
+            if (idx != VK_ATTACHMENT_UNUSED)
+               view = cmdbuf->state.render.framebuffer->attachments[idx];
+      } else {
+         if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
+            assert(pAttachments[i].colorAttachment < cmdbuf->state.render.attachments.color_count);
+            view = cmdbuf->state.render.attachments.colors[pAttachments[i].colorAttachment].iview;
+         } else {
+            if (cmdbuf->state.render.attachments.depth.iview &&
+                (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT))
+               view = cmdbuf->state.render.attachments.depth.iview;
+
+            if (cmdbuf->state.render.attachments.stencil.iview &&
+                (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
+               assert(!view || view == cmdbuf->state.render.attachments.depth.iview);
+               view = cmdbuf->state.render.attachments.stencil.iview;
+            }
+         }
+      }
+
+      if (!view)
+         continue;
 
       for (uint32_t j = 0; j < rectCount; j++) {
          D3D12_RECT rect;
@@ -3488,6 +3505,251 @@ dzn_CmdNextSubpass2(VkCommandBuffer commandBuffer,
    dzn_cmd_buffer_begin_subpass(cmdbuf);
 }
 
+static void
+dzn_cmd_buffer_resolve_rendering_attachment(struct dzn_cmd_buffer *cmdbuf,
+                                            const struct dzn_rendering_attachment *att,
+                                            VkImageAspectFlagBits aspect)
+{
+   struct dzn_image_view *src = att->iview;
+   struct dzn_image_view *dst = att->resolve.iview;
+
+   if (!src || !dst)
+      return;
+
+   VkImageLayout src_layout = att->layout;
+   VkImageLayout dst_layout = att->resolve.layout;
+   struct dzn_image *src_img = container_of(src->vk.image, struct dzn_image, vk);
+   D3D12_RESOURCE_STATES src_state = dzn_image_layout_to_state(src_layout, aspect);
+   struct dzn_image *dst_img = container_of(dst->vk.image, struct dzn_image, vk);
+   D3D12_RESOURCE_STATES dst_state = dzn_image_layout_to_state(src_layout, aspect);
+   D3D12_RESOURCE_BARRIER barriers[2] = {
+      {
+         .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
+         .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
+         .Transition = {
+            .pResource = src_img->res,
+            .StateBefore = dzn_image_layout_to_state(src_layout, aspect),
+            .StateAfter = D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
+         },
+      },
+      {
+         .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
+         .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
+         .Transition = {
+            .pResource = dst_img->res,
+            .StateBefore = dzn_image_layout_to_state(dst_layout, aspect),
+            .StateAfter = D3D12_RESOURCE_STATE_RESOLVE_DEST,
+         },
+      },
+   };
+
+   VkImageSubresourceRange src_range = {
+      .aspectMask = (VkImageAspectFlags)aspect,
+      .baseMipLevel = src->vk.base_mip_level,
+      .levelCount = MIN2(src->vk.level_count, dst->vk.level_count),
+      .baseArrayLayer = src->vk.base_array_layer,
+      .layerCount = MIN2(src->vk.layer_count, dst->vk.layer_count),
+   };
+
+   VkImageSubresourceRange dst_range = {
+      .aspectMask = (VkImageAspectFlags)aspect,
+      .baseMipLevel = dst->vk.base_mip_level,
+      .levelCount = MIN2(src->vk.level_count, dst->vk.level_count),
+      .baseArrayLayer = dst->vk.base_array_layer,
+      .layerCount = MIN2(src->vk.layer_count, dst->vk.layer_count),
+   };
+
+   for (uint32_t level = 0; level < src_range.levelCount; level++) {
+      for (uint32_t layer = 0; layer < src_range.layerCount; layer++) {
+         uint32_t src_subres =
+            dzn_image_range_get_subresource_index(src_img, &src_range, aspect, level, layer);
+         uint32_t dst_subres =
+            dzn_image_range_get_subresource_index(dst_img, &dst_range, aspect, level, layer);
+
+         barriers[0].Transition.Subresource = src_subres;
+         barriers[0].Transition.StateBefore = src_state;
+         barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_RESOLVE_SOURCE;
+         barriers[1].Transition.Subresource = dst_subres,
+         barriers[1].Transition.StateBefore = dst_state;
+         barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_RESOLVE_DEST;
+         ID3D12GraphicsCommandList1_ResourceBarrier(cmdbuf->cmdlist, ARRAY_SIZE(barriers), barriers);
+
+         ID3D12GraphicsCommandList1_ResolveSubresource(cmdbuf->cmdlist,
+                                                       dst_img->res, src_subres,
+                                                       src_img->res, dst_subres,
+                                                       dst->srv_desc.Format);
+         DZN_SWAP(D3D12_RESOURCE_STATES,
+                  barriers[0].Transition.StateBefore,
+                  barriers[0].Transition.StateAfter);
+         DZN_SWAP(D3D12_RESOURCE_STATES,
+                  barriers[1].Transition.StateBefore,
+                  barriers[1].Transition.StateAfter);
+         ID3D12GraphicsCommandList1_ResourceBarrier(cmdbuf->cmdlist, ARRAY_SIZE(barriers), barriers);
+      }
+   }
+}
+
+VKAPI_ATTR void VKAPI_CALL
+dzn_CmdBeginRendering(VkCommandBuffer commandBuffer,
+                      const VkRenderingInfo *pRenderingInfo)
+{
+   VK_FROM_HANDLE(dzn_cmd_buffer, cmdbuf, commandBuffer);
+
+   D3D12_RECT new_render_area = {
+      .left = pRenderingInfo->renderArea.offset.x,
+      .top = pRenderingInfo->renderArea.offset.y,
+      .right = (LONG)(pRenderingInfo->renderArea.offset.x + pRenderingInfo->renderArea.extent.width),
+      .bottom = (LONG)(pRenderingInfo->renderArea.offset.y + pRenderingInfo->renderArea.extent.height),
+   };
+
+   // The render area has an impact on the scissor state.
+   if (memcmp(&cmdbuf->state.render.area, &new_render_area, sizeof(new_render_area))) {
+      cmdbuf->state.dirty |= DZN_CMD_DIRTY_SCISSORS;
+      cmdbuf->state.render.area = new_render_area;
+   }
+
+   cmdbuf->state.render.flags = pRenderingInfo->flags;
+   cmdbuf->state.render.layer_count = pRenderingInfo->layerCount;
+   cmdbuf->state.render.view_mask = pRenderingInfo->viewMask;
+
+   D3D12_CPU_DESCRIPTOR_HANDLE rt_handles[MAX_RTS] = { 0 };
+   D3D12_CPU_DESCRIPTOR_HANDLE zs_handle = { 0 };
+
+   cmdbuf->state.render.attachments.color_count = pRenderingInfo->colorAttachmentCount;
+   for (uint32_t i = 0; i < pRenderingInfo->colorAttachmentCount; i++) {
+      const VkRenderingAttachmentInfo *att = &pRenderingInfo->pColorAttachments[i];
+      VK_FROM_HANDLE(dzn_image_view, iview, att->imageView);
+
+      cmdbuf->state.render.attachments.colors[i].iview = iview;
+      cmdbuf->state.render.attachments.colors[i].layout = att->imageLayout;
+      cmdbuf->state.render.attachments.colors[i].resolve.mode = att->resolveMode;
+      cmdbuf->state.render.attachments.colors[i].resolve.iview =
+         dzn_image_view_from_handle(att->resolveImageView);
+      cmdbuf->state.render.attachments.colors[i].resolve.layout =
+         att->resolveImageLayout;
+      cmdbuf->state.render.attachments.colors[i].store_op = att->storeOp;
+
+      if (!iview)
+         continue;
+
+      struct dzn_image *img = container_of(iview->vk.image, struct dzn_image, vk);
+      rt_handles[i] = dzn_cmd_buffer_get_rtv(cmdbuf, img, &iview->rtv_desc);
+   }
+
+   if (pRenderingInfo->pDepthAttachment) {
+      const VkRenderingAttachmentInfo *att = pRenderingInfo->pDepthAttachment;
+
+      cmdbuf->state.render.attachments.depth.iview =
+         dzn_image_view_from_handle(att->imageView);
+      cmdbuf->state.render.attachments.depth.layout = att->imageLayout;
+      cmdbuf->state.render.attachments.depth.resolve.mode = att->resolveMode;
+      cmdbuf->state.render.attachments.depth.resolve.iview =
+         dzn_image_view_from_handle(att->resolveImageView);
+      cmdbuf->state.render.attachments.depth.resolve.layout =
+         att->resolveImageLayout;
+      cmdbuf->state.render.attachments.depth.store_op = att->storeOp;
+   }
+
+   if (pRenderingInfo->pStencilAttachment) {
+      const VkRenderingAttachmentInfo *att = pRenderingInfo->pStencilAttachment;
+
+      cmdbuf->state.render.attachments.stencil.iview =
+         dzn_image_view_from_handle(att->imageView);
+      cmdbuf->state.render.attachments.stencil.layout = att->imageLayout;
+      cmdbuf->state.render.attachments.stencil.resolve.mode = att->resolveMode;
+      cmdbuf->state.render.attachments.stencil.resolve.iview =
+         dzn_image_view_from_handle(att->resolveImageView);
+      cmdbuf->state.render.attachments.stencil.resolve.layout =
+         att->resolveImageLayout;
+      cmdbuf->state.render.attachments.stencil.store_op = att->storeOp;
+   }
+
+   if (pRenderingInfo->pDepthAttachment || pRenderingInfo->pStencilAttachment) {
+      struct dzn_image_view *z_iview =
+         pRenderingInfo->pDepthAttachment ?
+         dzn_image_view_from_handle(pRenderingInfo->pDepthAttachment->imageView) :
+         NULL;
+      struct dzn_image_view *s_iview =
+         pRenderingInfo->pStencilAttachment ?
+         dzn_image_view_from_handle(pRenderingInfo->pStencilAttachment->imageView) :
+         NULL;
+      struct dzn_image_view *iview = z_iview ? z_iview : s_iview;
+      assert(!z_iview || !s_iview || z_iview == s_iview);
+
+      if (iview) {
+         struct dzn_image *img = container_of(iview->vk.image, struct dzn_image, vk);
+
+         zs_handle = dzn_cmd_buffer_get_dsv(cmdbuf, img, &iview->dsv_desc);
+      }
+   }
+
+   ID3D12GraphicsCommandList1_OMSetRenderTargets(cmdbuf->cmdlist,
+                                                 pRenderingInfo->colorAttachmentCount,
+                                                 pRenderingInfo->colorAttachmentCount ? rt_handles : NULL,
+                                                 FALSE, zs_handle.ptr ? &zs_handle : NULL);
+
+   for (uint32_t a = 0; a < pRenderingInfo->colorAttachmentCount; a++) {
+      const VkRenderingAttachmentInfo *att = &pRenderingInfo->pColorAttachments[a];
+      VK_FROM_HANDLE(dzn_image_view, iview, att->imageView);
+
+      if (iview != NULL && att->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
+         dzn_cmd_buffer_clear_attachment(cmdbuf, iview, &att->clearValue,
+                                         VK_IMAGE_ASPECT_COLOR_BIT, 0, ~0, 1,
+                                         &cmdbuf->state.render.area);
+      }
+   }
+
+   if (pRenderingInfo->pDepthAttachment || pRenderingInfo->pStencilAttachment) {
+      const VkRenderingAttachmentInfo *z_att = pRenderingInfo->pDepthAttachment;
+      const VkRenderingAttachmentInfo *s_att = pRenderingInfo->pStencilAttachment;
+      struct dzn_image_view *z_iview = z_att ? dzn_image_view_from_handle(z_att->imageView) : NULL;
+      struct dzn_image_view *s_iview = s_att ? dzn_image_view_from_handle(s_att->imageView) : NULL;
+      struct dzn_image_view *iview = z_iview ? z_iview : s_iview;
+
+      assert(!z_iview || !s_iview || z_iview == s_iview);
+
+      VkImageAspectFlags aspects = 0;
+      VkClearValue clear_val;
+
+      if (z_iview && z_att->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
+         aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
+         clear_val.depthStencil.depth = z_att->clearValue.depthStencil.depth;
+      }
+
+      if (s_iview && s_att->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
+         aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
+         clear_val.depthStencil.stencil = s_att->clearValue.depthStencil.stencil;
+      }
+
+      if (aspects != 0) {
+         dzn_cmd_buffer_clear_attachment(cmdbuf, iview, &clear_val,
+                                         aspects, 0, ~0, 1,
+                                         &cmdbuf->state.render.area);
+      }
+   }
+}
+
+VKAPI_ATTR void VKAPI_CALL
+dzn_CmdEndRendering(VkCommandBuffer commandBuffer)
+{
+   VK_FROM_HANDLE(dzn_cmd_buffer, cmdbuf, commandBuffer);
+
+   for (uint32_t i = 0; i < cmdbuf->state.render.attachments.color_count; i++) {
+      dzn_cmd_buffer_resolve_rendering_attachment(cmdbuf,
+                                                  &cmdbuf->state.render.attachments.colors[i],
+                                                  VK_IMAGE_ASPECT_COLOR_BIT);
+   }
+
+   dzn_cmd_buffer_resolve_rendering_attachment(cmdbuf,
+                                               &cmdbuf->state.render.attachments.depth,
+                                               VK_IMAGE_ASPECT_DEPTH_BIT);
+   dzn_cmd_buffer_resolve_rendering_attachment(cmdbuf,
+                                               &cmdbuf->state.render.attachments.stencil,
+                                               VK_IMAGE_ASPECT_STENCIL_BIT);
+
+   memset(&cmdbuf->state.render, 0, sizeof(cmdbuf->state.render));
+}
+
 VKAPI_ATTR void VKAPI_CALL
 dzn_CmdBindPipeline(VkCommandBuffer commandBuffer,
                     VkPipelineBindPoint pipelineBindPoint,
diff --git a/src/microsoft/vulkan/dzn_device.c b/src/microsoft/vulkan/dzn_device.c
index 0648a082d3d..bf107b1a828 100644
--- a/src/microsoft/vulkan/dzn_device.c
+++ b/src/microsoft/vulkan/dzn_device.c
@@ -78,6 +78,7 @@ dzn_physical_device_get_extensions(struct dzn_physical_device *pdev)
 {
    pdev->vk.supported_extensions = (struct vk_device_extension_table) {
       .KHR_descriptor_update_template        = true,
+      .KHR_dynamic_rendering                 = true,
       .KHR_shader_draw_parameters            = true,
 #ifdef DZN_USE_WSI_PLATFORM
       .KHR_swapchain                         = true,
diff --git a/src/microsoft/vulkan/dzn_pipeline.c b/src/microsoft/vulkan/dzn_pipeline.c
index 403f41971f5..00d6b132eca 100644
--- a/src/microsoft/vulkan/dzn_pipeline.c
+++ b/src/microsoft/vulkan/dzn_pipeline.c
@@ -778,9 +778,13 @@ dzn_graphics_pipeline_create(struct dzn_device *device,
                              const VkAllocationCallbacks *pAllocator,
                              VkPipeline *out)
 {
+   const VkPipelineRenderingCreateInfo *ri = (const VkPipelineRenderingCreateInfo *)
+      vk_find_struct_const(pCreateInfo, PIPELINE_RENDERING_CREATE_INFO);
    VK_FROM_HANDLE(dzn_render_pass, pass, pCreateInfo->renderPass);
    VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout);
-   const struct dzn_subpass *subpass = &pass->subpasses[pCreateInfo->subpass];
+   uint32_t color_count = 0;
+   VkFormat color_fmts[MAX_RTS] = { 0 };
+   VkFormat zs_fmt = VK_FORMAT_UNDEFINED;
    uint32_t stage_mask = 0;
    VkResult ret;
    HRESULT hres = 0;
@@ -841,26 +845,46 @@ dzn_graphics_pipeline_create(struct dzn_device *device,
    dzn_graphics_pipeline_translate_zsa(pipeline, &desc, pCreateInfo);
    dzn_graphics_pipeline_translate_blend(pipeline, &desc, pCreateInfo);
 
-   desc.NumRenderTargets = subpass->color_count;
-   for (uint32_t i = 0; i < subpass->color_count; i++) {
-      uint32_t idx = subpass->colors[i].idx;
+   if (pass) {
+      const struct dzn_subpass *subpass = &pass->subpasses[pCreateInfo->subpass];
+      color_count = subpass->color_count;
+      for (uint32_t i = 0; i < subpass->color_count; i++) {
+         uint32_t idx = subpass->colors[i].idx;
 
-      if (idx == VK_ATTACHMENT_UNUSED) continue;
+         if (idx == VK_ATTACHMENT_UNUSED) continue;
 
-      const struct dzn_attachment *attachment = &pass->attachments[idx];
+         const struct dzn_attachment *attachment = &pass->attachments[idx];
 
+         color_fmts[i] = attachment->format;
+      }
+
+      if (subpass->zs.idx != VK_ATTACHMENT_UNUSED) {
+         const struct dzn_attachment *attachment =
+            &pass->attachments[subpass->zs.idx];
+
+	 zs_fmt = attachment->format;
+      }
+   } else if (ri) {
+      color_count = ri->colorAttachmentCount;
+      memcpy(color_fmts, ri->pColorAttachmentFormats,
+             sizeof(color_fmts[0]) * color_count);
+      if (ri->depthAttachmentFormat != VK_FORMAT_UNDEFINED)
+         zs_fmt = ri->depthAttachmentFormat;
+      else if (ri->stencilAttachmentFormat != VK_FORMAT_UNDEFINED)
+         zs_fmt = ri->stencilAttachmentFormat;
+   }
+
+   desc.NumRenderTargets = color_count;
+   for (uint32_t i = 0; i < color_count; i++) {
       desc.RTVFormats[i] =
-         dzn_image_get_dxgi_format(attachment->format,
+         dzn_image_get_dxgi_format(color_fmts[i],
                                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
                                    VK_IMAGE_ASPECT_COLOR_BIT);
    }
 
-   if (subpass->zs.idx != VK_ATTACHMENT_UNUSED) {
-      const struct dzn_attachment *attachment =
-         &pass->attachments[subpass->zs.idx];
-
+   if (zs_fmt != VK_FORMAT_UNDEFINED) {
       desc.DSVFormat =
-         dzn_image_get_dxgi_format(attachment->format,
+         dzn_image_get_dxgi_format(zs_fmt,
                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
                                    VK_IMAGE_ASPECT_DEPTH_BIT |
                                    VK_IMAGE_ASPECT_STENCIL_BIT);
diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h
index 2ed97056639..8cc7e7f1c55 100644
--- a/src/microsoft/vulkan/dzn_private.h
+++ b/src/microsoft/vulkan/dzn_private.h
@@ -458,11 +458,32 @@ struct dzn_cmd_buffer_push_constant_state {
    uint32_t values[MAX_PUSH_CONSTANT_DWORDS];
 };
 
+struct dzn_rendering_attachment {
+   struct dzn_image_view *iview;
+   VkImageLayout layout;
+   struct {
+      VkResolveModeFlagBits mode;
+      struct dzn_image_view *iview;
+      VkImageLayout layout;
+   } resolve;
+   VkAttachmentStoreOp store_op;
+};
+
+#define MAX_RTS D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT
+
 struct dzn_cmd_buffer_state {
    const struct dzn_pipeline *pipeline;
    struct dzn_descriptor_heap *heaps[NUM_POOL_TYPES];
    struct {
+      VkRenderingFlags flags;
       D3D12_RECT area;
+      uint32_t layer_count;
+      uint32_t view_mask;
+      struct {
+         uint32_t color_count;
+         struct dzn_rendering_attachment colors[MAX_RTS];
+         struct dzn_rendering_attachment depth, stencil;
+      } attachments;
       struct dzn_render_pass *pass;
       uint32_t subpass;
       struct dzn_framebuffer *framebuffer;
@@ -664,7 +685,6 @@ struct dzn_descriptor_update_template {
    const struct dzn_descriptor_update_template_entry *entries;
 };
 
-#define MAX_RTS D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT
 #define MAX_INPUT_ATTACHMENTS 4
 
 struct dzn_subpass {



More information about the mesa-commit mailing list