[Mesa-dev] [PATCH v2 10/11] anv: enable multiple planes per image/imageView
Jason Ekstrand
jason at jlekstrand.net
Wed Oct 4 01:16:06 UTC 2017
On Tue, Oct 3, 2017 at 9:29 AM, Lionel Landwerlin <
lionel.g.landwerlin at intel.com> wrote:
> This change introduce the concept of planes for image & views. It
> matches the planes available in new formats.
>
> We also refactor depth & stencil support through the usage of planes
> for the sake of uniformity. In the backend (genX_cmd_buffer.c) we have
> to take some care though with regard to auxilliary surfaces.
> Multiplanar color buffers can have multiple auxilliary surfaces but
> depth & stencil share the same HiZ one (only store in the depth
> plane).
>
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
> ---
> src/intel/vulkan/anv_blorp.c | 302 ++++++++++++------
> src/intel/vulkan/anv_dump.c | 17 +-
> src/intel/vulkan/anv_formats.c | 3 +-
> src/intel/vulkan/anv_image.c | 632 +++++++++++++++++++++++-------
> -------
> src/intel/vulkan/anv_intel.c | 4 +-
> src/intel/vulkan/anv_private.h | 244 ++++++++++----
> src/intel/vulkan/anv_wsi.c | 8 +-
> src/intel/vulkan/gen8_cmd_buffer.c | 2 +-
> src/intel/vulkan/genX_cmd_buffer.c | 312 ++++++++++--------
> 9 files changed, 985 insertions(+), 539 deletions(-)
>
> diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
> index 72f482625aa..a181630a2f9 100644
> --- a/src/intel/vulkan/anv_blorp.c
> +++ b/src/intel/vulkan/anv_blorp.c
> @@ -177,30 +177,34 @@ get_blorp_surf_for_anv_buffer(struct anv_device
> *device,
>
> static void
> get_blorp_surf_for_anv_image(const struct anv_image *image,
> + uint32_t plane,
> VkImageAspectFlags aspect,
>
Ok, maybe I'm being a bit dense, but doesn't the aspect imply the plane?
Why can't we just use anv_image_aspect_to_plane here? That would reduce
the churn by a good bit.
> enum isl_aux_usage aux_usage,
> struct blorp_surf *blorp_surf)
> {
> + /* For the stencil surface aux_usage is always NONE. */
> if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT ||
> aux_usage == ISL_AUX_USAGE_HIZ)
> aux_usage = ISL_AUX_USAGE_NONE;
>
> - const struct anv_surface *surface =
> - anv_image_get_surface_for_aspect_mask(image, aspect);
> + const struct anv_surface *surface = &image->planes[plane].surface;
>
> *blorp_surf = (struct blorp_surf) {
> .surf = &surface->isl,
> .addr = {
> - .buffer = image->bo,
> - .offset = image->offset + surface->offset,
> + .buffer = image->planes[plane].bo,
> + .offset = image->planes[plane].bo_offset + surface->offset,
> },
> };
>
> if (aux_usage != ISL_AUX_USAGE_NONE) {
> - blorp_surf->aux_surf = &image->aux_surface.isl,
> + const struct anv_surface *aux_surface =
> + &image->planes[plane].aux_surface;
> +
> + blorp_surf->aux_surf = &aux_surface->isl,
> blorp_surf->aux_addr = (struct blorp_address) {
> - .buffer = image->bo,
> - .offset = image->offset + image->aux_surface.offset,
> + .buffer = image->planes[plane].bo,
> + .offset = image->planes[plane].bo_offset + aux_surface->offset,
> };
> blorp_surf->aux_usage = aux_usage;
> }
> @@ -249,17 +253,44 @@ void anv_CmdCopyImage(
> anv_get_layerCount(src_image,
> &pRegions[r].srcSubresource));
> }
>
> - assert(pRegions[r].srcSubresource.aspectMask ==
> - pRegions[r].dstSubresource.aspectMask);
> -
> - uint32_t a;
> - for_each_bit(a, pRegions[r].dstSubresource.aspectMask) {
> - VkImageAspectFlagBits aspect = (1 << a);
> -
> + VkImageAspectFlags src_mask = pRegions[r].srcSubresource.
> aspectMask,
> + dst_mask = pRegions[r].dstSubresource.aspectMask;
> +
> + assert(anv_image_aspects_compatible(src_mask, dst_mask));
> +
> + if (_mesa_bitcount(src_mask) > 1) {
> + uint32_t plane, bit_aspect;
> + anv_foreach_plane_aspect_bit(plane, bit_aspect, src_mask,
> + src_image->aspects) {
> + struct blorp_surf src_surf, dst_surf;
> + get_blorp_surf_for_anv_image(src_image, plane, 1UL <<
> bit_aspect,
> + src_image->planes[plane].aux_
> usage,
> + &src_surf);
> + get_blorp_surf_for_anv_image(dst_image, plane, 1UL <<
> bit_aspect,
> + dst_image->planes[plane].aux_
> usage,
> + &dst_surf);
> +
> + for (unsigned i = 0; i < layer_count; i++) {
> + blorp_copy(&batch, &src_surf, pRegions[r].srcSubresource.
> mipLevel,
> + src_base_layer + i,
> + &dst_surf, pRegions[r].dstSubresource.mipLevel,
> + dst_base_layer + i,
> + srcOffset.x, srcOffset.y,
> + dstOffset.x, dstOffset.y,
> + extent.width, extent.height);
> + }
> + }
> + } else {
> + uint32_t src_plane = anv_image_aspect_to_plane(src_
> image->aspects,
> + src_mask),
> + dst_plane = anv_image_aspect_to_plane(dst_image->aspects,
> + dst_mask);
> struct blorp_surf src_surf, dst_surf;
> - get_blorp_surf_for_anv_image(src_image, aspect,
> src_image->aux_usage,
> + get_blorp_surf_for_anv_image(src_image, src_plane, src_mask,
> + src_image->planes[src_plane].
> aux_usage,
> &src_surf);
> - get_blorp_surf_for_anv_image(dst_image, aspect,
> dst_image->aux_usage,
> + get_blorp_surf_for_anv_image(dst_image, dst_plane, dst_mask,
> + dst_image->planes[dst_plane].
> aux_usage,
> &dst_surf);
>
> for (unsigned i = 0; i < layer_count; i++) {
> @@ -307,8 +338,10 @@ copy_buffer_to_image(struct anv_cmd_buffer
> *cmd_buffer,
>
> for (unsigned r = 0; r < regionCount; r++) {
> const VkImageAspectFlags aspect = pRegions[r].imageSubresource.
> aspectMask;
> + uint32_t plane = anv_image_aspect_to_plane(anv_image->aspects,
> aspect);
>
> - get_blorp_surf_for_anv_image(anv_image, aspect,
> anv_image->aux_usage,
> + get_blorp_surf_for_anv_image(anv_image, plane, aspect,
> + anv_image->planes[plane].aux_usage,
> &image.surf);
> image.offset =
> anv_sanitize_image_offset(anv_image->type,
> pRegions[r].imageOffset);
> @@ -455,10 +488,15 @@ void anv_CmdBlitImage(
> const VkImageSubresourceLayers *src_res =
> &pRegions[r].srcSubresource;
> const VkImageSubresourceLayers *dst_res =
> &pRegions[r].dstSubresource;
>
> - get_blorp_surf_for_anv_image(src_image, src_res->aspectMask,
> - src_image->aux_usage, &src);
> - get_blorp_surf_for_anv_image(dst_image, dst_res->aspectMask,
> - dst_image->aux_usage, &dst);
> + const uint32_t src_plane = anv_image_aspect_to_plane(src_
> image->aspects,
> +
> src_res->aspectMask),
> + dst_plane = anv_image_aspect_to_plane(dst_image->aspects,
> + dst_res->aspectMask);
> +
> + get_blorp_surf_for_anv_image(src_image, src_plane,
> src_res->aspectMask,
> + src_image->planes[src_plane].aux_usage,
> &src);
> + get_blorp_surf_for_anv_image(dst_image, dst_plane,
> dst_res->aspectMask,
> + dst_image->planes[dst_plane].aux_usage,
> &dst);
>
> struct anv_format_plane src_format =
> anv_get_plane_format(&cmd_buffer->device->info,
> src_image->vk_format,
> @@ -749,15 +787,19 @@ void anv_CmdClearColorImage(
> struct blorp_batch batch;
> blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
> - struct blorp_surf surf;
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> - image->aux_usage, &surf);
>
> for (unsigned r = 0; r < rangeCount; r++) {
> if (pRanges[r].aspectMask == 0)
> continue;
>
> - assert(pRanges[r].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
> + assert(pRanges[r].aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> +
> + const uint32_t plane = anv_image_aspect_to_plane(image->aspects,
> +
> pRanges[r].aspectMask);
> +
> + struct blorp_surf surf;
> + get_blorp_surf_for_anv_image(image, plane, pRanges[r].aspectMask,
> + image->planes[plane].aux_usage,
> &surf);
>
> struct anv_format_plane src_format =
> anv_get_plane_format(&cmd_buffer->device->info,
> image->vk_format,
> @@ -803,14 +845,20 @@ void anv_CmdClearDepthStencilImage(
>
> struct blorp_surf depth, stencil;
> if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_DEPTH_BIT,
> + uint32_t depth_plane =
> + anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_DEPTH_BIT);
> + get_blorp_surf_for_anv_image(image, depth_plane,
> + VK_IMAGE_ASPECT_DEPTH_BIT,
> ISL_AUX_USAGE_NONE, &depth);
> } else {
> memset(&depth, 0, sizeof(depth));
> }
>
> if (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_STENCIL_BIT,
> + uint32_t stencil_plane =
> + anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_STENCIL_BIT);
> + get_blorp_surf_for_anv_image(image, stencil_plane,
> + VK_IMAGE_ASPECT_STENCIL_BIT,
> ISL_AUX_USAGE_NONE, &stencil);
> } else {
> memset(&stencil, 0, sizeof(stencil));
> @@ -1044,7 +1092,7 @@ void anv_CmdClearAttachments(
> BLORP_BATCH_NO_EMIT_DEPTH_STENCIL);
>
> for (uint32_t a = 0; a < attachmentCount; ++a) {
> - if (pAttachments[a].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
> + if (pAttachments[a].aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> clear_color_attachment(cmd_buffer, &batch,
> &pAttachments[a],
> rectCount, pRects);
> @@ -1130,7 +1178,7 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer
> *cmd_buffer)
> struct anv_image_view *iview = fb->attachments[a];
> const struct anv_image *image = iview->image;
> struct blorp_surf surf;
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> + get_blorp_surf_for_anv_image(image, 0, VK_IMAGE_ASPECT_COLOR_BIT,
> att_state->aux_usage, &surf);
>
> if (att_state->fast_clear) {
> @@ -1155,24 +1203,26 @@ anv_cmd_buffer_clear_subpass(struct
> anv_cmd_buffer *cmd_buffer)
> cmd_buffer->state.pending_pipe_bits |=
> ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT |
> ANV_PIPE_CS_STALL_BIT;
>
> - blorp_fast_clear(&batch, &surf, iview->isl.format,
> - iview->isl.base_level,
> - iview->isl.base_array_layer, fb->layers,
> - render_area.offset.x, render_area.offset.y,
> - render_area.offset.x + render_area.extent.width,
> - render_area.offset.y +
> render_area.extent.height);
> + for (unsigned p = 0; p < iview->n_planes; p++)
> + blorp_fast_clear(&batch, &surf, iview->planes[p].isl.format,
> + iview->planes[p].isl.base_level,
> + iview->planes[p].isl.base_array_layer,
> fb->layers,
> + render_area.offset.x, render_area.offset.y,
> + render_area.offset.x +
> render_area.extent.width,
> + render_area.offset.y +
> render_area.extent.height);
>
> cmd_buffer->state.pending_pipe_bits |=
> ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT |
> ANV_PIPE_CS_STALL_BIT;
> } else {
> - blorp_clear(&batch, &surf, iview->isl.format,
> - anv_swizzle_for_render(iview->isl.swizzle),
> - iview->isl.base_level,
> - iview->isl.base_array_layer, fb->layers,
> - render_area.offset.x, render_area.offset.y,
> - render_area.offset.x + render_area.extent.width,
> - render_area.offset.y + render_area.extent.height,
> - vk_to_isl_color(att_state->clear_value.color),
> NULL);
> + for (unsigned p = 0; p < iview->n_planes; p++)
> + blorp_clear(&batch, &surf, iview->planes[p].isl.format,
> + anv_swizzle_for_render(iview->
> planes[p].isl.swizzle),
> + iview->planes[p].isl.base_level,
> + iview->planes[p].isl.base_array_layer,
> fb->layers,
> + render_area.offset.x, render_area.offset.y,
> + render_area.offset.x + render_area.extent.width,
> + render_area.offset.y + render_area.extent.height,
> + vk_to_isl_color(att_state->clear_value.color),
> NULL);
> }
>
> att_state->pending_clear_aspects = 0;
> @@ -1207,7 +1257,7 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer
> *cmd_buffer)
> * a stencil clear in addition to using the BLORP-fallback for
> depth.
> */
> if (clear_depth) {
> - if (!blorp_can_hiz_clear_depth(gen, iview->isl.format,
> + if (!blorp_can_hiz_clear_depth(gen,
> iview->planes[0].isl.format,
> iview->image->samples,
> render_area.offset.x,
> render_area.offset.y,
> @@ -1224,8 +1274,7 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer
> *cmd_buffer)
> clear_with_hiz = false;
> } else if (gen == 8 &&
> anv_can_sample_with_hiz(&cmd_buffer->device->info,
> - iview->aspect_mask,
> - iview->image->samples)) {
> + iview->image)) {
> /* Only gen9+ supports returning ANV_HZ_FC_VAL when
> sampling a
> * fast-cleared portion of a HiZ buffer. Testing has
> revealed
> * that Gen8 only supports returning 0.0f. Gens prior to
> gen8 do
> @@ -1276,13 +1325,30 @@ anv_cmd_buffer_clear_subpass(struct
> anv_cmd_buffer *cmd_buffer)
> blorp_batch_finish(&batch);
> }
>
> +static void
> +resolve_surface(struct blorp_batch *batch,
> + struct blorp_surf *src_surf,
> + uint32_t src_level, uint32_t src_layer,
> + struct blorp_surf *dst_surf,
> + uint32_t dst_level, uint32_t dst_layer,
> + uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t
> dst_y,
> + uint32_t width, uint32_t height)
> +{
> + blorp_blit(batch,
> + src_surf, src_level, src_layer,
> + ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> + dst_surf, dst_level, dst_layer,
> + ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> + src_x, src_y, src_x + width, src_y + height,
> + dst_x, dst_y, dst_x + width, dst_y + height,
> + 0x2600 /* GL_NEAREST */, false, false);
> +}
> +
> static void
> resolve_image(struct blorp_batch *batch,
> const struct anv_image *src_image,
> - enum isl_aux_usage src_aux_usage,
> uint32_t src_level, uint32_t src_layer,
> const struct anv_image *dst_image,
> - enum isl_aux_usage dst_aux_usage,
> uint32_t dst_level, uint32_t dst_layer,
> VkImageAspectFlags aspect_mask,
> uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t
> dst_y,
> @@ -1292,25 +1358,31 @@ resolve_image(struct blorp_batch *batch,
> assert(src_image->samples > 1);
> assert(dst_image->type == VK_IMAGE_TYPE_2D);
> assert(dst_image->samples == 1);
> + assert(src_image->n_planes == dst_image->n_planes);
>
> - uint32_t a;
> - for_each_bit(a, aspect_mask) {
> - VkImageAspectFlagBits aspect = 1 << a;
> -
> + uint32_t plane, aspect_bit;
> + anv_foreach_plane_aspect_bit(plane, aspect_bit, aspect_mask,
> + src_image->aspects) {
> struct blorp_surf src_surf, dst_surf;
> - get_blorp_surf_for_anv_image(src_image, aspect,
> - src_aux_usage, &src_surf);
> - get_blorp_surf_for_anv_image(dst_image, aspect,
> - dst_aux_usage, &dst_surf);
> -
> - blorp_blit(batch,
> - &src_surf, src_level, src_layer,
> - ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> - &dst_surf, dst_level, dst_layer,
> - ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
> - src_x, src_y, src_x + width, src_y + height,
> - dst_x, dst_y, dst_x + width, dst_y + height,
> - 0x2600 /* GL_NEAREST */, false, false);
> + get_blorp_surf_for_anv_image(src_image, plane, 1UL << aspect_bit,
> + src_image->planes[plane].aux_usage,
> + &src_surf);
> + get_blorp_surf_for_anv_image(dst_image, plane, 1UL << aspect_bit,
> + dst_image->planes[plane].aux_usage,
> + &dst_surf);
> +
> + uint32_t width_div = src_image->format->planes[
> plane].denominator_scales[0],
> + height_div = src_image->format->planes[
> plane].denominator_scales[1];
>
Multisample YUV isn't a thing. I don't think we need to do anything here
except assert that we're not YUV.
> +
> + resolve_surface(batch,
> + &src_surf, src_level, src_layer,
> + &dst_surf, dst_level, dst_layer,
> + src_x / width_div,
> + src_y / height_div,
> + dst_x / width_div,
> + dst_y / height_div,
> + width / width_div,
> + height / height_div);
> }
> }
>
> @@ -1339,12 +1411,17 @@ void anv_CmdResolveImage(
> const uint32_t layer_count =
> anv_get_layerCount(dst_image, &pRegions[r].dstSubresource);
>
> + VkImageAspectFlags src_mask = pRegions[r].srcSubresource.
> aspectMask,
> + dst_mask = pRegions[r].dstSubresource.aspectMask;
> +
> + assert(anv_image_aspects_compatible(src_mask, dst_mask));
> +
> for (uint32_t layer = 0; layer < layer_count; layer++) {
> resolve_image(&batch,
> - src_image, src_image->aux_usage,
> + src_image,
> pRegions[r].srcSubresource.mipLevel,
> pRegions[r].srcSubresource.baseArrayLayer + layer,
> - dst_image, dst_image->aux_usage,
> + dst_image,
> pRegions[r].dstSubresource.mipLevel,
> pRegions[r].dstSubresource.baseArrayLayer + layer,
> pRegions[r].dstSubresource.aspectMask,
> @@ -1360,6 +1437,7 @@ void anv_CmdResolveImage(
> void
> anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> + const uint32_t plane,
> const uint32_t base_level, const uint32_t
> level_count,
> const uint32_t base_layer, uint32_t layer_count)
> {
> @@ -1374,9 +1452,9 @@ anv_image_fast_clear(struct anv_cmd_buffer
> *cmd_buffer,
> blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
> struct blorp_surf surf;
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> - image->aux_usage == ISL_AUX_USAGE_NONE ?
> - ISL_AUX_USAGE_CCS_D : image->aux_usage,
> + get_blorp_surf_for_anv_image(image, plane, VK_IMAGE_ASPECT_COLOR_BIT,
> + image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_NONE ?
> + ISL_AUX_USAGE_CCS_D :
> image->planes[plane].aux_usage,
> &surf);
>
> /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
> @@ -1397,6 +1475,9 @@ anv_image_fast_clear(struct anv_cmd_buffer
> *cmd_buffer,
> cmd_buffer->state.pending_pipe_bits |=
> ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
>
> + uint32_t width_div = image->format->planes[plane].
> denominator_scales[0],
> + height_div = image->format->planes[plane].denominator_scales[1];
> +
> for (uint32_t l = 0; l < level_count; l++) {
> const uint32_t level = base_level + l;
>
> @@ -1409,11 +1490,13 @@ anv_image_fast_clear(struct anv_cmd_buffer
> *cmd_buffer,
> if (image->type == VK_IMAGE_TYPE_3D)
> layer_count = extent.depth;
>
> - assert(level < anv_image_aux_levels(image));
> - assert(base_layer + layer_count <= anv_image_aux_layers(image,
> level));
> + assert(level < anv_image_aux_levels(image, plane));
> + assert(base_layer + layer_count <= anv_image_aux_layers(image,
> plane, level));
> blorp_fast_clear(&batch, &surf, surf.surf->format,
> level, base_layer, layer_count,
> - 0, 0, extent.width, extent.height);
> + 0, 0,
> + extent.width / width_div,
> + extent.height / height_div);
> }
>
> cmd_buffer->state.pending_pipe_bits |=
> @@ -1470,17 +1553,34 @@ anv_cmd_buffer_resolve_subpass(struct
> anv_cmd_buffer *cmd_buffer)
> const VkRect2D render_area = cmd_buffer->state.render_area;
>
> assert(src_iview->aspect_mask == dst_iview->aspect_mask);
> + assert(src_iview->n_planes == 1);
> + assert(dst_iview->n_planes == 1);
>
> - resolve_image(&batch, src_iview->image, src_aux_usage,
> - src_iview->isl.base_level,
> - src_iview->isl.base_array_layer,
> - dst_iview->image, dst_aux_usage,
> - dst_iview->isl.base_level,
> - dst_iview->isl.base_array_layer,
> - src_iview->aspect_mask,
> - render_area.offset.x, render_area.offset.y,
> - render_area.offset.x, render_area.offset.y,
> - render_area.extent.width,
> render_area.extent.height);
> + const struct anv_format *format = src_iview->image->format;
> +
> + uint32_t width_div = format->planes[0].denominator_scales[0],
> + height_div = format->planes[0].denominator_scales[1];
>
YUV is not going to be used as an input/output attachment. We should just
assert here and not pretend to support it.
> +
> + struct blorp_surf src_surf, dst_surf;
> + get_blorp_surf_for_anv_image(src_iview->image, 0,
> + src_iview->aspect_mask,
> + src_aux_usage, &src_surf);
> + get_blorp_surf_for_anv_image(dst_iview->image, 0,
> + dst_iview->aspect_mask,
> + dst_aux_usage, &dst_surf);
> +
> + resolve_surface(&batch, &src_surf,
> + src_iview->planes[0].isl.base_level,
> + src_iview->planes[0].isl.base_array_layer,
> + &dst_surf,
> + dst_iview->planes[0].isl.base_level,
> + dst_iview->planes[0].isl.base_array_layer,
> + render_area.offset.x / width_div,
> + render_area.offset.y / height_div,
> + render_area.offset.x / width_div,
> + render_area.offset.y / height_div,
> + render_area.extent.width / width_div,
> + render_area.extent.height / height_div);
> }
>
> blorp_batch_finish(&batch);
> @@ -1490,7 +1590,7 @@ anv_cmd_buffer_resolve_subpass(struct
> anv_cmd_buffer *cmd_buffer)
> void
> anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> - VkImageAspectFlagBits aspect,
> + uint32_t plane,
> uint32_t base_level, uint32_t level_count,
> uint32_t base_layer, uint32_t layer_count)
> {
> @@ -1498,14 +1598,15 @@ anv_image_copy_to_shadow(struct anv_cmd_buffer
> *cmd_buffer,
> blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
> struct blorp_surf surf;
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> + get_blorp_surf_for_anv_image(image, plane, VK_IMAGE_ASPECT_COLOR_BIT,
> ISL_AUX_USAGE_NONE, &surf);
>
Ugh... This function takes an aspect and then entirely ignores it. :-( We
can just hard-code plane to 0 here because it's for compressed textures
which will never be YUV.
>
> struct blorp_surf shadow_surf = {
> - .surf = &image->shadow_surface.isl,
> + .surf = &image->planes[plane].shadow_surface.isl,
> .addr = {
> - .buffer = image->bo,
> - .offset = image->offset + image->shadow_surface.offset,
> + .buffer = image->planes[plane].bo,
> + .offset = image->planes[plane].bo_offset +
> + image->planes[plane].shadow_surface.offset,
> },
> };
>
> @@ -1544,7 +1645,7 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer
> *cmd_buffer,
> * don't perform such a resolve on gens that don't support it.
> */
> if (cmd_buffer->device->info.gen < 8 ||
> - image->aux_usage != ISL_AUX_USAGE_HIZ)
> + image->planes[0].aux_usage != ISL_AUX_USAGE_HIZ)
> return;
>
> assert(op == BLORP_HIZ_OP_HIZ_RESOLVE ||
> @@ -1554,14 +1655,15 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer
> *cmd_buffer,
> blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
>
> struct blorp_surf surf;
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_DEPTH_BIT,
> + get_blorp_surf_for_anv_image(image, 0, VK_IMAGE_ASPECT_DEPTH_BIT,
> ISL_AUX_USAGE_NONE, &surf);
>
> /* Manually add the aux HiZ surf */
> - surf.aux_surf = &image->aux_surface.isl,
> + surf.aux_surf = &image->planes[0].aux_surface.isl,
> surf.aux_addr = (struct blorp_address) {
> - .buffer = image->bo,
> - .offset = image->offset + image->aux_surface.offset,
> + .buffer = image->planes[0].bo,
> + .offset = image->planes[0].bo_offset +
> + image->planes[0].aux_surface.offset,
> };
> surf.aux_usage = ISL_AUX_USAGE_HIZ;
>
> @@ -1575,15 +1677,16 @@ void
> anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
> const struct anv_state surface_state,
> const struct anv_image * const image,
> + const uint32_t plane,
> const uint8_t level, const uint32_t layer_count,
> const enum blorp_fast_clear_op op)
> {
> assert(cmd_buffer && image);
>
> /* The resolved subresource range must have a CCS buffer. */
> - assert(level < anv_image_aux_levels(image));
> - assert(layer_count <= anv_image_aux_layers(image, level));
> - assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT && image->samples
> == 1);
> + assert(level < anv_image_aux_levels(image, plane));
> + assert(layer_count <= anv_image_aux_layers(image, plane, level));
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT &&
> image->samples == 1);
>
> /* Create a binding table for this surface state. */
> uint32_t binding_table;
> @@ -1598,13 +1701,14 @@ anv_ccs_resolve(struct anv_cmd_buffer * const
> cmd_buffer,
> BLORP_BATCH_PREDICATE_ENABLE);
>
> struct blorp_surf surf;
> - get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT,
> - image->aux_usage == ISL_AUX_USAGE_CCS_E ?
> + get_blorp_surf_for_anv_image(image, plane, VK_IMAGE_ASPECT_COLOR_BIT,
> + image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_CCS_E ?
> ISL_AUX_USAGE_CCS_E : ISL_AUX_USAGE_CCS_D,
> &surf);
>
> blorp_ccs_resolve_attachment(&batch, binding_table, &surf, level,
> - layer_count, image->color_surface.isl.
> format,
> + layer_count,
> + image->planes[plane].surface.isl.format,
> op);
>
> blorp_batch_finish(&batch);
> diff --git a/src/intel/vulkan/anv_dump.c b/src/intel/vulkan/anv_dump.c
> index 0608904219e..160c18c4f17 100644
> --- a/src/intel/vulkan/anv_dump.c
> +++ b/src/intel/vulkan/anv_dump.c
> @@ -424,20 +424,25 @@ anv_dump_add_framebuffer(struct anv_cmd_buffer
> *cmd_buffer,
> uint32_t b;
> for_each_bit(b, iview->image->aspects) {
> VkImageAspectFlagBits aspect = (1 << b);
> - char suffix;
> + const char *suffix;
> switch (aspect) {
> - case VK_IMAGE_ASPECT_COLOR_BIT: suffix = 'c'; break;
> - case VK_IMAGE_ASPECT_DEPTH_BIT: suffix = 'd'; break;
> - case VK_IMAGE_ASPECT_STENCIL_BIT: suffix = 's'; break;
> + case VK_IMAGE_ASPECT_COLOR_BIT: suffix = "c"; break;
> + case VK_IMAGE_ASPECT_DEPTH_BIT: suffix = "d"; break;
> + case VK_IMAGE_ASPECT_STENCIL_BIT: suffix = "s"; break;
> + case VK_IMAGE_ASPECT_PLANE_0_BIT_KHR: suffix = "c0"; break;
> + case VK_IMAGE_ASPECT_PLANE_1_BIT_KHR: suffix = "c1"; break;
> + case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR: suffix = "c2"; break;
> default:
> unreachable("Invalid aspect");
> }
>
> - char *filename = ralloc_asprintf(dump_ctx,
> "framebuffer%04d-%d%c.ppm",
> + char *filename = ralloc_asprintf(dump_ctx,
> "framebuffer%04d-%d%s.ppm",
> dump_idx, i, suffix);
>
> + unsigned plane = anv_image_aspect_to_plane(iview->image->aspects,
> aspect);
> dump_add_image(cmd_buffer, (struct anv_image *)iview->image,
> aspect,
> - iview->isl.base_level,
> iview->isl.base_array_layer,
> + iview->planes[plane].isl.base_level,
> + iview->planes[plane].isl.base_array_layer,
> filename);
> }
> }
> diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_
> formats.c
> index 303531a6ab9..3a941d4bd06 100644
> --- a/src/intel/vulkan/anv_formats.c
> +++ b/src/intel/vulkan/anv_formats.c
> @@ -423,8 +423,7 @@ anv_get_plane_format(const struct gen_device_info
> *devinfo, VkFormat vk_format,
> return plane_format;
> }
>
> - assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
> - assert(vk_format_aspects(vk_format) == VK_IMAGE_ASPECT_COLOR_BIT);
> + assert((aspect & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
>
> const struct isl_format_layout *isl_layout =
> isl_format_get_layout(plane_format.isl_format);
> diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
> index 262be68575a..6b3b70803d0 100644
> --- a/src/intel/vulkan/anv_image.c
> +++ b/src/intel/vulkan/anv_image.c
> @@ -68,6 +68,9 @@ choose_isl_surf_usage(VkImageCreateFlags
> vk_create_flags,
> isl_usage |= ISL_SURF_USAGE_STENCIL_BIT;
> break;
> case VK_IMAGE_ASPECT_COLOR_BIT:
> + case VK_IMAGE_ASPECT_PLANE_0_BIT_KHR:
> + case VK_IMAGE_ASPECT_PLANE_1_BIT_KHR:
> + case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR:
> break;
> default:
> unreachable("bad VkImageAspect");
> @@ -95,26 +98,31 @@ choose_isl_surf_usage(VkImageCreateFlags
> vk_create_flags,
> static struct anv_surface *
> get_surface(struct anv_image *image, VkImageAspectFlags aspect)
> {
> - switch (aspect) {
> - default:
> - unreachable("bad VkImageAspect");
> - case VK_IMAGE_ASPECT_COLOR_BIT:
> - return &image->color_surface;
> - case VK_IMAGE_ASPECT_DEPTH_BIT:
> - return &image->depth_surface;
> - case VK_IMAGE_ASPECT_STENCIL_BIT:
> - return &image->stencil_surface;
> - }
> + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
> + return &image->planes[plane].surface;
> }
>
> static void
> -add_surface(struct anv_image *image, struct anv_surface *surf)
> +add_surface(struct anv_image *image, struct anv_surface *surf, uint32_t
> plane)
> {
> assert(surf->isl.size > 0); /* isl surface must be initialized */
>
> - surf->offset = align_u32(image->size, surf->isl.alignment);
> + if (image->disjoint) {
> + surf->offset = align_u32(image->planes[plane].size,
> surf->isl.alignment);
> + /* Plane offset is always 0 when it's disjoint. */
> + } else {
> + surf->offset = align_u32(image->size, surf->isl.alignment);
> + /* Determine plane's offset only once when the first surface is
> added. */
> + if (image->planes[plane].size == 0)
> + image->planes[plane].offset = image->size;
>
This seems to be in conflict with code below (A)
> + }
> +
> image->size = surf->offset + surf->isl.size;
> + image->planes[plane].size = (surf->offset + surf->isl.size) -
> image->planes[plane].offset;
>
Is surf->offset relative to the image or the plane? I think, based on what
you have here, that it's relative to the image but it's confusing. :(
Also, what do we use the plane size for? Does it even make sense for
non-disjoint?
> +
> image->alignment = MAX2(image->alignment, surf->isl.alignment);
> + image->planes[plane].alignment = MAX2(image->planes[plane].alignment,
> + surf->isl.alignment);
> }
>
>
> @@ -194,11 +202,12 @@ all_formats_ccs_e_compatible(const struct
> gen_device_info *devinfo,
> */
> static void
> add_fast_clear_state_buffer(struct anv_image *image,
> + uint32_t plane,
> const struct anv_device *device)
> {
> assert(image && device);
> - assert(image->aux_surface.isl.size > 0 &&
> - image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> + assert(image->planes[plane].aux_surface.isl.size > 0 &&
> + image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
>
> /* The offset to the buffer of clear values must be dword-aligned for
> GPU
> * memcpy operations. It is located immediately after the auxiliary
> surface.
> @@ -212,18 +221,31 @@ add_fast_clear_state_buffer(struct anv_image *image,
> /* Auxiliary buffers should be a multiple of 4K, so the start of the
> clear
> * values buffer should already be dword-aligned.
> */
> - assert(image->aux_surface.isl.size % 4 == 0);
> + assert((image->planes[plane].offset + image->planes[plane].size) % 4
> == 0);
>
> - /* This buffer should be at the very end of the image. */
> - assert(image->size ==
> - image->aux_surface.offset + image->aux_surface.isl.size);
> + /* This buffer should be at the very end of the plane. */
> + if (image->disjoint) {
> + assert(image->planes[plane].size ==
> + (image->planes[plane].offset + image->planes[plane].size));
> + } else {
> + assert(image->size ==
> + (image->planes[plane].offset + image->planes[plane].size));
> + }
>
> const unsigned entry_size = anv_fast_clear_state_entry_size(device);
> /* There's no padding between entries, so ensure that they're always a
> * multiple of 32 bits in order to enable GPU memcpy operations.
> */
> assert(entry_size % 4 == 0);
> - image->size += entry_size * anv_image_aux_levels(image);
> +
> + const unsigned plane_state_size =
> + entry_size * anv_image_aux_levels(image, plane);
> +
> + image->planes[plane].fast_clear_state_offset =
> + image->planes[plane].offset + image->planes[plane].size;
> +
> + image->planes[plane].size += plane_state_size;
> + image->size += plane_state_size;
> }
>
> /**
> @@ -259,15 +281,13 @@ make_surface(const struct anv_device *dev,
>
> assert(tiling_flags);
>
> - struct anv_surface *anv_surf = get_surface(image, aspect);
> -
> image->extent = anv_sanitize_image_extent(vk_info->imageType,
> vk_info->extent);
>
> - enum isl_format format =
> - anv_get_isl_plane_format(&dev->info, vk_info->format,
> - aspect, vk_info->tiling);
> - assert(format != ISL_FORMAT_UNSUPPORTED);
> + const unsigned plane = anv_image_aspect_to_plane(image->aspects,
> aspect);
> + const struct anv_format_plane plane_format =
> + anv_get_plane_format(&dev->info, image->vk_format, aspect,
> image->tiling);
> + struct anv_surface *anv_surf = &image->planes[plane].surface;
>
> /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need
> to
> * fall back to linear on Broadwell and earlier because we aren't
> @@ -279,16 +299,16 @@ make_surface(const struct anv_device *dev,
> if (dev->info.gen <= 8 &&
> (vk_info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR)
> &&
> vk_info->tiling == VK_IMAGE_TILING_OPTIMAL) {
> - assert(isl_format_is_compressed(format));
> + assert(isl_format_is_compressed(plane_format.isl_format));
> tiling_flags = ISL_TILING_LINEAR_BIT;
> needs_shadow = true;
> }
>
> ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl,
> .dim = vk_to_isl_surf_dim[vk_info->imageType],
> - .format = format,
> - .width = image->extent.width,
> - .height = image->extent.height,
> + .format = plane_format.isl_format,
> + .width = image->extent.width / plane_format.denominator_scales[0],
> + .height = image->extent.height / plane_format.denominator_
> scales[1],
> .depth = image->extent.depth,
> .levels = vk_info->mipLevels,
> .array_len = vk_info->arrayLayers,
> @@ -303,7 +323,18 @@ make_surface(const struct anv_device *dev,
> */
> assert(ok);
>
> - add_surface(image, anv_surf);
> + image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
> +
> + if (!image->disjoint) {
> + /* With non disjoint planes, align the plane to its surface
> alignment.
> + */
> + uint32_t previous_plane_size = plane == 0 ? 0 :
> + (image->planes[plane - 1].offset + image->planes[plane -
> 1].size);
> + image->planes[plane].offset = align_u32(previous_plane_size,
> + anv_surf->isl.alignment);
> + }
>
(A) add_surface already does this for us as far as I can tell.
> +
> + add_surface(image, anv_surf, plane);
>
> /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need
> to
> * create an identical tiled shadow surface for use while texturing so
> we
> @@ -313,9 +344,9 @@ make_surface(const struct anv_device *dev,
> assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
> assert(tiling_flags == ISL_TILING_LINEAR_BIT);
>
> - ok = isl_surf_init(&dev->isl_dev, &image->shadow_surface.isl,
> + ok = isl_surf_init(&dev->isl_dev, &image->planes[plane].shadow_
> surface.isl,
> .dim = vk_to_isl_surf_dim[vk_info->imageType],
> - .format = format,
> + .format = plane_format.isl_format,
> .width = image->extent.width,
> .height = image->extent.height,
> .depth = image->extent.depth,
> @@ -332,7 +363,7 @@ make_surface(const struct anv_device *dev,
> */
> assert(ok);
>
> - add_surface(image, &image->shadow_surface);
> + add_surface(image, &image->planes[plane].shadow_surface, plane);
> }
>
> /* Add a HiZ surface to a depth buffer that will be used for rendering.
> @@ -358,24 +389,43 @@ make_surface(const struct anv_device *dev,
> } else if (dev->info.gen == 8 && vk_info->samples > 1) {
> anv_perf_warn(dev->instance, image, "Enable gen8 multisampled
> HiZ");
> } else if (!unlikely(INTEL_DEBUG & DEBUG_NO_HIZ)) {
> - assert(image->aux_surface.isl.size == 0);
> - ok = isl_surf_get_hiz_surf(&dev->isl_dev,
> &image->depth_surface.isl,
> - &image->aux_surface.isl);
> + assert(image->planes[plane].aux_surface.isl.size == 0);
> + ok = isl_surf_get_hiz_surf(&dev->isl_dev,
> + &image->planes[plane].surface.isl,
> + &image->planes[plane].aux_
> surface.isl);
> assert(ok);
> - add_surface(image, &image->aux_surface);
> - image->aux_usage = ISL_AUX_USAGE_HIZ;
> + add_surface(image, &image->planes[plane].aux_surface, plane);
> + image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ;
> }
> - } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT && vk_info->samples ==
> 1) {
> - if (!unlikely(INTEL_DEBUG & DEBUG_NO_RBC)) {
> - assert(image->aux_surface.isl.size == 0);
> - ok = isl_surf_get_ccs_surf(&dev->isl_dev, &anv_surf->isl,
> - &image->aux_surface.isl, 0);
> + } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT) &&
> vk_info->samples == 1) {
> + /* TODO: Allow compression on :
> + *
> + * 1) non multiplanar images (We appear to hit a sampler bug
> with CCS &
> + * R16G16 format. Putting the clear state a page (4096
> bytes)
> + * further fixes the issue.
>
Did we never get anywhere on this? I know we talked about it and I thought
we had it sorted but I don't remember.
> + *
> + * 2) alias images, because they might be aliases of images
> described
> + * in 1)
> + *
> + * 3) if compression is disabled by debug
> + */
> + const bool allow_compression =
> + image->n_planes == 1 &&
> + (vk_info->flags & VK_IMAGE_CREATE_ALIAS_BIT_KHR) == 0 &&
> + likely((INTEL_DEBUG & DEBUG_NO_RBC) == 0);
> +
> + if (allow_compression) {
> + assert(image->planes[plane].aux_surface.isl.size == 0);
> + ok = isl_surf_get_ccs_surf(&dev->isl_dev,
> + &image->planes[plane].surface.isl,
> + &image->planes[plane].aux_surface.isl,
> 0);
> if (ok) {
>
> /* Disable CCS when it is not useful (i.e., when you can't
> render
> * to the image with CCS enabled).
> */
> - if (!isl_format_supports_rendering(&dev->info, format)) {
> + if (!isl_format_supports_rendering(&dev->info,
> + plane_format.isl_format)) {
> /* While it may be technically possible to enable CCS for
> this
> * image, we currently don't have things hooked up to get
> it
> * working.
> @@ -383,12 +433,12 @@ make_surface(const struct anv_device *dev,
> anv_perf_warn(dev->instance, image,
> "This image format doesn't support
> rendering. "
> "Not allocating an CCS buffer.");
> - image->aux_surface.isl.size = 0;
> + image->planes[plane].aux_surface.isl.size = 0;
> return VK_SUCCESS;
> }
>
> - add_surface(image, &image->aux_surface);
> - add_fast_clear_state_buffer(image, dev);
> + add_surface(image, &image->planes[plane].aux_surface, plane);
> + add_fast_clear_state_buffer(image, plane, dev);
>
> /* For images created without MUTABLE_FORMAT_BIT set, we know
> that
> * they will always be used with the original format. In
> @@ -400,22 +450,42 @@ make_surface(const struct anv_device *dev,
> */
> if (!(vk_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
> all_formats_ccs_e_compatible(&dev->info, vk_info)) {
> - image->aux_usage = ISL_AUX_USAGE_CCS_E;
> + image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
> }
> }
> }
> - } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT && vk_info->samples >
> 1) {
> - assert(image->aux_surface.isl.size == 0);
> + } else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT) &&
> vk_info->samples > 1) {
> assert(!(vk_info->usage & VK_IMAGE_USAGE_STORAGE_BIT));
> - ok = isl_surf_get_mcs_surf(&dev->isl_dev, &anv_surf->isl,
> - &image->aux_surface.isl);
> + assert(image->planes[plane].aux_surface.isl.size == 0);
> + ok = isl_surf_get_mcs_surf(&dev->isl_dev,
> + &image->planes[plane].surface.isl,
> + &image->planes[plane].aux_surface.isl);
> if (ok) {
> - add_surface(image, &image->aux_surface);
> - add_fast_clear_state_buffer(image, dev);
> - image->aux_usage = ISL_AUX_USAGE_MCS;
> + add_surface(image, &image->planes[plane].aux_surface, plane);
> + add_fast_clear_state_buffer(image, plane, dev);
> + image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
> }
> }
>
> + assert((image->planes[plane].offset + image->planes[plane].size) ==
> image->size);
> +
> + /* Upper bound of the last surface should be smaller than the plane's
> + * size.
> + */
> + assert((MAX2(image->planes[plane].surface.offset,
> + image->planes[plane].aux_surface.offset) +
> + (image->planes[plane].aux_surface.isl.size > 0 ?
> + image->planes[plane].aux_surface.isl.size :
> + image->planes[plane].surface.isl.size)) <=
> + (image->planes[plane].offset + image->planes[plane].size));
> +
> + if (image->planes[plane].aux_surface.isl.size) {
> + /* assert(image->planes[plane].fast_clear_state_offset == */
> + /* (image->planes[plane].aux_surface.offset +
> image->planes[plane].aux_surface.isl.size)); */
> + assert(image->planes[plane].fast_clear_state_offset <
> + (image->planes[plane].offset + image->planes[plane].size));
> + }
> +
> return VK_SUCCESS;
> }
>
> @@ -447,13 +517,18 @@ anv_image_create(VkDevice _device,
> image->type = pCreateInfo->imageType;
> image->extent = pCreateInfo->extent;
> image->vk_format = pCreateInfo->format;
> + image->format = anv_get_format(pCreateInfo->format);
> image->aspects = vk_format_aspects(image->vk_format);
> image->levels = pCreateInfo->mipLevels;
> image->array_size = pCreateInfo->arrayLayers;
> image->samples = pCreateInfo->samples;
> image->usage = pCreateInfo->usage;
> image->tiling = pCreateInfo->tiling;
> - image->aux_usage = ISL_AUX_USAGE_NONE;
> +
> + const struct anv_format *format = anv_get_format(image->vk_format);
> + assert(format != NULL);
> +
> + image->n_planes = format->n_planes;
>
> uint32_t b;
> for_each_bit(b, image->aspects) {
> @@ -500,37 +575,41 @@ anv_DestroyImage(VkDevice _device, VkImage _image,
> vk_free2(&device->alloc, pAllocator, image);
> }
>
> -static void
> -anv_bind_image_memory(const VkBindImageMemoryInfoKHR *pBindInfo)
> +static VkResult anv_image_bind_memory_plane(struct anv_device *device,
> + struct anv_image *image,
> + uint32_t plane,
> + struct anv_device_memory
> *memory,
> + uint32_t memory_offset)
> {
> - ANV_FROM_HANDLE(anv_device_memory, mem, pBindInfo->memory);
> - ANV_FROM_HANDLE(anv_image, image, pBindInfo->image);
> -
> - assert(pBindInfo->sType == VK_STRUCTURE_TYPE_BIND_IMAGE_
> MEMORY_INFO_KHR);
> -
> - if (mem == NULL) {
> - image->bo = NULL;
> - image->offset = 0;
> - return;
> + if (memory) {
> + image->planes[plane].bo = memory->bo;
> + image->planes[plane].bo_offset = memory_offset;
> + } else {
> + image->planes[plane].bo = NULL;
> + image->planes[plane].bo_offset = 0;
> }
>
> - image->bo = mem->bo;
> - image->offset = pBindInfo->memoryOffset;
> + return VK_SUCCESS;
> }
>
> VkResult anv_BindImageMemory(
> - VkDevice device,
> - VkImage image,
> - VkDeviceMemory memory,
> + VkDevice _device,
> + VkImage _image,
> + VkDeviceMemory _memory,
> VkDeviceSize memoryOffset)
> {
> - anv_bind_image_memory(
> - &(VkBindImageMemoryInfoKHR) {
> - .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR,
> - .image = image,
> - .memory = memory,
> - .memoryOffset = memoryOffset,
> - });
> + ANV_FROM_HANDLE(anv_device, device, _device);
> + ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
> + ANV_FROM_HANDLE(anv_image, image, _image);
> +
> + uint32_t plane, aspect_bit;
> + anv_foreach_plane_aspect_bit(plane, aspect_bit,
> + image->aspects, image->aspects) {
> + VkResult result = anv_image_bind_memory_plane(device, image, plane,
> + mem, memoryOffset);
> + if (result != VK_SUCCESS)
> + return vk_error(result);
> + }
>
> return VK_SUCCESS;
> }
> @@ -540,10 +619,27 @@ VkResult anv_BindImageMemory2KHR(
> uint32_t bindInfoCount,
> const VkBindImageMemoryInfoKHR* pBindInfos)
> {
> - for (uint32_t i = 0; i < bindInfoCount; i++)
> - anv_bind_image_memory(&pBindInfos[i]);
> + VkResult result = VK_SUCCESS;
>
> - return VK_SUCCESS;
> + for (uint32_t i = 0; i < bindInfoCount; i++) {
> + const VkBindImageMemoryInfoKHR *bind_info = &pBindInfos[i];
> +
> + if (pBindInfos->pNext == NULL) {
> + result = anv_BindImageMemory(device, bind_info->image,
> + bind_info->memory,
> + bind_info->memoryOffset);
>
This isn't right. We're supposed to ignore extension structs we don't know
about. We can't just not bind the memory if pNext != NULL.
> + } else {
> + vk_foreach_struct_const(s, bind_info->pNext) {
> + switch (s->sType) {
> + default:
> + anv_debug_ignored_stype(s->sType);
> + break;
> + }
> + }
> + }
> + }
> +
> + return result;
> }
>
> static void
> @@ -575,22 +671,10 @@ void anv_GetImageSubresourceLayout(
>
> assert(__builtin_popcount(pSubresource->aspectMask) == 1);
>
> - switch (pSubresource->aspectMask) {
> - case VK_IMAGE_ASPECT_COLOR_BIT:
> - anv_surface_get_subresource_layout(image, &image->color_surface,
> - pSubresource, pLayout);
> - break;
> - case VK_IMAGE_ASPECT_DEPTH_BIT:
> - anv_surface_get_subresource_layout(image, &image->depth_surface,
> - pSubresource, pLayout);
> - break;
> - case VK_IMAGE_ASPECT_STENCIL_BIT:
> - anv_surface_get_subresource_layout(image, &image->stencil_surface,
> - pSubresource, pLayout);
> - break;
> - default:
> - assert(!"Invalid image aspect");
> - }
> + anv_surface_get_subresource_layout(image,
> + get_surface(image,
> +
> pSubresource->aspectMask),
> + pSubresource, pLayout);
> }
>
> /**
> @@ -601,7 +685,7 @@ void anv_GetImageSubresourceLayout(
> *
> * @param devinfo The device information of the Intel GPU.
> * @param image The image that may contain a collection of buffers.
> - * @param aspects The aspect(s) of the image to be accessed.
> + * @param plane The plane of the image to be accessed.
> * @param layout The current layout of the image aspect(s).
> *
> * @return The primary buffer that should be used for the given layout.
> @@ -609,7 +693,7 @@ void anv_GetImageSubresourceLayout(
> enum isl_aux_usage
> anv_layout_to_aux_usage(const struct gen_device_info * const devinfo,
> const struct anv_image * const image,
> - const VkImageAspectFlags aspects,
> + const uint32_t plane,
> const VkImageLayout layout)
> {
> /* Validate the inputs. */
> @@ -620,35 +704,41 @@ anv_layout_to_aux_usage(const struct gen_device_info
> * const devinfo,
> /* The layout of a NULL image is not properly defined. */
> assert(image != NULL);
>
> - /* The aspects must be a subset of the image aspects. */
> - assert(aspects & image->aspects && aspects <= image->aspects);
> -
> /* Determine the optimal buffer. */
>
> - /* If there is no auxiliary surface allocated, we must use the one and
> only
> - * main buffer.
> + /* Depth & stencil buffers share the same auxilliary buffer, we need to
> + * process them differently from color buffers.
> */
> - if (image->aux_surface.isl.size == 0)
> - return ISL_AUX_USAGE_NONE;
> + if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> + /* If there is no auxiliary surface allocated, we must use the one
> and
> + * only main buffer.
> + */
> + if (image->planes[plane].aux_surface.isl.size == 0)
> + return ISL_AUX_USAGE_NONE;
> + } else {
> + /* If there is no auxiliary surface allocated, we must use the one
> and
> + * only main buffer.
> + */
> + if (image->planes[plane].aux_surface.isl.size == 0)
> + return ISL_AUX_USAGE_NONE;
> +
> + /* On BDW+, when clearing the stencil aspect of a depth stencil
> image,
> + * the HiZ buffer allows us to record the clear with a relatively
> small
> + * number of packets. Prior to BDW, the HiZ buffer provides no known
> + * benefit to the stencil aspect.
> + */
> + if (devinfo->gen < 8 && plane != 0 /* aka stencil */)
> + return ISL_AUX_USAGE_NONE;
> + }
>
> /* All images that use an auxiliary surface are required to be tiled.
> */
> assert(image->tiling == VK_IMAGE_TILING_OPTIMAL);
>
> - /* On BDW+, when clearing the stencil aspect of a depth stencil image,
> - * the HiZ buffer allows us to record the clear with a relatively small
> - * number of packets. Prior to BDW, the HiZ buffer provides no known
> benefit
> - * to the stencil aspect.
> - */
> - if (devinfo->gen < 8 && aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
> - return ISL_AUX_USAGE_NONE;
> -
> - const bool color_aspect = aspects == VK_IMAGE_ASPECT_COLOR_BIT;
> -
> /* The following switch currently only handles depth stencil aspects.
> * TODO: Handle the color aspect.
> */
> - if (color_aspect)
> - return image->aux_usage;
> + if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT)
> + return image->planes[plane].aux_usage;
>
> switch (layout) {
>
> @@ -682,17 +772,17 @@ anv_layout_to_aux_usage(const struct gen_device_info
> * const devinfo,
>
> /* Sampling Layouts */
> case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
> - assert(!color_aspect);
> + assert((image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> /* Fall-through */
> case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
> case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR:
> - if (anv_can_sample_with_hiz(devinfo, aspects, image->samples))
> + if (anv_can_sample_with_hiz(devinfo, image))
> return ISL_AUX_USAGE_HIZ;
> else
> return ISL_AUX_USAGE_NONE;
>
> case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
> - assert(color_aspect);
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
>
> /* On SKL+, the render buffer can be decompressed by the
> presentation
> * engine. Support for this feature has not yet landed in the wider
> @@ -714,12 +804,12 @@ anv_layout_to_aux_usage(const struct gen_device_info
> * const devinfo,
>
> /* Rendering Layouts */
> case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
> - assert(color_aspect);
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> unreachable("Color images are not yet supported.");
>
> case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
> case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR:
> - assert(!color_aspect);
> + assert((image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> return ISL_AUX_USAGE_HIZ;
>
> case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
> @@ -761,7 +851,7 @@ remap_swizzle(VkComponentSwizzle swizzle,
> VkComponentSwizzle component,
> void
> anv_image_fill_surface_state(struct anv_device *device,
> const struct anv_image *image,
> - VkImageAspectFlagBits aspect,
> + uint32_t plane,
> const struct isl_view *view_in,
> isl_surf_usage_flags_t view_usage,
> enum isl_aux_usage aux_usage,
> @@ -770,8 +860,8 @@ anv_image_fill_surface_state(struct anv_device
> *device,
> struct anv_surface_state *state_inout,
> struct brw_image_param *image_param_out)
> {
> - const struct anv_surface *surface =
> - anv_image_get_surface_for_aspect_mask(image, aspect);
> + const struct anv_surface *surface = &image->planes[plane].surface,
> + *aux_surface = &image->planes[plane].aux_surface;
>
> struct isl_view view = *view_in;
> view.usage |= view_usage;
> @@ -781,13 +871,13 @@ anv_image_fill_surface_state(struct anv_device
> *device,
> * the primary surface. The shadow surface will be tiled, unlike the
> main
> * surface, so it should get significantly better performance.
> */
> - if (image->shadow_surface.isl.size > 0 &&
> + if (image->planes[plane].shadow_surface.isl.size > 0 &&
> isl_format_is_compressed(view.format) &&
> (flags & ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL)) {
> assert(isl_format_is_compressed(surface->isl.format));
> assert(surface->isl.tiling == ISL_TILING_LINEAR);
> - assert(image->shadow_surface.isl.tiling != ISL_TILING_LINEAR);
> - surface = &image->shadow_surface;
> + assert(image->planes[plane].shadow_surface.isl.tiling !=
> ISL_TILING_LINEAR);
> + surface = &image->planes[plane].shadow_surface;
> }
>
> if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
> @@ -802,9 +892,9 @@ anv_image_fill_surface_state(struct anv_device
> *device,
> if (!clear_color)
> clear_color = &default_clear_color;
>
> - const uint64_t address = image->offset + surface->offset;
> - const uint64_t aux_address = (aux_usage == ISL_AUX_USAGE_NONE) ? 0 :
> - image->offset + image->aux_surface.offset;
> + const uint64_t address = image->planes[plane].bo_offset +
> surface->offset;
> + const uint64_t aux_address = aux_usage == ISL_AUX_USAGE_NONE ?
> + 0 : (image->planes[plane].bo_offset + aux_surface->offset);
>
> if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
> !(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY) &&
> @@ -893,7 +983,7 @@ anv_image_fill_surface_state(struct anv_device
> *device,
> .view = &view,
> .address = address + offset_B,
> .clear_color = *clear_color,
> - .aux_surf = &image->aux_surface.isl,
> + .aux_surf = &aux_surface->isl,
> .aux_usage = aux_usage,
> .aux_address = aux_address,
> .mocs = device->default_mocs,
> @@ -924,6 +1014,22 @@ anv_image_fill_surface_state(struct anv_device
> *device,
> }
> }
>
> +static VkImageAspectFlags
> +remap_aspect_flags(VkImageAspectFlags view_aspects)
> +{
> + if (view_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> + if (_mesa_bitcount(view_aspects) == 1)
> + return VK_IMAGE_ASPECT_COLOR_BIT;
> +
> + VkImageAspectFlags color_aspects = 0;
> + for (uint32_t i = 0; i < _mesa_bitcount(view_aspects); i++)
> + color_aspects |= VK_IMAGE_ASPECT_PLANE_0_BIT_KHR << i;
> + return color_aspects;
> + }
> + /* No special remapping needed for depth & stencil aspects. */
> + return view_aspects;
> +}
> +
> VkResult
> anv_CreateImageView(VkDevice _device,
> const VkImageViewCreateInfo *pCreateInfo,
> @@ -968,106 +1074,125 @@ anv_CreateImageView(VkDevice _device,
> break;
> }
>
> + /* First expand aspects to the image's ones (for example
> + * VK_IMAGE_ASPECT_COLOR_BIT will be converted to
> + * VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | VK_IMAGE_ASPECT_PLANE_1_BIT_KHR |
> + * VK_IMAGE_ASPECT_PLANE_2_BIT_KHR for an image of format
> + * VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR.
> + */
> + VkImageAspectFlags expanded_aspects =
> + anv_image_color_aspects(image, range->aspectMask);
> +
> iview->image = image;
>
> - iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask;
> + /* Remap the expanded aspects for the image view. For example if only
> + * VK_IMAGE_ASPECT_PLANE_1_BIT_KHR was given in range->aspectMask, we
> will
> + * convert it to VK_IMAGE_ASPECT_COLOR_BIT since from the point of
> view of
> + * the image view, it only has a single plane.
> + */
> + iview->aspect_mask = remap_aspect_flags(expanded_aspects);
> + iview->n_planes = anv_image_aspect_get_planes(iview->aspect_mask);
> iview->vk_format = pCreateInfo->format;
>
> - struct anv_format_plane format =
> - anv_get_plane_format(&device->info, pCreateInfo->format,
> - range->aspectMask ==
> (VK_IMAGE_ASPECT_DEPTH_BIT |
> -
> VK_IMAGE_ASPECT_STENCIL_BIT) ?
> - VK_IMAGE_ASPECT_DEPTH_BIT : range->aspectMask,
> - image->tiling);
> -
> - iview->isl = (struct isl_view) {
> - .format = format.isl_format,
> - .base_level = range->baseMipLevel,
> - .levels = anv_get_levelCount(image, range),
> - .base_array_layer = range->baseArrayLayer,
> - .array_len = anv_get_layerCount(image, range),
> - .swizzle = {
> - .r = remap_swizzle(pCreateInfo->components.r,
> - VK_COMPONENT_SWIZZLE_R, format.swizzle),
> - .g = remap_swizzle(pCreateInfo->components.g,
> - VK_COMPONENT_SWIZZLE_G, format.swizzle),
> - .b = remap_swizzle(pCreateInfo->components.b,
> - VK_COMPONENT_SWIZZLE_B, format.swizzle),
> - .a = remap_swizzle(pCreateInfo->components.a,
> - VK_COMPONENT_SWIZZLE_A, format.swizzle),
> - },
> - };
> -
> iview->extent = (VkExtent3D) {
> .width = anv_minify(image->extent.width , range->baseMipLevel),
> .height = anv_minify(image->extent.height, range->baseMipLevel),
> .depth = anv_minify(image->extent.depth , range->baseMipLevel),
> };
>
> - if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
> - iview->isl.base_array_layer = 0;
> - iview->isl.array_len = iview->extent.depth;
> - }
> + /* Now go through the underlying image selected planes (computed in
> + * expanded_aspects) and map them to planes in the image view.
> + */
> + uint32_t iaspect_bit, vplane = 0, iplane;
> + anv_foreach_plane_aspect_bit(iplane, iaspect_bit,
> + expanded_aspects, image->aspects) {
> + VkImageAspectFlags vplane_aspect =
> + anv_plane_to_aspect(iview->aspect_mask, vplane);
> + struct anv_format_plane format =
> + anv_get_plane_format(&device->info, pCreateInfo->format,
> + vplane_aspect, image->tiling);
> +
> + iview->planes[vplane].image_plane = iplane;
> +
> + iview->planes[vplane].isl = (struct isl_view) {
> + .format = format.isl_format,
> + .base_level = range->baseMipLevel,
> + .levels = anv_get_levelCount(image, range),
> + .base_array_layer = range->baseArrayLayer,
> + .array_len = anv_get_layerCount(image, range),
> + .swizzle = {
> + .r = remap_swizzle(pCreateInfo->components.r,
> + VK_COMPONENT_SWIZZLE_R, format.swizzle),
> + .g = remap_swizzle(pCreateInfo->components.g,
> + VK_COMPONENT_SWIZZLE_G, format.swizzle),
> + .b = remap_swizzle(pCreateInfo->components.b,
> + VK_COMPONENT_SWIZZLE_B, format.swizzle),
> + .a = remap_swizzle(pCreateInfo->components.a,
> + VK_COMPONENT_SWIZZLE_A, format.swizzle),
> + },
> + };
> +
> + if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
> + iview->planes[vplane].isl.base_array_layer = 0;
> + iview->planes[vplane].isl.array_len = iview->extent.depth;
> + }
>
> - if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
> - pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
> - iview->isl.usage = ISL_SURF_USAGE_CUBE_BIT;
> - } else {
> - iview->isl.usage = 0;
> - }
> + if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
> + pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
> + iview->planes[vplane].isl.usage = ISL_SURF_USAGE_CUBE_BIT;
> + } else {
> + iview->planes[vplane].isl.usage = 0;
> + }
>
> - /* Input attachment surfaces for color are allocated and filled
> - * out at BeginRenderPass time because they need compression
> information.
> - * Compression is not yet enabled for depth textures and stencil
> doesn't
> - * allow compression so we can just use the texture surface state from
> the
> - * view.
> - */
> - if (view_usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
> - (view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
> - !(iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT))) {
> - iview->optimal_sampler_surface_state.state =
> alloc_surface_state(device);
> - iview->general_sampler_surface_state.state =
> alloc_surface_state(device);
> -
> - enum isl_aux_usage general_aux_usage =
> - anv_layout_to_aux_usage(&device->info, image,
> iview->aspect_mask,
> - VK_IMAGE_LAYOUT_GENERAL);
> - enum isl_aux_usage optimal_aux_usage =
> - anv_layout_to_aux_usage(&device->info, image,
> iview->aspect_mask,
> - VK_IMAGE_LAYOUT_SHADER_READ_
> ONLY_OPTIMAL);
> -
> - anv_image_fill_surface_state(device, image, iview->aspect_mask,
> - &iview->isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> - optimal_aux_usage, NULL,
> - ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
> - &iview->optimal_sampler_surface_state,
> - NULL);
> -
> - anv_image_fill_surface_state(device, image, iview->aspect_mask,
> - &iview->isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> - general_aux_usage, NULL,
> - 0,
> - &iview->general_sampler_surface_state,
> - NULL);
> - }
> + if (view_usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
> + (view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
> + !(iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT))) {
> + iview->planes[vplane].optimal_sampler_surface_state.state =
> alloc_surface_state(device);
> + iview->planes[vplane].general_sampler_surface_state.state =
> alloc_surface_state(device);
> +
> + enum isl_aux_usage general_aux_usage =
> + anv_layout_to_aux_usage(&device->info, image, iplane,
> + VK_IMAGE_LAYOUT_GENERAL);
> + enum isl_aux_usage optimal_aux_usage =
> + anv_layout_to_aux_usage(&device->info, image, iplane,
> + VK_IMAGE_LAYOUT_SHADER_READ_
> ONLY_OPTIMAL);
> +
> + anv_image_fill_surface_state(device, image, iplane,
> + &iview->planes[vplane].isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> + optimal_aux_usage, NULL,
> + ANV_IMAGE_VIEW_STATE_TEXTURE_
> OPTIMAL,
> + &iview->planes[vplane].
> optimal_sampler_surface_state,
> + NULL);
> +
> + anv_image_fill_surface_state(device, image, iplane,
> + &iview->planes[vplane].isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> + general_aux_usage, NULL,
> + 0,
> + &iview->planes[vplane].
> general_sampler_surface_state,
> + NULL);
> + }
> +
> + /* NOTE: This one needs to go last since it may stomp
> isl_view.format */
> + if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
> + iview->planes[vplane].storage_surface_state.state =
> alloc_surface_state(device);
> + iview->planes[vplane].writeonly_storage_surface_state.state =
> alloc_surface_state(device);
> +
> + anv_image_fill_surface_state(device, image, iplane,
> + &iview->planes[vplane].isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> + ISL_AUX_USAGE_NONE, NULL,
> + 0,
> + &iview->planes[vplane].
> storage_surface_state,
> + &iview->planes[vplane].
> storage_image_param);
> +
> + anv_image_fill_surface_state(device, image, iplane,
> + &iview->planes[vplane].isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> + ISL_AUX_USAGE_NONE, NULL,
> + ANV_IMAGE_VIEW_STATE_STORAGE_
> WRITE_ONLY,
> + &iview->planes[vplane].
> writeonly_storage_surface_state,
> + NULL);
> + }
>
> - /* NOTE: This one needs to go last since it may stomp isl_view.format
> */
> - if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
> - iview->storage_surface_state.state = alloc_surface_state(device);
> - iview->writeonly_storage_surface_state.state =
> alloc_surface_state(device);
> -
> - anv_image_fill_surface_state(device, image, iview->aspect_mask,
> - &iview->isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> - ISL_AUX_USAGE_NONE, NULL,
> - 0,
> - &iview->storage_surface_state,
> - &iview->storage_image_param);
> -
> - anv_image_fill_surface_state(device, image, iview->aspect_mask,
> - &iview->isl,
> ISL_SURF_USAGE_STORAGE_BIT,
> - ISL_AUX_USAGE_NONE, NULL,
> - ANV_IMAGE_VIEW_STATE_STORAGE_
> WRITE_ONLY,
> - &iview->writeonly_storage_
> surface_state,
> - NULL);
> + vplane++;
> }
>
> *pView = anv_image_view_to_handle(iview);
> @@ -1085,24 +1210,26 @@ anv_DestroyImageView(VkDevice _device, VkImageView
> _iview,
> if (!iview)
> return;
>
> - if (iview->optimal_sampler_surface_state.state.alloc_size > 0) {
> - anv_state_pool_free(&device->surface_state_pool,
> - iview->optimal_sampler_surface_state.state);
> - }
> + for (uint32_t plane = 0; plane < iview->n_planes; plane++) {
> + if (iview->planes[plane].optimal_sampler_surface_state.state.alloc_size
> > 0) {
> + anv_state_pool_free(&device->surface_state_pool,
> + iview->planes[plane].optimal_
> sampler_surface_state.state);
> + }
>
> - if (iview->general_sampler_surface_state.state.alloc_size > 0) {
> - anv_state_pool_free(&device->surface_state_pool,
> - iview->general_sampler_surface_state.state);
> - }
> + if (iview->planes[plane].general_sampler_surface_state.state.alloc_size
> > 0) {
> + anv_state_pool_free(&device->surface_state_pool,
> + iview->planes[plane].general_
> sampler_surface_state.state);
> + }
>
> - if (iview->storage_surface_state.state.alloc_size > 0) {
> - anv_state_pool_free(&device->surface_state_pool,
> - iview->storage_surface_state.state);
> - }
> + if (iview->planes[plane].storage_surface_state.state.alloc_size >
> 0) {
> + anv_state_pool_free(&device->surface_state_pool,
> + iview->planes[plane].storage_
> surface_state.state);
> + }
>
> - if (iview->writeonly_storage_surface_state.state.alloc_size > 0) {
> - anv_state_pool_free(&device->surface_state_pool,
> - iview->writeonly_storage_surface_state.state);
> + if (iview->planes[plane].writeonly_storage_surface_state.state.alloc_size
> > 0) {
> + anv_state_pool_free(&device->surface_state_pool,
> + iview->planes[plane].
> writeonly_storage_surface_state.state);
> + }
> }
>
> vk_free2(&device->alloc, pAllocator, iview);
> @@ -1210,16 +1337,21 @@ const struct anv_surface *
> anv_image_get_surface_for_aspect_mask(const struct anv_image *image,
> VkImageAspectFlags aspect_mask)
> {
> + VkImageAspectFlags sanitized_mask;
> +
> switch (aspect_mask) {
> case VK_IMAGE_ASPECT_COLOR_BIT:
> assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> - return &image->color_surface;
> + sanitized_mask = VK_IMAGE_ASPECT_COLOR_BIT;
> + break;
> case VK_IMAGE_ASPECT_DEPTH_BIT:
> assert(image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT);
> - return &image->depth_surface;
> + sanitized_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
> + break;
> case VK_IMAGE_ASPECT_STENCIL_BIT:
> assert(image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT);
> - return &image->stencil_surface;
> + sanitized_mask = VK_IMAGE_ASPECT_STENCIL_BIT;
> + break;
> case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
> /* FINISHME: The Vulkan spec (git a511ba2) requires support for
> * combined depth stencil formats. Specifically, it states:
> @@ -1233,13 +1365,29 @@ anv_image_get_surface_for_aspect_mask(const
> struct anv_image *image,
> * stencil surfaces from the underlying surface.
> */
> if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
> - return &image->depth_surface;
> + sanitized_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
> } else {
> assert(image->aspects == VK_IMAGE_ASPECT_STENCIL_BIT);
> - return &image->stencil_surface;
> + sanitized_mask = VK_IMAGE_ASPECT_STENCIL_BIT;
> }
>
Does this case actually happen? I know it's in there for some reason but I
have a feeling that reason is now bogus. If so, then we can get rid of
this whole switch mess and replace it all with the two lines you added
below.
> - default:
> + break;
> + case VK_IMAGE_ASPECT_PLANE_0_BIT_KHR:
> + assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> + sanitized_mask = VK_IMAGE_ASPECT_PLANE_0_BIT_KHR;
> + break;
> + case VK_IMAGE_ASPECT_PLANE_1_BIT_KHR:
> + assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> + sanitized_mask = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR;
> + break;
> + case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR:
> + assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0);
> + sanitized_mask = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR;
> + break;
> + default:
> unreachable("image does not have aspect");
> return NULL;
> }
> +
> + uint32_t plane = anv_image_aspect_to_plane(image->aspects,
> sanitized_mask);
> + return &image->planes[plane].surface;
> }
> diff --git a/src/intel/vulkan/anv_intel.c b/src/intel/vulkan/anv_intel.c
> index 991a93542d2..d4ef3beb743 100644
> --- a/src/intel/vulkan/anv_intel.c
> +++ b/src/intel/vulkan/anv_intel.c
> @@ -80,8 +80,8 @@ VkResult anv_CreateDmaBufImageINTEL(
> pAllocator, &image_h);
>
> image = anv_image_from_handle(image_h);
> - image->bo = mem->bo;
> - image->offset = 0;
> + image->planes[0].bo = mem->bo;
> + image->planes[0].bo_offset = 0;
>
> assert(image->extent.width > 0);
> assert(image->extent.height > 0);
> diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_
> private.h
> index 5e14f49b196..cb324a3995e 100644
> --- a/src/intel/vulkan/anv_private.h
> +++ b/src/intel/vulkan/anv_private.h
> @@ -1566,6 +1566,16 @@ anv_pipe_invalidate_bits_for_access_flags(VkAccessFlags
> flags)
> return pipe_bits;
> }
>
> +#define VK_IMAGE_ASPECT_ANY_COLOR_BIT ( \
> + VK_IMAGE_ASPECT_COLOR_BIT | \
> + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | \
> + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | \
> + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR)
> +#define VK_IMAGE_ASPECT_PLANES_BITS ( \
> + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR | \
> + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR | \
> + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR)
> +
> struct anv_vertex_binding {
> struct anv_buffer * buffer;
> VkDeviceSize offset;
> @@ -2236,10 +2246,48 @@ anv_image_aspect_to_plane(VkImageAspectFlags
> image_aspects,
> case VK_IMAGE_ASPECT_PLANE_2_BIT_KHR:
> return 2;
> default:
> + /* Purposefully assert with depth/stencil aspects. */
> unreachable("invalid image aspect");
> }
> }
>
> +static inline uint32_t
> +anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)
> +{
> + uint32_t planes = 0;
> +
> + if (aspect_mask & (VK_IMAGE_ASPECT_COLOR_BIT |
> + VK_IMAGE_ASPECT_DEPTH_BIT |
> + VK_IMAGE_ASPECT_STENCIL_BIT |
> + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR))
> + planes++;
> + if (aspect_mask & VK_IMAGE_ASPECT_PLANE_1_BIT_KHR)
> + planes++;
> + if (aspect_mask & VK_IMAGE_ASPECT_PLANE_2_BIT_KHR)
> + planes++;
> +
> + return planes;
> +}
> +
> +static inline VkImageAspectFlags
> +anv_plane_to_aspect(VkImageAspectFlags image_aspects,
> + uint32_t plane)
> +{
> + if (image_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> + if (_mesa_bitcount(image_aspects) > 1)
> + return VK_IMAGE_ASPECT_PLANE_0_BIT_KHR << plane;
> + return VK_IMAGE_ASPECT_COLOR_BIT;
> + }
> + if (image_aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
> + return VK_IMAGE_ASPECT_DEPTH_BIT << plane;
> + assert(image_aspects == VK_IMAGE_ASPECT_STENCIL_BIT);
> + return VK_IMAGE_ASPECT_STENCIL_BIT;
> +}
> +
> +#define anv_foreach_plane_aspect_bit(p, b, aspects, image_aspects) \
> + for_each_bit(b, aspects) \
> + for (p = anv_image_aspect_to_plane(image_aspects, 1 << b); p !=
> ~0; p = ~0)
>
Why not something like this:
VkImageAspectFlags
anv_image_expand_aspects(struct anv_image *image, VkImageAspectFlags
aspects)
{
if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
assert(aspects == VK_IMAGE_ASPECT_COLOR_BIT);
if (!(image->aspects & VK_IMAGE_ASPECT_COLOR_BIT) &&
(image->aspects & VK_IMAGE_ASPECT_PLANE0_BIT)) {
aspects &= VK_IMAGE_ASPECT_COLOR_BIT;
aspects |= image->aspects & VK_IMAGE_ASPECT_PLANES_BITS;
}
}
assert((aspects & image->aspects) == aspects);
return aspects;
}
#define anv_image_foreach_aspect(a, image, aspects) \
for (VkImageAspectFlags _bits = anv_image_expand_aspects(image,
aspects), \
a = (1 << (ffs(_bits) - 1)); \
a; \
_bits &= ~a, a = (1 << (ffs(_bits) - 1)))
I think I got that more-or-less right; I did type it blind. :) Anyway, I
think something like that would be much nicer to use. Also, it's not a
double loop so break works the way you would expect.
+
> const struct anv_format *
> anv_get_format(VkFormat format);
>
> @@ -2300,72 +2348,115 @@ struct anv_image {
> * of the actual surface formats.
> */
> VkFormat vk_format;
> + const struct anv_format *format;
> +
> VkImageAspectFlags aspects;
> VkExtent3D extent;
> uint32_t levels;
> uint32_t array_size;
> uint32_t samples; /**< VkImageCreateInfo::samples */
> + uint32_t n_planes;
> VkImageUsageFlags usage; /**< Superset of VkImageCreateInfo::usage. */
> VkImageTiling tiling; /** VkImageCreateInfo::tiling */
>
> VkDeviceSize size;
> uint32_t alignment;
>
> - /* Set when bound */
> - struct anv_bo *bo;
> - VkDeviceSize offset;
> + bool disjoint;
>
> /**
> * Image subsurfaces
> *
> - * For each foo, anv_image::foo_surface is valid if and only if
> - * anv_image::aspects has a foo aspect.
> + * For each foo, anv_image::planes[x].surface is valid if and only if
> + * anv_image::aspects has a x aspect. Refer to
> anv_image_aspect_to_plane()
> + * to figure the number associated with a given aspect.
> *
> * The hardware requires that the depth buffer and stencil buffer be
> * separate surfaces. From Vulkan's perspective, though, depth and
> stencil
> * reside in the same VkImage. To satisfy both the hardware and
> Vulkan, we
> * allocate the depth and stencil buffers as separate surfaces in the
> same
> * bo.
> + *
> + * Memory layout :
> + *
> + * -----------------------
> + * | surface0 | /|\
> + * ----------------------- |
> + * | shadow surface0 | |
> + * ----------------------- | Plane 0
> + * | aux surface0 | |
> + * ----------------------- |
> + * | fast clear colors0 | \|/
> + * -----------------------
> + * | surface1 | /|\
> + * ----------------------- |
> + * | shadow surface1 | |
> + * ----------------------- | Plane 1
> + * | aux surface1 | |
> + * ----------------------- |
> + * | fast clear colors1 | \|/
> + * -----------------------
> + * | ... |
> + * | |
> + * -----------------------
> */
> - union {
> - struct anv_surface color_surface;
> + struct {
> + /**
> + * Offset of the entire plane (whenever the image is disjoint this
> is
> + * set to 0).
> + */
> + uint32_t offset;
>
> - struct {
> - struct anv_surface depth_surface;
> - struct anv_surface stencil_surface;
> - };
> - };
> + VkDeviceSize size;
> + uint32_t alignment;
>
> - /**
> - * A surface which shadows the main surface and may have different
> tiling.
> - * This is used for sampling using a tiling that isn't supported for
> other
> - * operations.
> - */
> - struct anv_surface shadow_surface;
> + struct anv_surface surface;
>
> - /**
> - * For color images, this is the aux usage for this image when not
> used as a
> - * color attachment.
> - *
> - * For depth/stencil images, this is set to ISL_AUX_USAGE_HIZ if the
> image
> - * has a HiZ buffer.
> - */
> - enum isl_aux_usage aux_usage;
> + /**
> + * A surface which shadows the main surface and may have different
> + * tiling. This is used for sampling using a tiling that isn't
> supported
> + * for other operations.
> + */
> + struct anv_surface shadow_surface;
> +
> + /**
> + * For color images, this is the aux usage for this image when not
> used
> + * as a color attachment.
> + *
> + * For depth/stencil images, this is set to ISL_AUX_USAGE_HIZ if the
> + * image has a HiZ buffer.
> + */
> + enum isl_aux_usage aux_usage;
>
> - struct anv_surface aux_surface;
> + struct anv_surface aux_surface;
> +
> + /**
> + * Offset of the fast clear state (used to compute the
> + * fast_clear_state_offset of the following planes).
> + */
> + uint32_t fast_clear_state_offset;
> +
> + /**
> + * BO associated with this plane, set when bound.
> + */
> + struct anv_bo *bo;
> + VkDeviceSize bo_offset;
> + } planes[3];
> };
>
> /* Returns the number of auxiliary buffer levels attached to an image. */
> static inline uint8_t
> -anv_image_aux_levels(const struct anv_image * const image)
> +anv_image_aux_levels(const struct anv_image * const image, uint8_t plane)
> {
> assert(image);
> - return image->aux_surface.isl.size > 0 ? image->aux_surface.isl.levels
> : 0;
> + return image->planes[plane].aux_surface.isl.size > 0 ?
> + image->planes[plane].aux_surface.isl.levels : 0;
> }
>
> /* Returns the number of auxiliary buffer layers attached to an image. */
> static inline uint32_t
> anv_image_aux_layers(const struct anv_image * const image,
> + const uint32_t plane,
> const uint8_t miplevel)
> {
> assert(image);
> @@ -2373,14 +2464,14 @@ anv_image_aux_layers(const struct anv_image *
> const image,
> /* The miplevel must exist in the main buffer. */
> assert(miplevel < image->levels);
>
> - if (miplevel >= anv_image_aux_levels(image)) {
> + if (miplevel >= anv_image_aux_levels(image, plane)) {
> /* There are no layers with auxiliary data because the miplevel has
> no
> * auxiliary data.
> */
> return 0;
> } else {
> - return MAX2(image->aux_surface.isl.logical_level0_px.array_len,
> - image->aux_surface.isl.logical_level0_px.depth >>
> miplevel);
> + return MAX2(image->planes[plane].aux_surface.isl.logical_level0_px.
> array_len,
> + image->planes[plane].aux_surface.isl.logical_level0_px.depth
> >> miplevel);
> }
> }
>
> @@ -2404,13 +2495,12 @@ anv_fast_clear_state_entry_size(const struct
> anv_device *device)
> /* Returns true if a HiZ-enabled depth buffer can be sampled from. */
> static inline bool
> anv_can_sample_with_hiz(const struct gen_device_info * const devinfo,
> - const VkImageAspectFlags aspect_mask,
> - const uint32_t samples)
> + const struct anv_image *image)
> {
> /* Validate the inputs. */
> - assert(devinfo && aspect_mask && samples);
> - return devinfo->gen >= 8 && (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
> &&
> - samples == 1;
> + assert(devinfo && image && image->samples);
> + return devinfo->gen >= 8 && (image->aspects &
> VK_IMAGE_ASPECT_DEPTH_BIT) &&
> + image->samples == 1;
> }
>
> void
> @@ -2421,19 +2511,21 @@ void
> anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
> const struct anv_state surface_state,
> const struct anv_image * const image,
> + const uint32_t plane,
> const uint8_t level, const uint32_t layer_count,
> const enum blorp_fast_clear_op op);
>
> void
> anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> + const uint32_t plane,
> const uint32_t base_level, const uint32_t
> level_count,
> const uint32_t base_layer, uint32_t layer_count);
>
> void
> anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> - VkImageAspectFlagBits aspect,
> + uint32_t plane,
>
Why do we need both the plane and the aspect on all these? Just the aspect
should be sufficient. This same question applies to a lot of functions in
this patch.
> uint32_t base_level, uint32_t level_count,
> uint32_t base_layer, uint32_t layer_count);
>
> @@ -2458,37 +2550,71 @@ anv_get_levelCount(const struct anv_image *image,
> image->levels - range->baseMipLevel : range->levelCount;
> }
>
> +static inline VkImageAspectFlags
> +anv_image_color_aspects(struct anv_image *image, VkImageAspectFlags
> aspects)
> +{
> + /* If the underlying image has color plane aspects and
> + * VK_IMAGE_ASPECT_COLOR_BIT has been requested, then return the
> aspects of
> + * the underlying image. */
> + if ((image->aspects & VK_IMAGE_ASPECT_PLANES_BITS) != 0 &&
> + aspects == VK_IMAGE_ASPECT_COLOR_BIT)
> + return image->aspects;
> +
> + return aspects;
> +}
>
I guess this is basically the expand_aspects function I wrote above.
> +
> +static inline bool
> +anv_image_aspects_compatible(VkImageAspectFlags aspects1,
> + VkImageAspectFlags aspects2)
> +{
> + if (aspects1 == aspects2)
> + return true;
> +
> + /* Only 1 color aspects are compatibles. */
> + if ((aspects1 & VK_IMAGE_ASPECT_ANY_COLOR_BIT) != 0 &&
> + (aspects2 & VK_IMAGE_ASPECT_ANY_COLOR_BIT) != 0 &&
> + _mesa_bitcount(aspects1) == _mesa_bitcount(aspects2))
> + return true;
> +
> + return false;
> +}
>
> struct anv_image_view {
> const struct anv_image *image; /**< VkImageViewCreateInfo::image */
>
> - struct isl_view isl;
> -
> VkImageAspectFlags aspect_mask;
> VkFormat vk_format;
> VkExtent3D extent; /**< Extent of VkImageViewCreateInfo::baseMipLevel.
> */
>
> - /**
> - * RENDER_SURFACE_STATE when using image as a sampler surface with an
> image
> - * layout of SHADER_READ_ONLY_OPTIMAL or DEPTH_STENCIL_READ_ONLY_
> OPTIMAL.
> - */
> - struct anv_surface_state optimal_sampler_surface_state;
> + unsigned n_planes;
> + struct {
> + uint32_t image_plane;
>
> - /**
> - * RENDER_SURFACE_STATE when using image as a sampler surface with an
> image
> - * layout of GENERAL.
> - */
> - struct anv_surface_state general_sampler_surface_state;
> + struct isl_view isl;
>
> - /**
> - * RENDER_SURFACE_STATE when using image as a storage image. Separate
> states
> - * for write-only and readable, using the real format for write-only
> and the
> - * lowered format for readable.
> - */
> - struct anv_surface_state storage_surface_state;
> - struct anv_surface_state writeonly_storage_surface_state;
> + /**
> + * RENDER_SURFACE_STATE when using image as a sampler surface with
> an
> + * image layout of SHADER_READ_ONLY_OPTIMAL or
> + * DEPTH_STENCIL_READ_ONLY_OPTIMAL.
> + */
> + struct anv_surface_state optimal_sampler_surface_state;
>
> - struct brw_image_param storage_image_param;
> + /**
> + * RENDER_SURFACE_STATE when using image as a sampler surface with
> an
> + * image layout of GENERAL.
> + */
> + struct anv_surface_state general_sampler_surface_state;
> +
> + /**
> + * RENDER_SURFACE_STATE when using image as a storage image.
> Separate
> + * states for write-only and readable, using the real format for
> + * write-only and the lowered format for readable.
> + */
> + struct anv_surface_state storage_surface_state;
> + struct anv_surface_state writeonly_storage_surface_state;
> +
> + struct brw_image_param storage_image_param;
> + } planes[3];
> };
>
> enum anv_image_view_state_flags {
> @@ -2498,7 +2624,7 @@ enum anv_image_view_state_flags {
>
> void anv_image_fill_surface_state(struct anv_device *device,
> const struct anv_image *image,
> - VkImageAspectFlagBits aspect,
> + uint32_t plane,
> const struct isl_view *view,
> isl_surf_usage_flags_t view_usage,
> enum isl_aux_usage aux_usage,
> diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
> index c3e5dc1870b..3fca076894c 100644
> --- a/src/intel/vulkan/anv_wsi.c
> +++ b/src/intel/vulkan/anv_wsi.c
> @@ -221,7 +221,7 @@ anv_wsi_image_create(VkDevice device_h,
> result = anv_AllocateMemory(anv_device_to_handle(device),
> &(VkMemoryAllocateInfo) {
> .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
> - .allocationSize = image->size,
> + .allocationSize = image->planes[0].surface.isl.size,
> .memoryTypeIndex = 0,
> },
> NULL /* XXX: pAllocator */,
> @@ -240,7 +240,7 @@ anv_wsi_image_create(VkDevice device_h,
>
> anv_BindImageMemory(device_h, image_h, memory_h, 0);
>
> - struct anv_surface *surface = &image->color_surface;
> + struct anv_surface *surface = &image->planes[0].surface;
> assert(surface->isl.tiling == ISL_TILING_X);
>
> *row_pitch = surface->isl.row_pitch;
> @@ -266,8 +266,8 @@ anv_wsi_image_create(VkDevice device_h,
> *image_p = image_h;
> *memory_p = memory_h;
> *fd_p = fd;
> - *size = image->size;
> - *offset = image->offset;
> + *size = image->planes[0].surface.isl.size;
> + *offset = image->planes[0].surface.offset;
> return VK_SUCCESS;
> fail_alloc_memory:
> anv_FreeMemory(device_h, memory_h, pAllocator);
> diff --git a/src/intel/vulkan/gen8_cmd_buffer.c
> b/src/intel/vulkan/gen8_cmd_buffer.c
> index 7bea231ea76..f19867ca320 100644
> --- a/src/intel/vulkan/gen8_cmd_buffer.c
> +++ b/src/intel/vulkan/gen8_cmd_buffer.c
> @@ -323,7 +323,7 @@ want_stencil_pma_fix(struct anv_cmd_buffer *cmd_buffer)
> /* HiZ is enabled so we had better have a depth buffer with HiZ */
> const struct anv_image_view *ds_iview =
> anv_cmd_buffer_get_depth_stencil_view(cmd_buffer);
> - assert(ds_iview && ds_iview->image->aux_usage == ISL_AUX_USAGE_HIZ);
> + assert(ds_iview && ds_iview->image->planes[0].aux_usage ==
> ISL_AUX_USAGE_HIZ);
>
> /* 3DSTATE_PS_EXTRA::PixelShaderValid */
> struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
> diff --git a/src/intel/vulkan/genX_cmd_buffer.c
> b/src/intel/vulkan/genX_cmd_buffer.c
> index dc5cf687dc6..71e46acfe4d 100644
> --- a/src/intel/vulkan/genX_cmd_buffer.c
> +++ b/src/intel/vulkan/genX_cmd_buffer.c
> @@ -181,18 +181,45 @@ add_surface_state_reloc(struct anv_cmd_buffer
> *cmd_buffer,
> static void
> add_image_relocs(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> + const uint32_t plane,
> struct anv_surface_state state)
> {
> const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;
>
> - add_surface_state_reloc(cmd_buffer, state.state, image->bo,
> state.address);
> + add_surface_state_reloc(cmd_buffer, state.state,
> + image->planes[plane].bo, state.address);
>
> if (state.aux_address) {
> VkResult result =
> anv_reloc_list_add(&cmd_buffer->surface_relocs,
> &cmd_buffer->pool->alloc,
> state.state.offset +
> isl_dev->ss.aux_addr_offset,
> - image->bo, state.aux_address);
> + image->planes[plane].bo,
> + state.aux_address);
> + if (result != VK_SUCCESS)
> + anv_batch_set_error(&cmd_buffer->batch, result);
> + }
> +}
> +
> +static void
> +add_image_view_relocs(struct anv_cmd_buffer *cmd_buffer,
> + const struct anv_image_view *image_view,
> + const uint32_t plane,
> + struct anv_surface_state state)
> +{
> + const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;
> + const struct anv_image *image = image_view->image;
> + uint32_t image_plane = image_view->planes[plane].image_plane;
> +
> + add_surface_state_reloc(cmd_buffer, state.state,
> + image->planes[image_plane].bo, state.address);
> +
> + if (state.aux_address) {
> + VkResult result =
> + anv_reloc_list_add(&cmd_buffer->surface_relocs,
> + &cmd_buffer->pool->alloc,
> + state.state.offset +
> isl_dev->ss.aux_addr_offset,
> + image->planes[image_plane].bo,
> state.aux_address);
> if (result != VK_SUCCESS)
> anv_batch_set_error(&cmd_buffer->batch, result);
> }
> @@ -225,8 +252,11 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
> struct anv_attachment_state *att_state = &cmd_state->attachments[att];
> struct anv_image_view *iview = cmd_state->framebuffer->
> attachments[att];
>
> - if (iview->isl.base_array_layer >=
> - anv_image_aux_layers(iview->image, iview->isl.base_level)) {
> + assert(iview->n_planes == 1);
> +
> + if (iview->planes[0].isl.base_array_layer >=
> + anv_image_aux_layers(iview->image, 0,
> + iview->planes[0].isl.base_level)) {
> /* There is no aux buffer which corresponds to the level and
> layer(s)
> * being accessed.
> */
> @@ -234,12 +264,12 @@ color_attachment_compute_aux_usage(struct
> anv_device * device,
> att_state->input_aux_usage = ISL_AUX_USAGE_NONE;
> att_state->fast_clear = false;
> return;
> - } else if (iview->image->aux_usage == ISL_AUX_USAGE_MCS) {
> + } else if (iview->image->planes[0].aux_usage == ISL_AUX_USAGE_MCS) {
> att_state->aux_usage = ISL_AUX_USAGE_MCS;
> att_state->input_aux_usage = ISL_AUX_USAGE_MCS;
> att_state->fast_clear = false;
> return;
> - } else if (iview->image->aux_usage == ISL_AUX_USAGE_CCS_E) {
> + } else if (iview->image->planes[0].aux_usage == ISL_AUX_USAGE_CCS_E) {
> att_state->aux_usage = ISL_AUX_USAGE_CCS_E;
> att_state->input_aux_usage = ISL_AUX_USAGE_CCS_E;
> } else {
> @@ -255,7 +285,7 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
> * In other words, we can only sample from a fast-cleared image if
> it
> * also supports color compression.
> */
> - if (isl_format_supports_ccs_e(&device->info, iview->isl.format)) {
> + if (isl_format_supports_ccs_e(&device->info,
> iview->planes[0].isl.format)) {
> att_state->input_aux_usage = ISL_AUX_USAGE_CCS_D;
>
> /* While fast-clear resolves and partial resolves are fairly
> cheap in the
> @@ -274,10 +304,10 @@ color_attachment_compute_aux_usage(struct
> anv_device * device,
> }
> }
>
> - assert(iview->image->aux_surface.isl.usage & ISL_SURF_USAGE_CCS_BIT);
> + assert(iview->image->planes[0].aux_surface.isl.usage &
> ISL_SURF_USAGE_CCS_BIT);
>
> att_state->clear_color_is_zero_one =
> - color_is_zero_one(att_state->clear_value.color, iview->isl.format);
> + color_is_zero_one(att_state->clear_value.color,
> iview->planes[0].isl.format);
> att_state->clear_color_is_zero =
> att_state->clear_value.color.uint32[0] == 0 &&
> att_state->clear_value.color.uint32[1] == 0 &&
> @@ -309,7 +339,8 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
> * layers.
> */
> if (cmd_state->framebuffer->layers !=
> - anv_image_aux_layers(iview->image, iview->isl.base_level)) {
> + anv_image_aux_layers(iview->image, 0,
> + iview->planes[0].isl.base_level)) {
> att_state->fast_clear = false;
> if (GEN_GEN == 7) {
> anv_perf_warn(device->instance, iview->image,
> @@ -325,7 +356,7 @@ color_attachment_compute_aux_usage(struct anv_device
> * device,
> if (cmd_state->pass->attachments[att].first_subpass_layout ==
> VK_IMAGE_LAYOUT_GENERAL &&
> (!att_state->clear_color_is_zero ||
> - iview->image->aux_usage == ISL_AUX_USAGE_NONE)) {
> + iview->image->planes[0].aux_usage == ISL_AUX_USAGE_NONE)) {
> att_state->fast_clear = false;
> }
>
> @@ -370,14 +401,14 @@ transition_depth_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> * that's currently in the buffer. Therefore, a data-preserving resolve
> * operation is not needed.
> */
> - if (image->aux_usage != ISL_AUX_USAGE_HIZ || initial_layout ==
> final_layout)
> + if (image->planes[0].aux_usage != ISL_AUX_USAGE_HIZ || initial_layout
> == final_layout)
> return;
>
> const bool hiz_enabled = ISL_AUX_USAGE_HIZ ==
> - anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
> image->aspects,
> + anv_layout_to_aux_usage(&cmd_buffer->device->info, image, 0,
> initial_layout);
> const bool enable_hiz = ISL_AUX_USAGE_HIZ ==
> - anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
> image->aspects,
> + anv_layout_to_aux_usage(&cmd_buffer->device->info, image, 0,
> final_layout);
>
> enum blorp_hiz_op hiz_op;
> @@ -403,14 +434,16 @@ enum fast_clear_state_field {
> static inline uint32_t
> get_fast_clear_state_offset(const struct anv_device *device,
> const struct anv_image *image,
> - unsigned level, enum fast_clear_state_field
> field)
> + unsigned plane, unsigned level,
> + enum fast_clear_state_field field)
> {
> assert(device && image);
> - assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> - assert(level < anv_image_aux_levels(image));
> - uint32_t offset = image->offset + image->aux_surface.offset +
> - image->aux_surface.isl.size +
> - anv_fast_clear_state_entry_size(device) * level;
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> + assert(level < anv_image_aux_levels(image, plane));
> + /* Refer to the definition of anv_image for the memory layout. */
> + uint32_t offset = image->planes[plane].fast_clear_state_offset;
> +
> + offset += anv_fast_clear_state_entry_size(device) * level;
>
> switch (field) {
> case FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE:
> @@ -420,7 +453,8 @@ get_fast_clear_state_offset(const struct anv_device
> *device,
> break;
> }
>
> - assert(offset < image->offset + image->size);
> + assert(offset < image->planes[plane].surface.offset +
> image->planes[plane].size);
> +
> return offset;
> }
>
> @@ -433,14 +467,14 @@ get_fast_clear_state_offset(const struct anv_device
> *device,
> static void
> genX(set_image_needs_resolve)(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> - unsigned level, bool needs_resolve)
> + unsigned plane, unsigned level, bool
> needs_resolve)
> {
> assert(cmd_buffer && image);
> - assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> - assert(level < anv_image_aux_levels(image));
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> + assert(level < anv_image_aux_levels(image, plane));
>
> const uint32_t resolve_flag_offset =
> - get_fast_clear_state_offset(cmd_buffer->device, image, level,
> + get_fast_clear_state_offset(cmd_buffer->device, image, plane,
> level,
> FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
>
> /* The HW docs say that there is no way to guarantee the completion of
> @@ -448,7 +482,8 @@ genX(set_image_needs_resolve)(struct anv_cmd_buffer
> *cmd_buffer,
> * issues in testing is currently being used in the GL driver.
> */
> anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_DATA_IMM), sdi) {
> - sdi.Address = (struct anv_address) { image->bo, resolve_flag_offset
> };
> + sdi.Address = (struct anv_address) { image->planes[plane].bo,
> + resolve_flag_offset };
> sdi.ImmediateData = needs_resolve;
> }
> }
> @@ -456,14 +491,14 @@ genX(set_image_needs_resolve)(struct anv_cmd_buffer
> *cmd_buffer,
> static void
> genX(load_needs_resolve_predicate)(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> - unsigned level)
> + unsigned plane, unsigned level)
> {
> assert(cmd_buffer && image);
> - assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> - assert(level < anv_image_aux_levels(image));
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> + assert(level < anv_image_aux_levels(image, plane));
>
> const uint32_t resolve_flag_offset =
> - get_fast_clear_state_offset(cmd_buffer->device, image, level,
> + get_fast_clear_state_offset(cmd_buffer->device, image, plane,
> level,
> FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE);
>
> /* Make the pending predicated resolve a no-op if one is not needed.
> @@ -473,7 +508,7 @@ genX(load_needs_resolve_predicate)(struct
> anv_cmd_buffer *cmd_buffer,
> emit_lri(&cmd_buffer->batch, MI_PREDICATE_SRC1 + 4, 0);
> emit_lri(&cmd_buffer->batch, MI_PREDICATE_SRC0 , 0);
> emit_lrm(&cmd_buffer->batch, MI_PREDICATE_SRC0 + 4,
> - image->bo, resolve_flag_offset);
> + image->planes[plane].bo, resolve_flag_offset);
> anv_batch_emit(&cmd_buffer->batch, GENX(MI_PREDICATE), mip) {
> mip.LoadOperation = LOAD_LOADINV;
> mip.CombineOperation = COMBINE_SET;
> @@ -484,11 +519,11 @@ genX(load_needs_resolve_predicate)(struct
> anv_cmd_buffer *cmd_buffer,
> static void
> init_fast_clear_state_entry(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> - unsigned level)
> + unsigned plane, unsigned level)
> {
> assert(cmd_buffer && image);
> - assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> - assert(level < anv_image_aux_levels(image));
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> + assert(level < anv_image_aux_levels(image, plane));
>
> /* The resolve flag should updated to signify that
> fast-clear/compression
> * data needs to be removed when leaving the undefined layout. Such
> data
> @@ -496,8 +531,8 @@ init_fast_clear_state_entry(struct anv_cmd_buffer
> *cmd_buffer,
> * to return incorrect data. The fast clear data in CCS_D buffers
> should
> * be removed because CCS_D isn't enabled all the time.
> */
> - genX(set_image_needs_resolve)(cmd_buffer, image, level,
> - image->aux_usage == ISL_AUX_USAGE_NONE);
> + genX(set_image_needs_resolve)(cmd_buffer, image, plane, level,
> + image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_NONE);
>
> /* The fast clear value dword(s) will be copied into a surface state
> object.
> * Ensure that the restrictions of the fields in the dword(s) are
> followed.
> @@ -514,13 +549,14 @@ init_fast_clear_state_entry(struct anv_cmd_buffer
> *cmd_buffer,
> for (; i < cmd_buffer->device->isl_dev.ss.clear_value_size; i += 4) {
> anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_DATA_IMM), sdi) {
> const uint32_t entry_offset =
> - get_fast_clear_state_offset(cmd_buffer->device, image, level,
> + get_fast_clear_state_offset(cmd_buffer->device, image,
> plane, level,
> FAST_CLEAR_STATE_FIELD_CLEAR_
> COLOR);
> - sdi.Address = (struct anv_address) { image->bo, entry_offset + i
> };
> + sdi.Address = (struct anv_address) { image->planes[plane].bo,
> + entry_offset + i };
>
> if (GEN_GEN >= 9) {
> /* MCS buffers on SKL+ can only have 1/0 clear colors. */
> - assert(image->aux_usage == ISL_AUX_USAGE_MCS);
> + assert(image->planes[plane].aux_usage == ISL_AUX_USAGE_MCS);
> sdi.ImmediateData = 0;
> } else if (GEN_VERSIONx10 >= 75) {
> /* Pre-SKL, the dword containing the clear values also
> contains
> @@ -550,28 +586,31 @@ static void
> genX(copy_fast_clear_dwords)(struct anv_cmd_buffer *cmd_buffer,
> struct anv_state surface_state,
> const struct anv_image *image,
> - unsigned level,
> + unsigned plane, unsigned level,
> bool copy_from_surface_state)
> {
> assert(cmd_buffer && image);
> - assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> - assert(level < anv_image_aux_levels(image));
> + assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> + assert(level < anv_image_aux_levels(image, plane));
>
> struct anv_bo *ss_bo =
> &cmd_buffer->device->surface_state_pool.block_pool.bo;
> uint32_t ss_clear_offset = surface_state.offset +
> cmd_buffer->device->isl_dev.ss.clear_value_offset;
> uint32_t entry_offset =
> - get_fast_clear_state_offset(cmd_buffer->device, image, level,
> + get_fast_clear_state_offset(cmd_buffer->device, image, plane,
> level,
> FAST_CLEAR_STATE_FIELD_CLEAR_COLOR);
> unsigned copy_size = cmd_buffer->device->isl_dev.ss.clear_value_size;
>
> if (copy_from_surface_state) {
> - genX(cmd_buffer_mi_memcpy)(cmd_buffer, image->bo, entry_offset,
> + genX(cmd_buffer_mi_memcpy)(cmd_buffer,
> + image->planes[plane].bo,
> + entry_offset,
> ss_bo, ss_clear_offset, copy_size);
> } else {
> genX(cmd_buffer_mi_memcpy)(cmd_buffer, ss_bo, ss_clear_offset,
> - image->bo, entry_offset, copy_size);
> + image->planes[plane].bo,
> + entry_offset, copy_size);
>
> /* Updating a surface state object may require that the state cache
> be
> * invalidated. From the SKL PRM, Shared Functions -> State -> State
> @@ -603,6 +642,7 @@ genX(copy_fast_clear_dwords)(struct anv_cmd_buffer
> *cmd_buffer,
> static void
> transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
> const struct anv_image *image,
> + const uint32_t plane,
> const uint32_t base_level, uint32_t level_count,
> uint32_t base_layer, uint32_t layer_count,
> VkImageLayout initial_layout,
> @@ -610,7 +650,7 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> {
> /* Validate the inputs. */
> assert(cmd_buffer);
> - assert(image && image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> + assert(image && image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT);
> /* These values aren't supported for simplicity's sake. */
> assert(level_count != VK_REMAINING_MIP_LEVELS &&
> layer_count != VK_REMAINING_ARRAY_LAYERS);
> @@ -630,22 +670,22 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> if (initial_layout == final_layout)
> return;
>
> - if (image->shadow_surface.isl.size > 0 &&
> + if (image->planes[plane].shadow_surface.isl.size > 0 &&
> final_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
> /* This surface is a linear compressed image with a tiled shadow
> surface
> * for texturing. The client is about to use it in
> READ_ONLY_OPTIMAL so
> * we need to ensure the shadow copy is up-to-date.
> */
> assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
> - assert(image->color_surface.isl.tiling == ISL_TILING_LINEAR);
> - assert(image->shadow_surface.isl.tiling != ISL_TILING_LINEAR);
> - assert(isl_format_is_compressed(image->color_surface.isl.format));
> - anv_image_copy_to_shadow(cmd_buffer, image,
> VK_IMAGE_ASPECT_COLOR_BIT,
> + assert(image->planes[plane].surface.isl.tiling ==
> ISL_TILING_LINEAR);
> + assert(image->planes[plane].shadow_surface.isl.tiling !=
> ISL_TILING_LINEAR);
> + assert(isl_format_is_compressed(image->planes[
> plane].surface.isl.format));
> + anv_image_copy_to_shadow(cmd_buffer, image, plane,
> base_level, level_count,
> base_layer, layer_count);
> }
>
> - if (base_layer >= anv_image_aux_layers(image, base_level))
> + if (base_layer >= anv_image_aux_layers(image, plane, base_level))
> return;
>
> /* A transition of a 3D subresource works on all slices at a time. */
> @@ -655,9 +695,9 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> }
>
> /* We're interested in the subresource range subset that has aux data.
> */
> - level_count = MIN2(level_count, anv_image_aux_levels(image) -
> base_level);
> + level_count = MIN2(level_count, anv_image_aux_levels(image, plane) -
> base_level);
> layer_count = MIN2(layer_count,
> - anv_image_aux_layers(image, base_level) -
> base_layer);
> + anv_image_aux_layers(image, plane, base_level) -
> base_layer);
> last_level_num = base_level + level_count;
>
> /* Record whether or not the layout is undefined. Pre-initialized
> images
> @@ -678,7 +718,7 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> * Initialize the relevant clear buffer entries.
> */
> for (unsigned level = base_level; level < last_level_num; level++)
> - init_fast_clear_state_entry(cmd_buffer, image, level);
> + init_fast_clear_state_entry(cmd_buffer, image, plane, level);
>
> /* Initialize the aux buffers to enable correct rendering. This
> operation
> * requires up to two steps: one to rid the aux buffer of data that
> may
> @@ -702,7 +742,8 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> "define an MCS buffer.");
> }
>
> - anv_image_fast_clear(cmd_buffer, image, base_level, level_count,
> + anv_image_fast_clear(cmd_buffer, image, plane,
> + base_level, level_count,
> base_layer, layer_count);
> }
> /* At this point, some elements of the CCS buffer may have the
> fast-clear
> @@ -714,7 +755,8 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> * enabled. In this case, we must force the associated CCS buffers
> of the
> * specified range to enter the ambiguated state in advance.
> */
> - if (image->samples == 1 && image->aux_usage != ISL_AUX_USAGE_CCS_E
> &&
> + if (image->samples == 1 &&
> + image->planes[plane].aux_usage != ISL_AUX_USAGE_CCS_E &&
> final_layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
> /* The CCS_D buffer may not be enabled in the final layout.
> Continue
> * executing this function to perform a resolve.
> @@ -766,13 +808,14 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
>
> /* The number of layers changes at each 3D miplevel. */
> if (image->type == VK_IMAGE_TYPE_3D) {
> - layer_count = MIN2(layer_count, anv_image_aux_layers(image,
> level));
> + layer_count = MIN2(layer_count, anv_image_aux_layers(image,
> plane, level));
> }
>
> - genX(load_needs_resolve_predicate)(cmd_buffer, image, level);
> + genX(load_needs_resolve_predicate)(cmd_buffer, image, plane,
> level);
>
> - enum isl_aux_usage aux_usage = image->aux_usage ==
> ISL_AUX_USAGE_NONE ?
> - ISL_AUX_USAGE_CCS_D :
> image->aux_usage;
> + enum isl_aux_usage aux_usage =
> + image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE ?
> + ISL_AUX_USAGE_CCS_D : image->planes[plane].aux_usage;
>
> /* Create a surface state with the right clear color and perform the
> * resolve.
> @@ -780,9 +823,9 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> struct anv_surface_state surface_state;
> surface_state.state = anv_cmd_buffer_alloc_surface_
> state(cmd_buffer);
> anv_image_fill_surface_state(cmd_buffer->device,
> - image, VK_IMAGE_ASPECT_COLOR_BIT,
> + image, plane,
> &(struct isl_view) {
> - .format = image->color_surface.isl.
> format,
> + .format =
> image->planes[plane].surface.isl.format,
> .swizzle = ISL_SWIZZLE_IDENTITY,
> .base_level = level,
> .levels = 1,
> @@ -792,16 +835,16 @@ transition_color_buffer(struct anv_cmd_buffer
> *cmd_buffer,
> ISL_SURF_USAGE_RENDER_TARGET_BIT,
> aux_usage, NULL, 0,
> &surface_state, NULL);
> - add_image_relocs(cmd_buffer, image, surface_state);
> + add_image_relocs(cmd_buffer, image, 0, surface_state);
> genX(copy_fast_clear_dwords)(cmd_buffer, surface_state.state,
> image,
> - level, false /* copy to ss */);
> + plane, level, false /* copy to ss */);
> anv_ccs_resolve(cmd_buffer, surface_state.state, image,
> - level, layer_count,
> - image->aux_usage == ISL_AUX_USAGE_CCS_E ?
> + plane, level, layer_count,
> + image->planes[plane].aux_usage ==
> ISL_AUX_USAGE_CCS_E ?
> BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL :
> BLORP_FAST_CLEAR_OP_RESOLVE_FULL);
>
> - genX(set_image_needs_resolve)(cmd_buffer, image, level, false);
> + genX(set_image_needs_resolve)(cmd_buffer, image, plane, level,
> false);
> }
>
> cmd_buffer->state.pending_pipe_bits |=
> @@ -887,7 +930,7 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
> VkImageAspectFlags att_aspects = vk_format_aspects(att->format);
> VkImageAspectFlags clear_aspects = 0;
>
> - if (att_aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
> + if (att_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> /* color attachment */
> if (att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
> clear_aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
> @@ -911,17 +954,17 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>
> struct anv_image_view *iview = framebuffer->attachments[i];
> anv_assert(iview->vk_format == att->format);
> + anv_assert(iview->n_planes == 1);
>
> union isl_color_value clear_color = { .u32 = { 0, } };
> - if (att_aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
> + if (att_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> color_attachment_compute_aux_usage(cmd_buffer->device,
> state, i,
> begin->renderArea,
> &clear_color);
>
> anv_image_fill_surface_state(cmd_buffer->device,
> - iview->image,
> - VK_IMAGE_ASPECT_COLOR_BIT,
> - &iview->isl,
> + iview->image, 0,
> + &iview->planes[0].isl,
> ISL_SURF_USAGE_RENDER_TARGET_
> BIT,
> state->attachments[i].aux_usage,
> &clear_color,
> @@ -929,8 +972,8 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
> &state->attachments[i].color,
> NULL);
>
> - add_image_relocs(cmd_buffer, iview->image,
> - state->attachments[i].color);
> + add_image_view_relocs(cmd_buffer, iview, 0,
> + state->attachments[i].color);
> } else {
> /* This field will be initialized after the first subpass
> * transition.
> @@ -942,9 +985,8 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>
> if (need_input_attachment_state(&pass->attachments[i])) {
> anv_image_fill_surface_state(cmd_buffer->device,
> - iview->image,
> - VK_IMAGE_ASPECT_COLOR_BIT,
> - &iview->isl,
> + iview->image, 0,
> + &iview->planes[0].isl,
> ISL_SURF_USAGE_TEXTURE_BIT,
> state->attachments[i].input_
> aux_usage,
> &clear_color,
> @@ -952,8 +994,8 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
> &state->attachments[i].input,
> NULL);
>
> - add_image_relocs(cmd_buffer, iview->image,
> - state->attachments[i].input);
> + add_image_view_relocs(cmd_buffer, iview, 0,
> + state->attachments[i].input);
> }
> }
> }
> @@ -1378,14 +1420,21 @@ void genX(CmdPipelineBarrier)(
> transition_depth_buffer(cmd_buffer, image,
> pImageMemoryBarriers[i].oldLayout,
> pImageMemoryBarriers[i].newLayout);
> - } else if (range->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
> - transition_color_buffer(cmd_buffer, image,
> - range->baseMipLevel,
> - anv_get_levelCount(image, range),
> - range->baseArrayLayer,
> - anv_get_layerCount(image, range),
> - pImageMemoryBarriers[i].oldLayout,
> - pImageMemoryBarriers[i].newLayout);
> + } else if (range->aspectMask & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> + VkImageAspectFlags color_aspects =
> + anv_image_color_aspects(image, range->aspectMask);
> + uint32_t aspect_bit, plane;
> +
> + anv_foreach_plane_aspect_bit(plane, aspect_bit, color_aspects,
> + image->aspects) {
> + transition_color_buffer(cmd_buffer, image, plane,
> + range->baseMipLevel,
> + anv_get_levelCount(image, range),
> + range->baseArrayLayer,
> + anv_get_layerCount(image, range),
> + pImageMemoryBarriers[i].oldLayout,
> + pImageMemoryBarriers[i].newLayout);
> + }
> }
> }
>
> @@ -1574,26 +1623,28 @@ emit_binding_table(struct anv_cmd_buffer
> *cmd_buffer,
> case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
> struct anv_surface_state sstate =
> (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ?
> - desc->image_view->general_sampler_surface_state :
> - desc->image_view->optimal_sampler_surface_state;
> + desc->image_view->planes[binding->plane].general_sampler_surface_state
> :
> + desc->image_view->planes[binding->plane].optimal_
> sampler_surface_state;
> surface_state = sstate.state;
> assert(surface_state.alloc_size);
> - add_image_relocs(cmd_buffer, desc->image_view->image, sstate);
> + add_image_view_relocs(cmd_buffer, desc->image_view,
> + binding->plane, sstate);
> break;
> }
> case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
> assert(stage == MESA_SHADER_FRAGMENT);
> - if (desc->image_view->aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT) {
> + if ((desc->image_view->aspect_mask &
> VK_IMAGE_ASPECT_ANY_COLOR_BIT) == 0) {
> /* For depth and stencil input attachments, we treat it like
> any
> * old texture that a user may have bound.
> */
> struct anv_surface_state sstate =
> (desc->layout == VK_IMAGE_LAYOUT_GENERAL) ?
> - desc->image_view->general_sampler_surface_state :
> - desc->image_view->optimal_sampler_surface_state;
> + desc->image_view->planes[binding->plane].general_sampler_surface_state
> :
> + desc->image_view->planes[binding->plane].optimal_
> sampler_surface_state;
> surface_state = sstate.state;
> assert(surface_state.alloc_size);
> - add_image_relocs(cmd_buffer, desc->image_view->image, sstate);
> + add_image_view_relocs(cmd_buffer, desc->image_view,
> + binding->plane, sstate);
> } else {
> /* For color input attachments, we create the surface state at
> * vkBeginRenderPass time so that we can include aux and clear
> @@ -1608,16 +1659,17 @@ emit_binding_table(struct anv_cmd_buffer
> *cmd_buffer,
>
> case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
> struct anv_surface_state sstate = (binding->write_only)
> - ? desc->image_view->writeonly_storage_surface_state
> - : desc->image_view->storage_surface_state;
> + ? desc->image_view->planes[binding->plane].writeonly_
> storage_surface_state
> + : desc->image_view->planes[binding->plane].storage_
> surface_state;
> surface_state = sstate.state;
> assert(surface_state.alloc_size);
> - add_image_relocs(cmd_buffer, desc->image_view->image, sstate);
> + add_image_view_relocs(cmd_buffer, desc->image_view,
> + binding->plane, sstate);
>
> struct brw_image_param *image_param =
> &cmd_buffer->state.push_constants[stage]->images[image++];
>
> - *image_param = desc->image_view->storage_image_param;
> + *image_param = desc->image_view->planes[
> binding->plane].storage_image_param;
> image_param->surface_idx = bias + s;
> break;
> }
> @@ -2753,41 +2805,51 @@ cmd_buffer_emit_depth_stencil(struct
> anv_cmd_buffer *cmd_buffer)
> };
>
> if (iview)
> - info.view = &iview->isl;
> + info.view = &iview->planes[0].isl;
>
> if (image && (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {
> - info.depth_surf = &image->depth_surface.isl;
> + uint32_t depth_plane =
> + anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_DEPTH_BIT);
> + const struct anv_surface *surface = &image->planes[depth_plane].
> surface;
> +
> + info.depth_surf = &surface->isl;
>
> info.depth_address =
> anv_batch_emit_reloc(&cmd_buffer->batch,
> dw + device->isl_dev.ds.depth_offset / 4,
> - image->bo,
> - image->offset +
> image->depth_surface.offset);
> + image->planes[depth_plane].bo,
> + image->planes[depth_plane].bo_offset +
> + surface->offset);
>
> const uint32_t ds =
> cmd_buffer->state.subpass->depth_stencil_attachment.attachment;
> info.hiz_usage = cmd_buffer->state.attachments[ds].aux_usage;
> if (info.hiz_usage == ISL_AUX_USAGE_HIZ) {
> - info.hiz_surf = &image->aux_surface.isl;
> + info.hiz_surf = &image->planes[depth_plane].aux_surface.isl;
>
> info.hiz_address =
> anv_batch_emit_reloc(&cmd_buffer->batch,
> dw + device->isl_dev.ds.hiz_offset / 4,
> - image->bo,
> - image->offset +
> image->aux_surface.offset);
> + image->planes[depth_plane].bo,
> + image->planes[depth_plane].bo_offset +
> + image->planes[depth_plane].
> aux_surface.offset);
>
> info.depth_clear_value = ANV_HZ_FC_VAL;
> }
> }
>
> if (image && (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) {
> - info.stencil_surf = &image->stencil_surface.isl;
> + uint32_t stencil_plane =
> + anv_image_aspect_to_plane(image->aspects,
> VK_IMAGE_ASPECT_STENCIL_BIT);
> + const struct anv_surface *surface = &image->planes[stencil_plane].
> surface;
> +
> + info.stencil_surf = &surface->isl;
>
> info.stencil_address =
> anv_batch_emit_reloc(&cmd_buffer->batch,
> dw + device->isl_dev.ds.stencil_offset / 4,
> - image->bo,
> - image->offset +
> image->stencil_surface.offset);
> + image->planes[stencil_plane].bo,
> + image->planes[stencil_plane].bo_offset +
> surface->offset);
> }
>
> isl_emit_depth_stencil_hiz_s(&device->isl_dev, dw, &info);
> @@ -2877,7 +2939,7 @@ cmd_buffer_subpass_transition_layouts(struct
> anv_cmd_buffer * const cmd_buffer,
> att_state->input_aux_usage != att_state->aux_usage;
> if (subpass_end) {
> target_layout = att_desc->final_layout;
> - } else if (iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT &&
> + } else if (iview->aspect_mask & VK_IMAGE_ASPECT_ANY_COLOR_BIT &&
> !input_needs_resolve) {
> /* Layout transitions before the final only help to enable
> sampling as
> * an input attachment. If the input attachment supports sampling
> @@ -2895,12 +2957,12 @@ cmd_buffer_subpass_transition_layouts(struct
> anv_cmd_buffer * const cmd_buffer,
> att_state->current_layout,
> target_layout);
> att_state->aux_usage =
> anv_layout_to_aux_usage(&cmd_buffer->device->info, image,
> - image->aspects, target_layout);
> - } else if (image->aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
> - transition_color_buffer(cmd_buffer, image,
> - iview->isl.base_level, 1,
> - iview->isl.base_array_layer,
> - iview->isl.array_len,
> + 0, target_layout);
> + } else if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) {
> + transition_color_buffer(cmd_buffer, image, 0,
> + iview->planes[0].isl.base_level, 1,
> + iview->planes[0].isl.base_array_layer,
> + iview->planes[0].isl.array_len,
> att_state->current_layout,
> target_layout);
> }
>
> @@ -2945,22 +3007,24 @@ cmd_buffer_subpass_sync_fast_clear_values(struct
> anv_cmd_buffer *cmd_buffer)
> if (att_state->pending_clear_aspects && att_state->fast_clear) {
> /* Update the fast clear state entry. */
> genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state,
> - iview->image, iview->isl.base_level,
> + iview->image, 0,
> iview->planes[0].isl.base_level,
> true /* copy from ss */);
>
> /* Fast-clears impact whether or not a resolve will be
> necessary. */
> - if (iview->image->aux_usage == ISL_AUX_USAGE_CCS_E &&
> + if (iview->image->planes[0].aux_usage == ISL_AUX_USAGE_CCS_E &&
> att_state->clear_color_is_zero) {
> /* This image always has the auxiliary buffer enabled. We can
> mark
> * the subresource as not needing a resolve because the clear
> color
> * will match what's in every RENDER_SURFACE_STATE object
> when it's
> * being used for sampling.
> */
> - genX(set_image_needs_resolve)(cmd_buffer, iview->image,
> - iview->isl.base_level, false);
> + genX(set_image_needs_resolve)(cmd_buffer, iview->image, 0,
> + iview->planes[0].isl.base_
> level,
> + false);
> } else {
> - genX(set_image_needs_resolve)(cmd_buffer, iview->image,
> - iview->isl.base_level, true);
> + genX(set_image_needs_resolve)(cmd_buffer, iview->image, 0,
> + iview->planes[0].isl.base_
> level,
> + true);
> }
> } else if (rp_att->load_op == VK_ATTACHMENT_LOAD_OP_LOAD) {
> /* The attachment may have been fast-cleared in a previous render
> @@ -2969,13 +3033,13 @@ cmd_buffer_subpass_sync_fast_clear_values(struct
> anv_cmd_buffer *cmd_buffer)
> * TODO: Do this only once per render pass instead of every
> subpass.
> */
> genX(copy_fast_clear_dwords)(cmd_buffer, att_state->color.state,
> - iview->image, iview->isl.base_level,
> + iview->image, 0,
> iview->planes[0].isl.base_level,
> false /* copy to ss */);
>
> if (need_input_attachment_state(rp_att) &&
> att_state->input_aux_usage != ISL_AUX_USAGE_NONE) {
> genX(copy_fast_clear_dwords)(cmd_buffer,
> att_state->input.state,
> - iview->image,
> iview->isl.base_level,
> + iview->image, 0,
> iview->planes[0].isl.base_level,
> false /* copy to ss */);
> }
> }
> --
> 2.14.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20171003/8d4e7b4a/attachment-0001.html>
More information about the mesa-dev
mailing list