<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Nov 8, 2016 at 12:21 AM, Pohjolainen, Topi <span dir="ltr"><<a href="mailto:topi.pohjolainen@gmail.com" target="_blank">topi.pohjolainen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Title says: "anv: Add initial for Sky Lake color compression". Did you mean<br>
to have something after "initial"?<span class=""><br></span></blockquote><div><br></div><div>Yeah, "support" should probably go in there<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
On Fri, Oct 28, 2016 at 02:17:09AM -0700, Jason Ekstrand wrote:<br>
> This commit adds basic support for color compression. For the moment,<br>
> color compression is only enabled within a render pass and a full resolve<br>
> is done before the render pass finishes. All texturing operations still<br>
> happen with CCS disabled.<br>
<br>
</span>I'm not that familiar with all the vulkan concepts so far and need to ask a<br>
few things. In this patch CCS_E is enabled whenever there is suitable render<br>
target. For surfaces of the type VK_DESCRIPTOR_TYPE_INPUT_<wbr>ATTACHMENT and<br>
VK_DESCRIPTOR_TYPE_STORAGE_<wbr>IMAGE aux is explicitly disabled. Does this mean<br>
that it is impossible to have one of these surfaces as render target in<br>
the same pass (and having compression turned on for writing)?<br></blockquote><div><br></div><div>No, not quite. In this patch, we always do a full resolve at the end of the render pass. Since input attachments aren't really supported yet (my next task), those aren't a problem. Also, you can't bind one of your render pass attachments as a storage image or texture so those will never be used while it's in an unresolved state.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Otherwise this patch looks good to me.<br>
<div><div class="h5"><br>
><br>
> Signed-off-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
> ---<br>
> src/intel/vulkan/anv_blorp.c | 139 +++++++++++++++++++++++++++++-<wbr>-------<br>
> src/intel/vulkan/anv_image.c | 17 +++--<br>
> src/intel/vulkan/anv_private.h | 1 +<br>
> src/intel/vulkan/genX_cmd_<wbr>buffer.c | 50 ++++++++++++-<br>
> 4 files changed, 171 insertions(+), 36 deletions(-)<br>
><br>
> diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c<br>
> index 0e70e9b..bf317c7 100644<br>
> --- a/src/intel/vulkan/anv_blorp.c<br>
> +++ b/src/intel/vulkan/anv_blorp.c<br>
> @@ -1179,52 +1179,131 @@ void anv_CmdResolveImage(<br>
> blorp_batch_finish(&batch);<br>
> }<br>
><br>
> +static void<br>
> +ccs_resolve_attachment(struct anv_cmd_buffer *cmd_buffer,<br>
> + struct blorp_batch *batch,<br>
> + uint32_t att)<br>
> +{<br>
> + struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;<br>
> + struct anv_attachment_state *att_state =<br>
> + &cmd_buffer->state.<wbr>attachments[att];<br>
> +<br>
> + assert(att_state->aux_usage != ISL_AUX_USAGE_CCS_D);<br>
> + if (att_state->aux_usage != ISL_AUX_USAGE_CCS_E)<br>
> + return; /* Nothing to resolve */<br>
> +<br>
> + struct anv_render_pass *pass = cmd_buffer->state.pass;<br>
> + struct anv_subpass *subpass = cmd_buffer->state.subpass;<br>
> + unsigned subpass_idx = subpass - pass->subpasses;<br>
> + assert(subpass_idx < pass->subpass_count);<br>
> +<br>
> + /* Scan forward to see what all ways this attachment will be used.<br>
> + * Ideally, we would like to resolve in the same subpass as the last write<br>
> + * of a particular attachment. That way we only resolve once but it's<br>
> + * still hot in the cache.<br>
> + */<br>
> + for (uint32_t s = subpass_idx + 1; s < pass->subpass_count; s++) {<br>
> + enum anv_subpass_usage usage = pass->attachments[att].<wbr>subpass_usage[s];<br>
<br>
</div></div>I'm wondering if this holds?<br>
<br>
assert(!(usage & ANV_SUBPASS_USAGE_INPUT));<br>
<div><div class="h5"><br>
> +<br>
> + if (usage & (ANV_SUBPASS_USAGE_DRAW | ANV_SUBPASS_USAGE_RESOLVE_DST)<wbr>) {<br>
> + /* We found another subpass that draws to this attachment. We'll<br>
> + * wait to resolve until then.<br>
> + */<br>
> + return;<br>
> + }<br>
> + }<br>
> +<br>
> + struct anv_image_view *iview = fb->attachments[att];<br>
> + const struct anv_image *image = iview->image;<br>
> + assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);<br>
> +<br>
> + struct blorp_surf surf;<br>
> + get_blorp_surf_for_anv_image(<wbr>image, VK_IMAGE_ASPECT_COLOR_BIT, &surf);<br>
> + surf.aux_surf = &image->aux_surface.isl;<br>
> + surf.aux_addr = (struct blorp_address) {<br>
> + .buffer = image->bo,<br>
> + .offset = image->offset + image->aux_surface.offset,<br>
> + };<br>
> + surf.aux_usage = att_state->aux_usage;<br>
> +<br>
> + for (uint32_t layer = 0; layer < fb->layers; layer++) {<br>
> + blorp_ccs_resolve(batch, &surf,<br>
> + iview->isl.base_level,<br>
> + iview->isl.base_array_layer + layer,<br>
> + iview->isl.format,<br>
> + BLORP_FAST_CLEAR_OP_RESOLVE_<wbr>FULL);<br>
> + }<br>
> +}<br>
> +<br>
> void<br>
> anv_cmd_buffer_resolve_<wbr>subpass(struct anv_cmd_buffer *cmd_buffer)<br>
> {<br>
> struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;<br>
> struct anv_subpass *subpass = cmd_buffer->state.subpass;<br>
><br>
> - if (!subpass->has_resolve)<br>
> - return;<br>
><br>
> struct blorp_batch batch;<br>
> blorp_batch_init(&cmd_buffer-><wbr>device->blorp, &batch, cmd_buffer, 0);<br>
><br>
> + /* From the Sky Lake PRM Vol. 7, "Render Target Resolve":<br>
> + *<br>
> + * "When performing a render target resolve, PIPE_CONTROL with end of<br>
> + * pipe sync must be delivered."<br>
> + */<br>
> + cmd_buffer->state.pending_<wbr>pipe_bits |= ANV_PIPE_CS_STALL_BIT;<br>
> +<br>
> for (uint32_t i = 0; i < subpass->color_count; ++i) {<br>
> - uint32_t src_att = subpass->color_attachments[i];<br>
> - uint32_t dst_att = subpass->resolve_attachments[<wbr>i];<br>
> + ccs_resolve_attachment(cmd_<wbr>buffer, &batch,<br>
> + subpass->color_attachments[i])<wbr>;<br>
> + }<br>
><br>
> - if (dst_att == VK_ATTACHMENT_UNUSED)<br>
> - continue;<br>
> + if (subpass->has_resolve) {<br>
> + for (uint32_t i = 0; i < subpass->color_count; ++i) {<br>
> + uint32_t src_att = subpass->color_attachments[i];<br>
> + uint32_t dst_att = subpass->resolve_attachments[<wbr>i];<br>
> +<br>
> + if (dst_att == VK_ATTACHMENT_UNUSED)<br>
> + continue;<br>
> +<br>
> + if (cmd_buffer->state.<wbr>attachments[dst_att].pending_<wbr>clear_aspects) {<br>
> + /* FINISHME(perf): Skip clears for resolve attachments.<br>
> + *<br>
> + * From the Vulkan 1.0 spec:<br>
> + *<br>
> + * If the first use of an attachment in a render pass is as a<br>
> + * resolve attachment, then the loadOp is effectively ignored<br>
> + * as the resolve is guaranteed to overwrite all pixels in the<br>
> + * render area.<br>
> + */<br>
> + cmd_buffer->state.attachments[<wbr>dst_att].pending_clear_aspects = 0;<br>
> + }<br>
><br>
> - if (cmd_buffer->state.<wbr>attachments[dst_att].pending_<wbr>clear_aspects) {<br>
> - /* FINISHME(perf): Skip clears for resolve attachments.<br>
> - *<br>
> - * From the Vulkan 1.0 spec:<br>
> - *<br>
> - * If the first use of an attachment in a render pass is as a<br>
> - * resolve attachment, then the loadOp is effectively ignored<br>
> - * as the resolve is guaranteed to overwrite all pixels in the<br>
> - * render area.<br>
> - */<br>
> - cmd_buffer->state.attachments[<wbr>dst_att].pending_clear_aspects = 0;<br>
> - }<br>
> + struct anv_image_view *src_iview = fb->attachments[src_att];<br>
> + struct anv_image_view *dst_iview = fb->attachments[dst_att];<br>
><br>
> - struct anv_image_view *src_iview = fb->attachments[src_att];<br>
> - struct anv_image_view *dst_iview = fb->attachments[dst_att];<br>
> + const VkRect2D render_area = cmd_buffer->state.render_area;<br>
><br>
> - const VkRect2D render_area = cmd_buffer->state.render_area;<br>
> + assert(src_iview->aspect_mask == dst_iview->aspect_mask);<br>
> + resolve_image(&batch, src_iview->image,<br>
> + src_iview->isl.base_level,<br>
> + src_iview->isl.base_array_<wbr>layer,<br>
> + dst_iview->image,<br>
> + dst_iview->isl.base_level,<br>
> + dst_iview->isl.base_array_<wbr>layer,<br>
> + src_iview->aspect_mask,<br>
> + render_area.offset.x, render_area.offset.y,<br>
> + render_area.offset.x, render_area.offset.y,<br>
> + render_area.extent.width, render_area.extent.height);<br>
><br>
> - assert(src_iview->aspect_mask == dst_iview->aspect_mask);<br>
> - resolve_image(&batch, src_iview->image,<br>
> - src_iview->isl.base_level, src_iview->isl.base_array_<wbr>layer,<br>
> - dst_iview->image,<br>
> - dst_iview->isl.base_level, dst_iview->isl.base_array_<wbr>layer,<br>
> - src_iview->aspect_mask,<br>
> - render_area.offset.x, render_area.offset.y,<br>
> - render_area.offset.x, render_area.offset.y,<br>
> - render_area.extent.width, render_area.extent.height);<br>
> + /* From the Sky Lake PRM Vol. 7, "Render Target Resolve":<br>
> + *<br>
> + * "When performing a render target resolve, PIPE_CONTROL with end<br>
> + * of pipe sync must be delivered."<br>
> + */<br>
> + cmd_buffer->state.pending_<wbr>pipe_bits |= ANV_PIPE_CS_STALL_BIT;<br>
> +<br>
> + ccs_resolve_attachment(cmd_<wbr>buffer, &batch, dst_att);<br>
> + }<br>
> }<br>
><br>
> blorp_batch_finish(&batch);<br>
> diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c<br>
> index bdf8bca..4bef5ce 100644<br>
> --- a/src/intel/vulkan/anv_image.c<br>
> +++ b/src/intel/vulkan/anv_image.c<br>
> @@ -176,23 +176,32 @@ make_surface(const struct anv_device *dev,<br>
><br>
> /* Add a HiZ surface to a depth buffer that will be used for rendering.<br>
> */<br>
> - if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT &&<br>
> - (image->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_<wbr>ATTACHMENT_BIT)) {<br>
> -<br>
> + if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {<br>
> /* Allow the user to control HiZ enabling. Disable by default on gen7<br>
> * because resolves are not currently implemented pre-BDW.<br>
> */<br>
> - if (!env_var_as_boolean("INTEL_<wbr>VK_HIZ", dev->info.gen >= 8)) {<br>
> + if (!(image->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_<wbr>ATTACHMENT_BIT)) {<br>
> + /* It will never be used as an attachment, HiZ is pointless. */<br>
> + } else if (!env_var_as_boolean("INTEL_<wbr>VK_HIZ", dev->info.gen >= 8)) {<br>
> anv_finishme("Implement gen7 HiZ");<br>
> } else if (vk_info->mipLevels > 1) {<br>
> anv_finishme("Test multi-LOD HiZ");<br>
> } else if (dev->info.gen == 8 && vk_info->samples > 1) {<br>
> anv_finishme("Test gen8 multisampled HiZ");<br>
> } else {<br>
> + assert(image->aux_surface.isl.<wbr>size == 0);<br>
> isl_surf_get_hiz_surf(&dev-><wbr>isl_dev, &image->depth_surface.isl,<br>
> &image->aux_surface.isl);<br>
> add_surface(image, &image->aux_surface);<br>
> }<br>
> + } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT) {<br>
> + if (dev->info.gen >= 9 && vk_info->samples == 1) {<br>
> + assert(image->aux_surface.isl.<wbr>size == 0);<br>
> + ok = isl_surf_get_ccs_surf(&dev-><wbr>isl_dev, &anv_surf->isl,<br>
> + &image->aux_surface.isl);<br>
> + if (ok)<br>
> + add_surface(image, &image->aux_surface);<br>
> + }<br>
> }<br>
><br>
> return VK_SUCCESS;<br>
> diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
> index 531f2d1..6e8f5e0 100644<br>
> --- a/src/intel/vulkan/anv_<wbr>private.h<br>
> +++ b/src/intel/vulkan/anv_<wbr>private.h<br>
> @@ -1059,6 +1059,7 @@ void anv_dynamic_state_copy(struct anv_dynamic_state *dest,<br>
> * The clear value is valid only if there exists a pending clear.<br>
> */<br>
> struct anv_attachment_state {<br>
> + enum isl_aux_usage aux_usage;<br>
> struct anv_state color_rt_state;<br>
><br>
> VkImageAspectFlags pending_clear_aspects;<br>
> diff --git a/src/intel/vulkan/genX_cmd_<wbr>buffer.c b/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
> index a87e5a3..3b9f946 100644<br>
> --- a/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
> +++ b/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
> @@ -165,6 +165,7 @@ add_surface_state_reloc(struct anv_cmd_buffer *cmd_buffer,<br>
> static void<br>
> add_image_view_relocs(struct anv_cmd_buffer *cmd_buffer,<br>
> const struct anv_image_view *iview,<br>
> + enum isl_aux_usage aux_usage,<br>
> struct anv_state state)<br>
> {<br>
> const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;<br>
> @@ -172,6 +173,41 @@ add_image_view_relocs(struct anv_cmd_buffer *cmd_buffer,<br>
> anv_reloc_list_add(&cmd_<wbr>buffer->surface_relocs, &cmd_buffer->pool->alloc,<br>
> state.offset + isl_dev->ss.addr_offset,<br>
> iview->bo, iview->offset);<br>
> +<br>
> + if (aux_usage != ISL_AUX_USAGE_NONE) {<br>
> + uint32_t aux_offset = iview->offset + iview->image->aux_surface.<wbr>offset;<br>
> +<br>
> + /* On gen7 and prior, the bottom 12 bits of the MCS base address are<br>
> + * used to store other information. This should be ok, however, because<br>
> + * surface buffer addresses are always 4K page alinged.<br>
> + */<br>
> + assert((aux_offset & 0xfff) == 0);<br>
> + uint32_t *aux_addr_dw = state.map + isl_dev->ss.aux_addr_offset;<br>
> + aux_offset += *aux_addr_dw & 0xfff;<br>
> +<br>
> + anv_reloc_list_add(&cmd_<wbr>buffer->surface_relocs, &cmd_buffer->pool->alloc,<br>
> + state.offset + isl_dev->ss.aux_addr_offset,<br>
> + iview->bo, aux_offset);<br>
> + }<br>
> +}<br>
> +<br>
> +static enum isl_aux_usage<br>
> +fb_attachment_get_aux_usage(<wbr>struct anv_device *device,<br>
> + struct anv_framebuffer *fb,<br>
> + uint32_t attachment)<br>
> +{<br>
> + struct anv_image_view *iview = fb->attachments[attachment];<br>
> +<br>
> + if (iview->image->aux_surface.<wbr>isl.size == 0)<br>
> + return ISL_AUX_USAGE_NONE; /* No aux surface */<br>
> +<br>
> + assert(iview->image->aux_<wbr>surface.isl.usage & ISL_SURF_USAGE_CCS_BIT);<br>
> +<br>
> + if (isl_format_supports_lossless_<wbr>compression(&device->info,<br>
> + iview->isl.format))<br>
> + return ISL_AUX_USAGE_CCS_E;<br>
> +<br>
> + return ISL_AUX_USAGE_NONE;<br>
> }<br>
><br>
> /**<br>
> @@ -293,16 +329,24 @@ genX(cmd_buffer_setup_<wbr>attachments)(struct anv_cmd_buffer *cmd_buffer,<br>
> assert(iview->image->vk_format == att->format);<br>
><br>
> if (att_aspects == VK_IMAGE_ASPECT_COLOR_BIT) {<br>
> + state->attachments[i].aux_<wbr>usage =<br>
> + fb_attachment_get_aux_usage(<wbr>cmd_buffer->device, framebuffer, i);<br>
> +<br>
> struct isl_view view = iview->isl;<br>
> view.usage |= ISL_SURF_USAGE_RENDER_TARGET_<wbr>BIT;<br>
> isl_surf_fill_state(isl_dev,<br>
> state->attachments[i].color_<wbr>rt_state.map,<br>
> .surf = &iview->image->color_surface.<wbr>isl,<br>
> .view = &view,<br>
> + .aux_surf = &iview->image->aux_surface.<wbr>isl,<br>
> + .aux_usage = state->attachments[i].aux_<wbr>usage,<br>
> .mocs = cmd_buffer->device->default_<wbr>mocs);<br>
><br>
> add_image_view_relocs(cmd_<wbr>buffer, iview,<br>
> + state->attachments[i].aux_<wbr>usage,<br>
> state->attachments[i].color_<wbr>rt_state);<br>
> + } else {<br>
> + state->attachments[i].aux_<wbr>usage = ISL_AUX_USAGE_NONE;<br>
> }<br>
> }<br>
><br>
> @@ -912,13 +956,15 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,<br>
> case VK_DESCRIPTOR_TYPE_INPUT_<wbr>ATTACHMENT:<br>
> surface_state = desc->image_view->sampler_<wbr>surface_state;<br>
> assert(surface_state.alloc_<wbr>size);<br>
> - add_image_view_relocs(cmd_<wbr>buffer, desc->image_view, surface_state);<br>
> + add_image_view_relocs(cmd_<wbr>buffer, desc->image_view,<br>
> + ISL_AUX_USAGE_NONE, surface_state);<br>
> break;<br>
><br>
> case VK_DESCRIPTOR_TYPE_STORAGE_<wbr>IMAGE: {<br>
> surface_state = desc->image_view->storage_<wbr>surface_state;<br>
> assert(surface_state.alloc_<wbr>size);<br>
> - add_image_view_relocs(cmd_<wbr>buffer, desc->image_view, surface_state);<br>
> + add_image_view_relocs(cmd_<wbr>buffer, desc->image_view,<br>
> + ISL_AUX_USAGE_NONE, surface_state);<br>
><br>
> struct brw_image_param *image_param =<br>
> &cmd_buffer->state.push_<wbr>constants[stage]->images[<wbr>image++];<br>
> --<br>
> 2.5.0.400.gff86faf<br>
><br>
</div></div>> ______________________________<wbr>_________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</blockquote></div><br></div></div>