diff options
-rw-r--r-- | src/intel/vulkan/anv_blorp.c | 46 | ||||
-rw-r--r-- | src/intel/vulkan/anv_image.c | 111 | ||||
-rw-r--r-- | src/intel/vulkan/anv_private.h | 14 | ||||
-rw-r--r-- | src/intel/vulkan/genX_cmd_buffer.c | 21 |
4 files changed, 187 insertions, 5 deletions
diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index 7f51bedb76f..8d0c2752485 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -1489,6 +1489,52 @@ 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); + + 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, + .addr = { + .buffer = image->bo, + .offset = image->offset + image->shadow_surface.offset, + }, + }; + + for (uint32_t l = 0; l < level_count; l++) { + const uint32_t level = base_level + l; + + const VkExtent3D extent = { + .width = anv_minify(image->extent.width, level), + .height = anv_minify(image->extent.height, level), + .depth = anv_minify(image->extent.depth, level), + }; + + if (image->type == VK_IMAGE_TYPE_3D) + layer_count = extent.depth; + + for (uint32_t a = 0; a < layer_count; a++) { + const uint32_t layer = base_layer + a; + + blorp_copy(&batch, &surf, level, layer, + &shadow_surf, level, layer, + 0, 0, 0, 0, extent.width, extent.height); + } + } + + blorp_batch_finish(&batch); +} + +void anv_gen8_hiz_op_resolve(struct anv_cmd_buffer *cmd_buffer, const struct anv_image *image, enum blorp_hiz_op op) diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index b69f76cac36..837b6a4e8dd 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -268,6 +268,18 @@ make_surface(const struct anv_device *dev, aspect, vk_info->tiling); assert(format != ISL_FORMAT_UNSUPPORTED); + /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need to + * fall back to linear because we aren't guaranteed that we can handle + * offsets correctly. + */ + bool needs_shadow = false; + if ((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)); + 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, @@ -289,6 +301,36 @@ make_surface(const struct anv_device *dev, add_surface(image, anv_surf); + /* 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 + * don't get garbage performance. + */ + if (needs_shadow) { + 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, + .dim = vk_to_isl_surf_dim[vk_info->imageType], + .format = format, + .width = image->extent.width, + .height = image->extent.height, + .depth = image->extent.depth, + .levels = vk_info->mipLevels, + .array_len = vk_info->arrayLayers, + .samples = vk_info->samples, + .min_alignment = 0, + .row_pitch = anv_info->stride, + .usage = choose_isl_surf_usage(image->usage, image->usage, aspect), + .tiling_flags = ISL_TILING_ANY_MASK); + + /* isl_surf_init() will fail only if provided invalid input. Invalid input + * is illegal in Vulkan. + */ + assert(ok); + + add_surface(image, &image->shadow_surface); + } + /* Add a HiZ surface to a depth buffer that will be used for rendering. */ if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) { @@ -730,6 +772,20 @@ anv_image_fill_surface_state(struct anv_device *device, struct isl_view view = *view_in; view.usage |= view_usage; + /* For texturing with VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL from a + * compressed surface with a shadow surface, we use the shadow instead of + * 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 && + 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; + } + if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT) view.swizzle = anv_swizzle_for_render(view.swizzle); @@ -775,16 +831,65 @@ anv_image_fill_surface_state(struct anv_device *device, view.format); } + const struct isl_surf *isl_surf = &surface->isl; + + struct isl_surf tmp_surf; + uint32_t offset_B = 0, tile_x_sa = 0, tile_y_sa = 0; + if (isl_format_is_compressed(surface->isl.format) && + !isl_format_is_compressed(view.format)) { + /* We're creating an uncompressed view of a compressed surface. This + * is allowed but only for a single level/layer. + */ + assert(surface->isl.samples == 1); + assert(view.levels == 1); + assert(view.array_len == 1); + + isl_surf_get_image_surf(&device->isl_dev, isl_surf, + view.base_level, + surface->isl.dim == ISL_SURF_DIM_3D ? + 0 : view.base_array_layer, + surface->isl.dim == ISL_SURF_DIM_3D ? + view.base_array_layer : 0, + &tmp_surf, + &offset_B, &tile_x_sa, &tile_y_sa); + + /* The newly created image represents the one subimage we're + * referencing with this view so it only has one array slice and + * miplevel. + */ + view.base_array_layer = 0; + view.base_level = 0; + + /* We're making an uncompressed view here. The image dimensions need + * to be scaled down by the block size. + */ + const struct isl_format_layout *fmtl = + isl_format_get_layout(surface->isl.format); + tmp_surf.format = view.format; + tmp_surf.logical_level0_px.width = + DIV_ROUND_UP(tmp_surf.logical_level0_px.width, fmtl->bw); + tmp_surf.logical_level0_px.height = + DIV_ROUND_UP(tmp_surf.logical_level0_px.height, fmtl->bh); + tmp_surf.phys_level0_sa.width /= fmtl->bw; + tmp_surf.phys_level0_sa.height /= fmtl->bh; + + isl_surf = &tmp_surf; + + assert(surface->isl.tiling == ISL_TILING_LINEAR); + assert(tile_x_sa == 0); + assert(tile_y_sa == 0); + } + isl_surf_fill_state(&device->isl_dev, state_inout->state.map, - .surf = &surface->isl, + .surf = isl_surf, .view = &view, - .address = address, + .address = address + offset_B, .clear_color = *clear_color, .aux_surf = &image->aux_surface.isl, .aux_usage = aux_usage, .aux_address = aux_address, .mocs = device->default_mocs); - state_inout->address = address; + state_inout->address = address + offset_B; if (device->info.gen >= 8) { state_inout->aux_address = aux_address; } else { diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 85843b204b2..355adbac91d 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2266,6 +2266,13 @@ struct anv_image { }; /** + * 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. * @@ -2352,6 +2359,13 @@ anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer, 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); + enum isl_aux_usage anv_layout_to_aux_usage(const struct gen_device_info * const devinfo, const struct anv_image *image, diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 7fb607f2189..fbc19957096 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -627,8 +627,25 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer, /* No work is necessary if the layout stays the same or if this subresource * range lacks auxiliary data. */ - if (initial_layout == final_layout || - base_layer >= anv_image_aux_layers(image, base_level)) + if (initial_layout == final_layout) + return; + + if (image->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, + base_level, level_count, + base_layer, layer_count); + } + + if (base_layer >= anv_image_aux_layers(image, base_level)) return; /* A transition of a 3D subresource works on all slices at a time. */ |