From b36938964063a4072abfd779f5607743dbc3b6f1 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 2 Dec 2015 16:46:16 -0800 Subject: [PATCH] anv/image: Use isl to calculate surface layout Remove the surface layout calculations in anv_image_make_surface(). Let isl_surf_init() do the heavy lifting. Fixes 8 Crucible tests and regresses none. (hw=Broadwell and crucible@33d91ec). --- src/vulkan/anv_image.c | 239 +++++++++++++++-------------------------- 1 file changed, 85 insertions(+), 154 deletions(-) diff --git a/src/vulkan/anv_image.c b/src/vulkan/anv_image.c index 7abd0db1460..2bfe19f3609 100644 --- a/src/vulkan/anv_image.c +++ b/src/vulkan/anv_image.c @@ -84,188 +84,119 @@ static const struct anv_surf_type_limits { [SURFTYPE_STRBUF] = {128, 16384, 64}, }; -static const struct anv_tile_info { - /** - * Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress. - * - * To simplify calculations, the alignments defined in the table are - * sometimes larger than required. For example, Skylake requires that X and - * Y tiled buffers be aligned to 4K, but Broadwell permits smaller - * alignment. We choose 4K to accomodate both chipsets. The alignment of - * a linear buffer depends on its element type and usage. Linear depth - * buffers have the largest alignment, 64B, so we choose that for all linear - * buffers. - */ - uint32_t surface_alignment; -} anv_tile_info_table[] = { - [ISL_TILING_LINEAR] = { 64 }, - [ISL_TILING_X] = { 4096 }, - [ISL_TILING_Y0] = { 4096 }, - [ISL_TILING_Yf] = { 4096 }, - [ISL_TILING_Ys] = { 4096 }, - [ISL_TILING_W] = { 4096 }, -}; - -static enum isl_tiling -anv_image_choose_tiling(const struct anv_image_create_info *anv_info) +static isl_tiling_flags_t +choose_isl_tiling_flags(const struct anv_image_create_info *anv_info) { - if (anv_info->force_tiling) - return anv_info->tiling; - - /* The Sandybridge PRM says that the stencil buffer "is supported - * only in Tile W memory". - */ - - switch (anv_info->vk_info->tiling) { - case VK_IMAGE_TILING_LINEAR: - assert(anv_info->vk_info->format != VK_FORMAT_S8_UINT); - return ISL_TILING_LINEAR; - case VK_IMAGE_TILING_OPTIMAL: - if (unlikely(anv_info->vk_info->format == VK_FORMAT_S8_UINT)) { - return ISL_TILING_W; - } else { - return ISL_TILING_Y0; - } - default: - assert(!"bad VKImageTiling"); - return ISL_TILING_LINEAR; + const VkImageCreateInfo *vk_info = anv_info->vk_info; + + if (anv_info->force_tiling) { + return 1u << anv_info->tiling; + } else if (vk_info->tiling == VK_IMAGE_TILING_LINEAR) { + return ISL_TILING_LINEAR_BIT; + } else if (vk_info->tiling == VK_IMAGE_TILING_OPTIMAL) { + return ISL_TILING_ANY_MASK; + } else { + unreachable("bad anv_image_create_info"); + return 0; } } - /** - * The \a format argument is required and overrides any format in - * struct anv_image_create_info. + * The \a format argument is required and overrides any format found in struct + * anv_image_create_info. */ -static VkResult -anv_image_make_surface(const struct anv_device *dev, - const struct anv_image_create_info *create_info, - const struct anv_format *format, - uint64_t *inout_image_size, - uint32_t *inout_image_alignment, - struct anv_surface *out_surface) +static isl_surf_usage_flags_t +choose_isl_surf_usage(const struct anv_image_create_info *info, + const struct anv_format *format) { - /* See RENDER_SURFACE_STATE.SurfaceQPitch */ - static const uint16_t min_qpitch UNUSED = 0x4; - static const uint16_t max_qpitch UNUSED = 0x1ffc; - - const VkExtent3D *restrict extent = &create_info->vk_info->extent; - const uint32_t levels = create_info->vk_info->mipLevels; - const uint32_t array_size = create_info->vk_info->arrayLayers; - const enum isl_tiling tiling = anv_image_choose_tiling(create_info); + const VkImageCreateInfo *vk_info = info->vk_info; + isl_surf_usage_flags_t isl_flags = 0; - const struct anv_tile_info *tile_info = - &anv_tile_info_table[tiling]; + /* FINISHME: Support aux surfaces */ + isl_flags |= ISL_SURF_USAGE_DISABLE_AUX_BIT; - const uint32_t bs = format->isl_layout->bs; - const uint32_t bw = format->isl_layout->bw; - const uint32_t bh = format->isl_layout->bh; + if (vk_info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) + isl_flags |= ISL_SURF_USAGE_TEXTURE_BIT; - struct isl_extent2d tile_extent; - isl_tiling_get_extent(&dev->isl_dev, tiling, bs, &tile_extent); + if (vk_info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) + isl_flags |= ISL_SURF_USAGE_TEXTURE_BIT; - const uint32_t i = MAX(4, bw); /* FINISHME: Stop hardcoding subimage alignment */ - const uint32_t j = MAX(4, bh); /* FINISHME: Stop hardcoding subimage alignment */ - assert(i == 4 || i == 8 || i == 16); - assert(j == 4 || j == 8 || j == 16); + if (vk_info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + isl_flags |= ISL_SURF_USAGE_RENDER_TARGET_BIT; - uint16_t qpitch = min_qpitch; - uint32_t mt_width = 0; - uint32_t mt_height = 0; + if (vk_info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) + isl_flags |= ISL_SURF_USAGE_CUBE_BIT; - switch (create_info->vk_info->imageType) { - case VK_IMAGE_TYPE_1D: - /* From the Broadwell PRM >> Memory Views >> Common Surface Formats >> - * Surface Layout >> 1D Surfaces: - * - * One-dimensional surfaces are identical to 2D surfaces with height of one. - * - * So fallthrough... - */ - case VK_IMAGE_TYPE_2D: { - const uint32_t w0 = align_u32(extent->width, i); - const uint32_t h0 = align_u32(extent->height, j); - - if (levels == 1 && array_size == 1) { - qpitch = min_qpitch; - mt_width = w0; - mt_height = h0; - } else { - uint32_t w1 = align_u32(anv_minify(extent->width, 1), i); - uint32_t h1 = align_u32(anv_minify(extent->height, 1), j); - uint32_t w2 = align_u32(anv_minify(extent->width, 2), i); + if (vk_info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + assert((format->depth_format != 0) ^ format->has_stencil); - /* The QPitch equation is found in the Broadwell PRM >> Volume 5: Memory - * Views >> Common Surface Formats >> Surface Layout >> 2D Surfaces >> - * Surface Arrays >> For All Surface Other Than Separate Stencil Buffer: - */ - assert(bh ==1 || bh == 4); - qpitch = (h0 + h1 + 11 * j) / bh; - mt_width = MAX(w0, w1 + w2); - mt_height = array_size * qpitch; + if (format->depth_format) { + isl_flags |= ISL_SURF_USAGE_DEPTH_BIT; + } else if (format->has_stencil) { + isl_flags |= ISL_SURF_USAGE_STENCIL_BIT; } - break; } - case VK_IMAGE_TYPE_3D: - /* The layout of 3D surfaces is described by the Broadwell PRM >> - * Volume 5: Memory Views >> Common Surface Formats >> Surface Layout >> - * 3D Surfaces. - */ - for (uint32_t l = 0; l < levels; ++l) { - const uint32_t w_l = align_u32(anv_minify(extent->width, l), i); - const uint32_t h_l = align_u32(anv_minify(extent->height, l), j); - const uint32_t d_l = anv_minify(extent->depth, l); - - const uint32_t max_layers_horiz = MIN(d_l, 1u << l); - const uint32_t max_layers_vert = align_u32(d_l, 1u << l) / (1u << l); - mt_width = MAX(mt_width, w_l * max_layers_horiz); - mt_height += h_l * max_layers_vert; - } - break; - default: - unreachable(!"bad VkImageType"); + if (vk_info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { + /* Meta implements transfers by sampling from the source image. */ + isl_flags |= ISL_SURF_USAGE_TEXTURE_BIT; } - assert(qpitch >= min_qpitch); - if (qpitch > max_qpitch) { - anv_loge("image qpitch > 0x%x\n", max_qpitch); - return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY); + if (vk_info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { + /* Meta implements transfers by rendering into the destination image. */ + isl_flags |= ISL_SURF_USAGE_RENDER_TARGET_BIT; } - /* From the Broadwell PRM, RENDER_SURFACE_STATE.SurfaceQpitch: - * - * This field must be set an integer multiple of the Surface Vertical - * Alignment. - */ - assert(anv_is_aligned(qpitch, j)); + return isl_flags; +} - uint32_t stride = align_u32(mt_width * bs / bw, tile_extent.width); - if (create_info->stride > 0) - stride = create_info->stride; +/** + * The \a format argument is required and overrides any format in + * struct anv_image_create_info. + */ +static VkResult +anv_image_make_surface(const struct anv_device *dev, + const struct anv_image_create_info *anv_info, + const struct anv_format *format, + uint64_t *inout_image_size, + uint32_t *inout_image_alignment, + struct anv_surface *out_surface) +{ + const VkImageCreateInfo *vk_info = anv_info->vk_info; - /* The padding requirement is found in the Broadwell PRM >> Volume 5: Memory - * Views >> Common Surface Formats >> Surface Padding Requirements >> - * Sampling Engine Surfaces >> Buffer Padding Requirements: - */ - const uint32_t mem_rows = align_u32(mt_height / bh, 2 * bh); - const uint32_t size = stride * align_u32(mem_rows, tile_extent.height); - const uint32_t offset = align_u32(*inout_image_size, - tile_info->surface_alignment); + static const enum isl_surf_dim vk_to_isl_surf_dim[] = { + [VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D, + [VK_IMAGE_TYPE_2D] = ISL_SURF_DIM_2D, + [VK_IMAGE_TYPE_3D] = ISL_SURF_DIM_3D, + }; - *inout_image_size = offset + size; - *inout_image_alignment = MAX(*inout_image_alignment, - tile_info->surface_alignment); + struct isl_surf isl_surf; + isl_surf_init(&dev->isl_dev, &isl_surf, + .dim = vk_to_isl_surf_dim[vk_info->imageType], + .format = format->surface_format, + .width = vk_info->extent.width, + .height = vk_info->extent.height, + .depth = vk_info->extent.depth, + .levels = vk_info->mipLevels, + .array_len = vk_info->arrayLayers, + .samples = vk_info->samples, + .min_alignment = 0, + .min_pitch = 0, + .usage = choose_isl_surf_usage(anv_info, format), + .tiling_flags = choose_isl_tiling_flags(anv_info)); *out_surface = (struct anv_surface) { - .offset = offset, - .stride = stride, - .tiling = tiling, - .qpitch = qpitch, - .h_align = i, - .v_align = j, + .offset = align_u32(*inout_image_size, isl_surf.alignment), + .stride = isl_surf.row_pitch, + .tiling = isl_surf.tiling, + .qpitch = isl_surf_get_array_pitch_sa_rows(&isl_surf), + .h_align = isl_surf_get_lod_alignment_sa(&isl_surf).width, + .v_align = isl_surf_get_lod_alignment_sa(&isl_surf).height, }; + *inout_image_size = out_surface->offset + isl_surf.size; + *inout_image_alignment = MAX(*inout_image_alignment, isl_surf.alignment); + return VK_SUCCESS; } -- 2.30.2