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 <ja...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev