[Mesa-dev] [PATCH 13/13] anv: Enable CCS for basic cases

Jason Ekstrand jason at jlekstrand.net
Sun Sep 25 16:59:12 UTC 2016


This enables lossless render target compression but only for first mip level
of the first slice and only within a render pass.  At the end of the render
pass it always does a full resolve.

Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
---
 src/intel/vulkan/anv_blorp.c       | 30 ++++++++++++++++++++++++++++
 src/intel/vulkan/anv_device.c      | 40 ++++++++++++++++++++++++++++++++------
 src/intel/vulkan/anv_image.c       |  9 +++++++++
 src/intel/vulkan/anv_private.h     |  2 ++
 src/intel/vulkan/genX_cmd_buffer.c | 17 ++++++++++++++++
 5 files changed, 92 insertions(+), 6 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index 5cc19eb..74f1d80 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -929,3 +929,33 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
 
    blorp_batch_finish(&batch);
 }
+
+void
+anv_cmd_buffer_resolve_framebuffer(struct anv_cmd_buffer *cmd_buffer,
+                                   struct anv_framebuffer *fb)
+{
+   struct blorp_batch batch;
+   blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer);
+
+   for (uint32_t i = 0; i < fb->attachment_count; i++) {
+      struct anv_framebuffer_attachment *fb_att = &fb->attachments[i];
+      const struct anv_image *image = fb_att->view->image;
+
+      if (fb_att->aux_usage != ISL_AUX_USAGE_CCS_E &&
+          fb_att->aux_usage != ISL_AUX_USAGE_CCS_D)
+         continue;
+
+      struct blorp_surf surf;
+      get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT, &surf);
+      surf.aux_surf = &image->aux_surface.isl;
+      surf.aux_addr = (struct blorp_address) {
+         .buffer = image->bo,
+         .offset = image->offset + image->aux_surface.offset,
+      };
+      surf.aux_usage = fb_att->aux_usage;
+
+      blorp_ccs_resolve(&batch, &surf, fb_att->view->isl.format);
+   }
+
+   blorp_batch_finish(&batch);
+}
diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index 3d4b783..8c68e94 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -1765,6 +1765,30 @@ void anv_DestroySampler(
    anv_free2(&device->alloc, pAllocator, sampler);
 }
 
+static enum isl_aux_usage
+get_fb_attachment_aux_usage(struct anv_device *device,
+                            struct anv_framebuffer *fb,
+                            struct anv_framebuffer_attachment *fb_att)
+{
+   if (fb_att->view->image->aux_surface.isl.size == 0)
+      return ISL_AUX_USAGE_NONE; /* No aux surface */
+
+   /* This is a color buffer, it had better be CCS */
+   assert(fb_att->view->image->aux_surface.isl.usage & ISL_SURF_USAGE_CCS_BIT);
+
+   if (!isl_format_supports_lossless_compression(&device->info,
+                                                 fb_att->view->isl.format))
+      return ISL_AUX_USAGE_NONE; /* Unsupported format */
+
+   if (fb->layers > 1 || fb_att->view->isl.base_array_layer > 0)
+      return ISL_AUX_USAGE_NONE; /* Multi-layered CCS not yet supported */
+
+   if (fb_att->view->isl.base_level > 0)
+      return ISL_AUX_USAGE_NONE; /* Multi-LOD CCS not yet supported */
+
+   return ISL_AUX_USAGE_CCS_E;
+}
+
 VkResult anv_CreateFramebuffer(
     VkDevice                                    _device,
     const VkFramebufferCreateInfo*              pCreateInfo,
@@ -1783,6 +1807,10 @@ VkResult anv_CreateFramebuffer(
    if (framebuffer == NULL)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
+   framebuffer->width = pCreateInfo->width;
+   framebuffer->height = pCreateInfo->height;
+   framebuffer->layers = pCreateInfo->layers;
+
    framebuffer->attachment_count = pCreateInfo->attachmentCount;
    unsigned color_count = 0;
    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
@@ -1802,10 +1830,14 @@ VkResult anv_CreateFramebuffer(
                            device->isl_dev.ss.align);
    unsigned color_idx = 0;
    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
-      struct anv_image_view *iview = framebuffer->attachments[i].view;
+      struct anv_framebuffer_attachment *fb_att = &framebuffer->attachments[i];
+      struct anv_image_view *iview = fb_att->view;
+
       if (iview->image->aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
          const uint16_t offset = (color_idx++) * device->isl_dev.ss.align;
-         framebuffer->attachments[i].rt_state_offset = offset;
+         fb_att->rt_state_offset = offset;
+         fb_att->aux_usage =
+            get_fb_attachment_aux_usage(device, framebuffer, fb_att);
 
          struct isl_view isl_view = iview->isl;
          isl_view.usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
@@ -1822,10 +1854,6 @@ VkResult anv_CreateFramebuffer(
    if (device->info.has_llc)
       anv_state_clflush(framebuffer->surface_states);
 
-   framebuffer->width = pCreateInfo->width;
-   framebuffer->height = pCreateInfo->height;
-   framebuffer->layers = pCreateInfo->layers;
-
    *pFramebuffer = anv_framebuffer_to_handle(framebuffer);
 
    return VK_SUCCESS;
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
index 405b923..ff99126 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -169,6 +169,15 @@ make_surface(const struct anv_device *dev,
 
    add_surface(image, anv_surf);
 
+   if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
+      if (dev->info.gen >= 9 && vk_info->samples == 1) {
+         ok = isl_surf_get_ccs_surf(&dev->isl_dev, &anv_surf->isl,
+                                    &image->aux_surface.isl);
+         if (ok)
+            add_surface(image, &image->aux_surface);
+      }
+   }
+
    return VK_SUCCESS;
 }
 
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 5c24c37..5f03ae0 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -1405,6 +1405,8 @@ anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer);
 
 void anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer);
 void anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer);
+void anv_cmd_buffer_resolve_framebuffer(struct anv_cmd_buffer *cmd_buffer,
+                                        struct anv_framebuffer *fb);
 
 const struct anv_image_view *
 anv_cmd_buffer_get_depth_stencil_view(const struct anv_cmd_buffer *cmd_buffer);
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index 90700e7..0962118 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -1346,6 +1346,23 @@ void genX(CmdEndRenderPass)(
 
    anv_cmd_buffer_resolve_subpass(cmd_buffer);
 
+   /* From the Sky Lake PRM Vol. 7, "Render Target Resolve":
+    *
+    *    "When performing a render target resolve, PIPE_CONTROL with end of
+    *    pipe sync must be delivered."
+    *
+    * By "end of pipe sync" it appears that they mean a pixel scoreboard stall
+    * This makes sense because the resolve operation probably needs the CCS to
+    * be fully valid before it looks at it.
+    */
+   anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
+      pc.StallAtPixelScoreboard     = true;
+      pc.CommandStreamerStallEnable = true;
+   }
+
+   anv_cmd_buffer_resolve_framebuffer(cmd_buffer,
+                                      cmd_buffer->state.framebuffer);
+
 #ifndef NDEBUG
    anv_dump_add_framebuffer(cmd_buffer, cmd_buffer->state.framebuffer);
 #endif
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list