[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