From: Lionel Landwerlin Date: Wed, 19 Jul 2017 11:14:19 +0000 (+0100) Subject: anv: enable multiple planes per image/imageView X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a62a97933578a813beb0d27cc8e404850f7fd302;p=mesa.git anv: enable multiple planes per image/imageView 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). v2: by Jason Remove unused aspect parameters from anv_blorp.c Assert when attempting to resolve YUV images Drop redundant logic for plane offset in make_surface() Rework anv_foreach_plane_aspect_bit() Signed-off-by: Lionel Landwerlin Reviewed-by: Jason Ekstrand --- diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index 27ab7ef9d90..70e1b2b022c 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -183,29 +183,30 @@ get_blorp_surf_for_anv_image(const struct anv_image *image, enum isl_aux_usage aux_usage, struct blorp_surf *blorp_surf) { + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + if (aux_usage == ANV_AUX_USAGE_DEFAULT) - aux_usage = image->aux_usage; + aux_usage = image->planes[plane].aux_usage; 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; } @@ -254,17 +255,35 @@ 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 aspect_bit; + anv_foreach_image_aspect_bit(aspect_bit, src_image, src_mask) { + struct blorp_surf src_surf, dst_surf; + get_blorp_surf_for_anv_image(src_image, 1UL << aspect_bit, + ANV_AUX_USAGE_DEFAULT, &src_surf); + get_blorp_surf_for_anv_image(dst_image, 1UL << aspect_bit, + ANV_AUX_USAGE_DEFAULT, &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 { struct blorp_surf src_surf, dst_surf; - get_blorp_surf_for_anv_image(src_image, aspect, + get_blorp_surf_for_anv_image(src_image, src_mask, ANV_AUX_USAGE_DEFAULT, &src_surf); - get_blorp_surf_for_anv_image(dst_image, aspect, + get_blorp_surf_for_anv_image(dst_image, dst_mask, ANV_AUX_USAGE_DEFAULT, &dst_surf); for (unsigned i = 0; i < layer_count; i++) { @@ -753,15 +772,16 @@ 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, - ANV_AUX_USAGE_DEFAULT, &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); + + struct blorp_surf surf; + get_blorp_surf_for_anv_image(image, pRanges[r].aspectMask, + ANV_AUX_USAGE_DEFAULT, &surf); struct anv_format_plane src_format = anv_get_format_plane(&cmd_buffer->device->info, image->vk_format, @@ -1048,7 +1068,8 @@ 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) { + assert(pAttachments[a].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); clear_color_attachment(cmd_buffer, &batch, &pAttachments[a], rectCount, pRects); @@ -1159,9 +1180,10 @@ 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, + assert(image->n_planes == 1); + blorp_fast_clear(&batch, &surf, iview->planes[0].isl.format, + iview->planes[0].isl.base_level, + iview->planes[0].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); @@ -1169,10 +1191,11 @@ 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; } 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, + assert(image->n_planes == 1); + blorp_clear(&batch, &surf, iview->planes[0].isl.format, + anv_swizzle_for_render(iview->planes[0].isl.swizzle), + iview->planes[0].isl.base_level, + iview->planes[0].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, @@ -1211,7 +1234,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, @@ -1279,13 +1302,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, @@ -1295,25 +1335,24 @@ 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 aspect_bit; + anv_foreach_image_aspect_bit(aspect_bit, src_image, aspect_mask) { 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, 1UL << aspect_bit, + ANV_AUX_USAGE_DEFAULT, &src_surf); + get_blorp_surf_for_anv_image(dst_image, 1UL << aspect_bit, + ANV_AUX_USAGE_DEFAULT, &dst_surf); + + assert(!src_image->format->can_ycbcr); + assert(!dst_image->format->can_ycbcr); + + resolve_surface(batch, + &src_surf, src_level, src_layer, + &dst_surf, dst_level, dst_layer, + src_x, src_y, dst_x, dst_y, width, height); } } @@ -1342,12 +1381,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, ANV_AUX_USAGE_DEFAULT, + src_image, pRegions[r].srcSubresource.mipLevel, pRegions[r].srcSubresource.baseArrayLayer + layer, - dst_image, ANV_AUX_USAGE_DEFAULT, + dst_image, pRegions[r].dstSubresource.mipLevel, pRegions[r].dstSubresource.baseArrayLayer + layer, pRegions[r].dstSubresource.aspectMask, @@ -1360,9 +1404,21 @@ void anv_CmdResolveImage( blorp_batch_finish(&batch); } +static enum isl_aux_usage +fast_clear_aux_usage(const struct anv_image *image, + VkImageAspectFlagBits aspect) +{ + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE) + return ISL_AUX_USAGE_CCS_D; + else + return image->planes[plane].aux_usage; +} + void anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer, const struct anv_image *image, + VkImageAspectFlagBits aspect, const uint32_t base_level, const uint32_t level_count, const uint32_t base_layer, uint32_t layer_count) { @@ -1377,9 +1433,8 @@ 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, aspect, + fast_clear_aux_usage(image, aspect), &surf); /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear": @@ -1400,6 +1455,10 @@ 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 plane = anv_image_aspect_to_plane(image->aspects, aspect); + uint32_t width_div = image->format->planes[plane].denominator_scales[0]; + uint32_t 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; @@ -1412,11 +1471,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, aspect)); + assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, 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 |= @@ -1472,18 +1533,30 @@ 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); - - 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); + assert(src_iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT && + dst_iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT); + + struct blorp_surf src_surf, dst_surf; + get_blorp_surf_for_anv_image(src_iview->image, + VK_IMAGE_ASPECT_COLOR_BIT, + src_aux_usage, &src_surf); + get_blorp_surf_for_anv_image(dst_iview->image, + VK_IMAGE_ASPECT_COLOR_BIT, + dst_aux_usage, &dst_surf); + + assert(!src_iview->image->format->can_ycbcr); + assert(!dst_iview->image->format->can_ycbcr); + + 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, render_area.offset.y, + render_area.offset.x, render_area.offset.y, + render_area.extent.width, render_area.extent.height); } blorp_batch_finish(&batch); @@ -1493,22 +1566,24 @@ 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 base_level, uint32_t level_count, uint32_t base_layer, uint32_t layer_count) { struct blorp_batch batch; blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0); + assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT && image->n_planes == 1); + struct blorp_surf surf; get_blorp_surf_for_anv_image(image, VK_IMAGE_ASPECT_COLOR_BIT, ISL_AUX_USAGE_NONE, &surf); struct blorp_surf shadow_surf = { - .surf = &image->shadow_surface.isl, + .surf = &image->planes[0].shadow_surface.isl, .addr = { - .buffer = image->bo, - .offset = image->offset + image->shadow_surface.offset, + .buffer = image->planes[0].bo, + .offset = image->planes[0].bo_offset + + image->planes[0].shadow_surface.offset, }, }; @@ -1543,11 +1618,14 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer *cmd_buffer, { assert(image); + assert(anv_image_aspect_to_plane(image->aspects, + VK_IMAGE_ASPECT_DEPTH_BIT) == 0); + /* Don't resolve depth buffers without an auxiliary HiZ buffer and * 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 || @@ -1561,10 +1639,11 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer *cmd_buffer, 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; @@ -1578,15 +1657,18 @@ void anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer, const struct anv_state surface_state, const struct anv_image * const image, + VkImageAspectFlagBits aspect, const uint8_t level, const uint32_t layer_count, const enum blorp_fast_clear_op op) { assert(cmd_buffer && image); + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + /* 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, aspect)); + assert(layer_count <= anv_image_aux_layers(image, aspect, 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; @@ -1601,13 +1683,13 @@ 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 ? - ISL_AUX_USAGE_CCS_E : ISL_AUX_USAGE_CCS_D, + get_blorp_surf_for_anv_image(image, aspect, + fast_clear_aux_usage(image, aspect), &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 795055b52ff..879eb072b10 100644 --- a/src/intel/vulkan/anv_formats.c +++ b/src/intel/vulkan/anv_formats.c @@ -430,8 +430,7 @@ anv_get_format_plane(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 1328f4cc27b..78daf4dc55f 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; + } + image->size = surf->offset + surf->isl.size; + image->planes[plane].size = (surf->offset + surf->isl.size) - image->planes[plane].offset; + image->alignment = MAX2(image->alignment, surf->isl.alignment); + image->planes[plane].alignment = MAX2(image->planes[plane].alignment, + surf->isl.alignment); } @@ -194,11 +202,13 @@ all_formats_ccs_e_compatible(const struct gen_device_info *devinfo, */ static void add_fast_clear_state_buffer(struct anv_image *image, + VkImageAspectFlagBits aspect, + 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 +222,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, aspect); + + 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,14 +282,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_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_format_plane(&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 @@ -278,16 +300,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, @@ -302,7 +324,9 @@ make_surface(const struct anv_device *dev, */ assert(ok); - add_surface(image, anv_surf); + image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE; + + 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 @@ -312,9 +336,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, @@ -331,7 +355,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. @@ -357,24 +381,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: Disallow compression with : + * + * 1) non multiplanar images (We appear to hit a sampler bug with + * CCS & R16G16 format. Putting the clear state a page/4096bytes + * further fixes the issue). + * + * 2) alias images, because they might be aliases of images + * described in 1) + * + * 3) compression 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. @@ -382,12 +425,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, aspect, plane, dev); /* For images created without MUTABLE_FORMAT_BIT set, we know that * they will always be used with the original format. In @@ -399,22 +442,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, aspect, 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; } @@ -446,13 +509,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) { @@ -499,48 +567,61 @@ anv_DestroyImage(VkDevice _device, VkImage _image, vk_free2(&device->alloc, pAllocator, image); } -static void -anv_bind_image_memory(const VkBindImageMemoryInfoKHR *pBindInfo) +static void 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 = NULL; + image->planes[plane].bo_offset = 0; } - image->bo = mem->bo; - image->offset = pBindInfo->memoryOffset; + image->planes[plane].bo = memory->bo; + image->planes[plane].bo_offset = memory_offset; } 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 aspect_bit; + anv_foreach_image_aspect_bit(aspect_bit, image, image->aspects) { + uint32_t plane = + anv_image_aspect_to_plane(image->aspects, 1UL << aspect_bit); + anv_image_bind_memory_plane(device, image, plane, mem, memoryOffset); + } return VK_SUCCESS; } VkResult anv_BindImageMemory2KHR( - VkDevice device, + VkDevice _device, uint32_t bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos) { - for (uint32_t i = 0; i < bindInfoCount; i++) - anv_bind_image_memory(&pBindInfos[i]); + ANV_FROM_HANDLE(anv_device, device, _device); + + for (uint32_t i = 0; i < bindInfoCount; i++) { + const VkBindImageMemoryInfoKHR *bind_info = &pBindInfos[i]; + ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory); + ANV_FROM_HANDLE(anv_image, image, bind_info->image); + uint32_t aspect_bit; + + anv_foreach_image_aspect_bit(aspect_bit, image, image->aspects) { + uint32_t plane = + anv_image_aspect_to_plane(image->aspects, 1UL << aspect_bit); + anv_image_bind_memory_plane(device, image, plane, + mem, bind_info->memoryOffset); + } + } return VK_SUCCESS; } @@ -574,22 +655,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); } /** @@ -600,7 +669,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. @@ -624,26 +693,25 @@ anv_layout_to_aux_usage(const struct gen_device_info * const devinfo, /* Determine the optimal buffer. */ + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + /* If there is no auxiliary surface allocated, we must use the one and only * main buffer. */ - if (image->aux_surface.isl.size == 0) + if (image->planes[plane].aux_surface.isl.size == 0) return ISL_AUX_USAGE_NONE; /* All images that use an auxiliary surface are required to be tiled. */ assert(image->tiling == VK_IMAGE_TILING_OPTIMAL); /* Stencil has no aux */ - if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) - return ISL_AUX_USAGE_NONE; - - const bool color_aspect = aspect == VK_IMAGE_ASPECT_COLOR_BIT; + assert(aspect != VK_IMAGE_ASPECT_STENCIL_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) { @@ -677,7 +745,7 @@ 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: @@ -688,7 +756,7 @@ anv_layout_to_aux_usage(const struct gen_device_info * const devinfo, return ISL_AUX_USAGE_NONE; case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: - assert(color_aspect); + assert(image->aspects == VK_IMAGE_ASPECT_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 @@ -710,7 +778,7 @@ 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_COLOR_BIT); unreachable("Color images are not yet supported."); case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: @@ -766,8 +834,10 @@ 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); + uint32_t plane = anv_image_aspect_to_plane(image->aspects, 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; @@ -777,13 +847,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) @@ -798,9 +868,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) && @@ -889,7 +959,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, @@ -920,6 +990,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, @@ -964,106 +1050,130 @@ 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_expand_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_format_plane(&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; + anv_foreach_image_aspect_bit(iaspect_bit, image, expanded_aspects) { + uint32_t iplane = + anv_image_aspect_to_plane(expanded_aspects, 1UL << iaspect_bit); + VkImageAspectFlags vplane_aspect = + anv_plane_to_aspect(iview->aspect_mask, vplane); + struct anv_format_plane format = + anv_get_format_plane(&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, 1UL << iaspect_bit, + VK_IMAGE_LAYOUT_GENERAL); + enum isl_aux_usage optimal_aux_usage = + anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit, + &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, 1ULL << iaspect_bit, + &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, 1ULL << iaspect_bit, + &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, 1ULL << iaspect_bit, + &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); @@ -1081,24 +1191,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); @@ -1206,16 +1318,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: @@ -1229,13 +1346,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; } - 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 0513780ede5..75b7044de81 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1551,6 +1551,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; @@ -2214,10 +2224,47 @@ 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_image_aspect_bit(b, image, aspects) \ + for_each_bit(b, anv_image_expand_aspects(image, aspects)) + const struct anv_format * anv_get_format(VkFormat format); @@ -2277,72 +2324,116 @@ 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, + VkImageAspectFlagBits aspect) { - assert(image); - return image->aux_surface.isl.size > 0 ? image->aux_surface.isl.levels : 0; + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + 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, + VkImageAspectFlagBits aspect, const uint8_t miplevel) { assert(image); @@ -2350,14 +2441,15 @@ 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, aspect)) { /* 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); + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + return MAX2(image->planes[plane].aux_surface.isl.logical_level0_px.array_len, + image->planes[plane].aux_surface.isl.logical_level0_px.depth >> miplevel); } } @@ -2400,19 +2492,20 @@ void anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer, const struct anv_state surface_state, const struct anv_image * const image, + VkImageAspectFlagBits aspect, 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, + VkImageAspectFlagBits aspect, 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 base_level, uint32_t level_count, uint32_t base_layer, uint32_t layer_count); @@ -2437,37 +2530,72 @@ anv_get_levelCount(const struct anv_image *image, image->levels - range->baseMipLevel : range->levelCount; } +static inline VkImageAspectFlags +anv_image_expand_aspects(const 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; +} + +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 { 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 dcebf1d3c42..93d360a1bbe 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, VK_IMAGE_ASPECT_COLOR_BIT, + 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, VK_IMAGE_ASPECT_COLOR_BIT, + 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,7 +401,7 @@ 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 == @@ -403,14 +434,20 @@ enum fast_clear_state_field { static inline struct anv_address get_fast_clear_state_address(const struct anv_device *device, const struct anv_image *image, - unsigned level, enum fast_clear_state_field field) + VkImageAspectFlagBits aspect, + 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, aspect)); + + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + + /* 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,9 +457,10 @@ get_fast_clear_state_address(const struct anv_device *device, break; } - assert(offset < image->offset + image->size); + assert(offset < image->planes[plane].surface.offset + image->planes[plane].size); + return (struct anv_address) { - .bo = image->bo, + .bo = image->planes[plane].bo, .offset = offset, }; } @@ -436,14 +474,15 @@ get_fast_clear_state_address(const struct anv_device *device, static void genX(set_image_needs_resolve)(struct anv_cmd_buffer *cmd_buffer, const struct anv_image *image, + VkImageAspectFlagBits aspect, 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, aspect)); const struct anv_address resolve_flag_addr = - get_fast_clear_state_address(cmd_buffer->device, image, level, + get_fast_clear_state_address(cmd_buffer->device, image, aspect, level, FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE); /* The HW docs say that there is no way to guarantee the completion of @@ -459,14 +498,15 @@ 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, + VkImageAspectFlagBits aspect, 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, aspect)); const struct anv_address resolve_flag_addr = - get_fast_clear_state_address(cmd_buffer->device, image, level, + get_fast_clear_state_address(cmd_buffer->device, image, aspect, level, FAST_CLEAR_STATE_FIELD_NEEDS_RESOLVE); /* Make the pending predicated resolve a no-op if one is not needed. @@ -487,11 +527,15 @@ 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, + VkImageAspectFlagBits aspect, 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, aspect)); + + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + enum isl_aux_usage aux_usage = image->planes[plane].aux_usage; /* The resolve flag should updated to signify that fast-clear/compression * data needs to be removed when leaving the undefined layout. Such data @@ -499,8 +543,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, aspect, level, + 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. @@ -517,12 +561,12 @@ 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) { sdi.Address = - get_fast_clear_state_address(cmd_buffer->device, image, level, + get_fast_clear_state_address(cmd_buffer->device, image, aspect, level, FAST_CLEAR_STATE_FIELD_CLEAR_COLOR); if (GEN_GEN >= 9) { /* MCS buffers on SKL+ can only have 1/0 clear colors. */ - assert(image->aux_usage == ISL_AUX_USAGE_MCS); + assert(aux_usage == ISL_AUX_USAGE_MCS); sdi.ImmediateData = 0; } else if (GEN_VERSIONx10 >= 75) { /* Pre-SKL, the dword containing the clear values also contains @@ -552,19 +596,20 @@ static void genX(copy_fast_clear_dwords)(struct anv_cmd_buffer *cmd_buffer, struct anv_state surface_state, const struct anv_image *image, + VkImageAspectFlagBits aspect, 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, aspect)); 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; const struct anv_address entry_addr = - get_fast_clear_state_address(cmd_buffer->device, image, level, + get_fast_clear_state_address(cmd_buffer->device, image, aspect, level, FAST_CLEAR_STATE_FIELD_CLEAR_COLOR); unsigned copy_size = cmd_buffer->device->isl_dev.ss.clear_value_size; @@ -605,6 +650,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, + VkImageAspectFlagBits aspect, const uint32_t base_level, uint32_t level_count, uint32_t base_layer, uint32_t layer_count, VkImageLayout initial_layout, @@ -612,7 +658,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); @@ -632,22 +678,25 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer, if (initial_layout == final_layout) return; - if (image->shadow_surface.isl.size > 0 && + uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect); + + 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)); + assert(plane == 0); + anv_image_copy_to_shadow(cmd_buffer, image, 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, aspect, base_level)) return; /* A transition of a 3D subresource works on all slices at a time. */ @@ -657,9 +706,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, aspect) - base_level); layer_count = MIN2(layer_count, - anv_image_aux_layers(image, base_level) - base_layer); + anv_image_aux_layers(image, aspect, base_level) - base_layer); last_level_num = base_level + level_count; /* Record whether or not the layout is undefined. Pre-initialized images @@ -680,7 +729,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, aspect, 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 @@ -704,7 +753,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, aspect, + base_level, level_count, base_layer, layer_count); } /* At this point, some elements of the CCS buffer may have the fast-clear @@ -716,7 +766,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. @@ -768,13 +819,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, aspect, level)); } - genX(load_needs_resolve_predicate)(cmd_buffer, image, level); + genX(load_needs_resolve_predicate)(cmd_buffer, image, aspect, 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. @@ -784,7 +836,7 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer, anv_image_fill_surface_state(cmd_buffer->device, image, VK_IMAGE_ASPECT_COLOR_BIT, &(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, @@ -794,16 +846,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 */); + aspect, 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 ? + aspect, 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, aspect, level, false); } cmd_buffer->state.pending_pipe_bits |= @@ -889,7 +941,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; @@ -913,9 +965,11 @@ 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) { + assert(att_aspects == VK_IMAGE_ASPECT_COLOR_BIT); color_attachment_compute_aux_usage(cmd_buffer->device, state, i, begin->renderArea, &clear_color); @@ -923,7 +977,7 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer, anv_image_fill_surface_state(cmd_buffer->device, iview->image, VK_IMAGE_ASPECT_COLOR_BIT, - &iview->isl, + &iview->planes[0].isl, ISL_SURF_USAGE_RENDER_TARGET_BIT, state->attachments[i].aux_usage, &clear_color, @@ -931,8 +985,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. @@ -946,7 +1000,7 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer, anv_image_fill_surface_state(cmd_buffer->device, iview->image, VK_IMAGE_ASPECT_COLOR_BIT, - &iview->isl, + &iview->planes[0].isl, ISL_SURF_USAGE_TEXTURE_BIT, state->attachments[i].input_aux_usage, &clear_color, @@ -954,8 +1008,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); } } } @@ -1380,14 +1434,20 @@ 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_expand_aspects(image, range->aspectMask); + uint32_t aspect_bit; + + anv_foreach_image_aspect_bit(aspect_bit, image, color_aspects) { + transition_color_buffer(cmd_buffer, image, 1UL << aspect_bit, + range->baseMipLevel, + anv_get_levelCount(image, range), + range->baseArrayLayer, + anv_get_layerCount(image, range), + pImageMemoryBarriers[i].oldLayout, + pImageMemoryBarriers[i].newLayout); + } } } @@ -1578,26 +1638,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 @@ -1612,16 +1674,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; } @@ -2750,41 +2813,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); @@ -2874,7 +2947,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 @@ -2893,11 +2966,12 @@ cmd_buffer_subpass_transition_layouts(struct anv_cmd_buffer * const cmd_buffer, att_state->aux_usage = anv_layout_to_aux_usage(&cmd_buffer->device->info, image, VK_IMAGE_ASPECT_DEPTH_BIT, 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, + } else if (image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT) { + assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT); + transition_color_buffer(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, + 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); } @@ -2942,11 +3016,13 @@ 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, + VK_IMAGE_ASPECT_COLOR_BIT, + 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 @@ -2954,10 +3030,14 @@ cmd_buffer_subpass_sync_fast_clear_values(struct anv_cmd_buffer *cmd_buffer) * being used for sampling. */ genX(set_image_needs_resolve)(cmd_buffer, iview->image, - iview->isl.base_level, false); + VK_IMAGE_ASPECT_COLOR_BIT, + iview->planes[0].isl.base_level, + false); } else { genX(set_image_needs_resolve)(cmd_buffer, iview->image, - iview->isl.base_level, true); + VK_IMAGE_ASPECT_COLOR_BIT, + 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 @@ -2966,13 +3046,17 @@ 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, + VK_IMAGE_ASPECT_COLOR_BIT, + 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, + VK_IMAGE_ASPECT_COLOR_BIT, + iview->planes[0].isl.base_level, false /* copy to ss */); } }