mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 20:28:04 +02:00
intel/isl: Implement correct tile size calculations for Ys/Yf
The tile size calculations use a clever bit of math to make them short and simple. We add unit tests to assert that they identically match the tables in the PRM. Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com> Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Nanley Chery <nanley.g.chery@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23620>
This commit is contained in:
parent
e230ef329b
commit
911832e9cf
5 changed files with 273 additions and 83 deletions
|
|
@ -507,13 +507,67 @@ isl_tiling_get_info(enum isl_tiling tiling,
|
|||
case ISL_TILING_ICL_Ys: {
|
||||
bool is_Ys = tiling == ISL_TILING_SKL_Ys ||
|
||||
tiling == ISL_TILING_ICL_Ys;
|
||||
assert(format_bpb >= 8);
|
||||
|
||||
assert(bs > 0);
|
||||
unsigned width = 1 << (6 + (ffs(bs) / 2) + (2 * is_Ys));
|
||||
unsigned height = 1 << (6 - (ffs(bs) / 2) + (2 * is_Ys));
|
||||
switch (dim) {
|
||||
case ISL_SURF_DIM_2D:
|
||||
/* See the BSpec Memory Data Formats » Common Surface Formats »
|
||||
* Surface Layout and Tiling [SKL+] » 2D Surfaces SKL+ » 2D/CUBE
|
||||
* Alignment Requirement [SKL+]
|
||||
*
|
||||
* Or, look in the SKL PRM under Memory Views > Common Surface
|
||||
* Formats > Surface Layout and Tiling > 2D Surfaces > 2D/CUBE
|
||||
* Alignment Requirements.
|
||||
*/
|
||||
logical_el = (struct isl_extent4d) {
|
||||
.w = 1 << (6 - ((ffs(format_bpb) - 4) / 2) + (2 * is_Ys)),
|
||||
.h = 1 << (6 - ((ffs(format_bpb) - 3) / 2) + (2 * is_Ys)),
|
||||
.d = 1,
|
||||
.a = 1,
|
||||
};
|
||||
|
||||
logical_el = isl_extent4d(width / bs, height, 1, 1);
|
||||
phys_B = isl_extent2d(width, height);
|
||||
if (samples > 1 && tiling != ISL_TILING_SKL_Yf) {
|
||||
/* SKL PRMs, Volume 5: Memory Views, 2D/CUBE Alignment
|
||||
* Requirement:
|
||||
*
|
||||
* "For MSFMT_MSS type multi-sampled TileYS surfaces, the
|
||||
* alignments given above must be divided by the appropriate
|
||||
* value from the table below."
|
||||
*
|
||||
* The formulas below reproduce those values.
|
||||
*/
|
||||
if (msaa_layout == ISL_MSAA_LAYOUT_ARRAY) {
|
||||
logical_el.w >>= (ffs(samples) - 0) / 2;
|
||||
logical_el.h >>= (ffs(samples) - 1) / 2;
|
||||
logical_el.a = samples;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ISL_SURF_DIM_3D:
|
||||
/* See the BSpec Memory Data Formats » Common Surface Formats »
|
||||
* Surface Layout and Tiling [SKL+] » 3D Surfaces SKL+ » 3D Alignment
|
||||
* Requirements [SKL+]
|
||||
*
|
||||
* Or, look in the SKL PRM under Memory Views > Common Surface
|
||||
* Formats > Surface Layout and Tiling > 3D Surfaces > 3D Alignment
|
||||
* Requirements.
|
||||
*/
|
||||
logical_el = (struct isl_extent4d) {
|
||||
.w = 1 << (4 - ((ffs(format_bpb) - 2) / 3) + (2 * is_Ys)),
|
||||
.h = 1 << (4 - ((ffs(format_bpb) - 4) / 3) + (1 * is_Ys)),
|
||||
.d = 1 << (4 - ((ffs(format_bpb) - 3) / 3) + (1 * is_Ys)),
|
||||
.a = 1,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
unreachable("Invalid dimension");
|
||||
}
|
||||
|
||||
uint32_t tile_size_B = is_Ys ? (1 << 16) : (1 << 12);
|
||||
|
||||
phys_B.w = logical_el.width * bs;
|
||||
phys_B.h = tile_size_B / phys_B.w;
|
||||
break;
|
||||
}
|
||||
case ISL_TILING_64:
|
||||
|
|
|
|||
|
|
@ -220,7 +220,29 @@ isl_gfx12_choose_image_alignment_el(const struct isl_device *dev,
|
|||
return;
|
||||
}
|
||||
|
||||
if (isl_surf_usage_is_depth(info->usage)) {
|
||||
if (isl_tiling_is_std_y(tiling)) {
|
||||
/* From RENDER_SURFACE_STATE::SurfaceHorizontalAlignment,
|
||||
*
|
||||
* This field is ignored for Tile64 surface formats because horizontal
|
||||
* alignment is always to the start of the next tile in that case.
|
||||
*
|
||||
* From RENDER_SURFACE_STATE::SurfaceQPitch,
|
||||
*
|
||||
* Because MSAA is only supported for Tile64, QPitch must also be
|
||||
* programmed to an aligned tile boundary for MSAA surfaces.
|
||||
*
|
||||
* Images in this surface must be tile-aligned. The table on the Bspec
|
||||
* page, "2D/CUBE Alignment Requirement", shows that the vertical
|
||||
* alignment is also a tile height for non-MSAA as well.
|
||||
*/
|
||||
struct isl_tile_info tile_info;
|
||||
isl_tiling_get_info(tiling, info->dim, msaa_layout, fmtl->bpb,
|
||||
info->samples, &tile_info);
|
||||
|
||||
*image_align_el = isl_extent3d(tile_info.logical_extent_el.w,
|
||||
tile_info.logical_extent_el.h,
|
||||
1);
|
||||
} else if (isl_surf_usage_is_depth(info->usage)) {
|
||||
/* The alignment parameters for depth buffers are summarized in the
|
||||
* following table:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,78 +25,6 @@
|
|||
#include "isl_gfx9.h"
|
||||
#include "isl_priv.h"
|
||||
|
||||
/**
|
||||
* Calculate the surface's subimage alignment, in units of surface samples,
|
||||
* for the standard tiling formats Yf and Ys.
|
||||
*/
|
||||
static void
|
||||
gfx9_calc_std_image_alignment_sa(const struct isl_device *dev,
|
||||
const struct isl_surf_init_info *restrict info,
|
||||
enum isl_tiling tiling,
|
||||
enum isl_msaa_layout msaa_layout,
|
||||
struct isl_extent3d *align_sa)
|
||||
{
|
||||
const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
|
||||
|
||||
assert(isl_tiling_is_std_y(tiling));
|
||||
|
||||
const uint32_t bpb = fmtl->bpb;
|
||||
const uint32_t is_Ys = tiling == ISL_TILING_SKL_Ys ||
|
||||
tiling == ISL_TILING_ICL_Ys;
|
||||
|
||||
switch (info->dim) {
|
||||
case ISL_SURF_DIM_1D:
|
||||
/* See the Skylake BSpec > Memory Views > Common Surface Formats > Surface
|
||||
* Layout and Tiling > 1D Surfaces > 1D Alignment Requirements.
|
||||
*/
|
||||
*align_sa = (struct isl_extent3d) {
|
||||
.w = 1 << (12 - (ffs(bpb) - 4) + (4 * is_Ys)),
|
||||
.h = 1,
|
||||
.d = 1,
|
||||
};
|
||||
return;
|
||||
case ISL_SURF_DIM_2D:
|
||||
/* See the Skylake BSpec > Memory Views > Common Surface Formats >
|
||||
* Surface Layout and Tiling > 2D Surfaces > 2D/CUBE Alignment
|
||||
* Requirements.
|
||||
*/
|
||||
*align_sa = (struct isl_extent3d) {
|
||||
.w = 1 << (6 - ((ffs(bpb) - 4) / 2) + (4 * is_Ys)),
|
||||
.h = 1 << (6 - ((ffs(bpb) - 3) / 2) + (4 * is_Ys)),
|
||||
.d = 1,
|
||||
};
|
||||
|
||||
if (is_Ys) {
|
||||
/* FINISHME(chadv): I don't trust this code. Untested. */
|
||||
isl_finishme("%s:%s: [SKL+] multisample TileYs", __FILE__, __func__);
|
||||
|
||||
switch (msaa_layout) {
|
||||
case ISL_MSAA_LAYOUT_NONE:
|
||||
case ISL_MSAA_LAYOUT_INTERLEAVED:
|
||||
break;
|
||||
case ISL_MSAA_LAYOUT_ARRAY:
|
||||
align_sa->w >>= (ffs(info->samples) - 0) / 2;
|
||||
align_sa->h >>= (ffs(info->samples) - 1) / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case ISL_SURF_DIM_3D:
|
||||
/* See the Skylake BSpec > Memory Views > Common Surface Formats > Surface
|
||||
* Layout and Tiling > 1D Surfaces > 1D Alignment Requirements.
|
||||
*/
|
||||
*align_sa = (struct isl_extent3d) {
|
||||
.w = 1 << (4 - ((ffs(bpb) - 2) / 3) + (4 * is_Ys)),
|
||||
.h = 1 << (4 - ((ffs(bpb) - 4) / 3) + (2 * is_Ys)),
|
||||
.d = 1 << (4 - ((ffs(bpb) - 3) / 3) + (2 * is_Ys)),
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
unreachable("bad isl_surface_type");
|
||||
}
|
||||
|
||||
void
|
||||
isl_gfx9_choose_image_alignment_el(const struct isl_device *dev,
|
||||
const struct isl_surf_init_info *restrict info,
|
||||
|
|
@ -167,11 +95,15 @@ isl_gfx9_choose_image_alignment_el(const struct isl_device *dev,
|
|||
*/
|
||||
|
||||
if (isl_tiling_is_std_y(tiling)) {
|
||||
struct isl_extent3d image_align_sa;
|
||||
gfx9_calc_std_image_alignment_sa(dev, info, tiling, msaa_layout,
|
||||
&image_align_sa);
|
||||
|
||||
*image_align_el = isl_extent3d_sa_to_el(info->format, image_align_sa);
|
||||
/* Ys and Yf tiled images are aligned to the tile size */
|
||||
struct isl_tile_info tile_info;
|
||||
isl_tiling_get_info(tiling, info->dim, msaa_layout,
|
||||
fmtl->bpb, info->samples, &tile_info);
|
||||
*image_align_el = (struct isl_extent3d) {
|
||||
.w = tile_info.logical_extent_el.w,
|
||||
.h = tile_info.logical_extent_el.h,
|
||||
.d = tile_info.logical_extent_el.d,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,4 +186,16 @@ if with_tests
|
|||
suite : ['intel'],
|
||||
protocol : 'gtest',
|
||||
)
|
||||
|
||||
test(
|
||||
'isl_tile_std_y',
|
||||
executable(
|
||||
'isl_tile_std_y_test',
|
||||
'tests/isl_tile_std_y_test.c',
|
||||
dependencies : dep_m,
|
||||
include_directories : [inc_include, inc_src, inc_gallium, inc_intel],
|
||||
link_with : [libisl, libintel_dev],
|
||||
),
|
||||
suite : ['intel'],
|
||||
)
|
||||
endif
|
||||
|
|
|
|||
170
src/intel/isl/tests/isl_tile_std_y_test.c
Normal file
170
src/intel/isl/tests/isl_tile_std_y_test.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright 2018 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "isl/isl.h"
|
||||
|
||||
// An asssert that works regardless of NDEBUG.
|
||||
#define t_assert(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
fprintf(stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
assert_tile_size(enum isl_tiling tiling, enum isl_surf_dim dim,
|
||||
enum isl_msaa_layout msaa_layout,
|
||||
uint32_t bpb, uint32_t samples,
|
||||
uint32_t w, uint32_t h, uint32_t d, uint32_t a)
|
||||
{
|
||||
struct isl_tile_info tile_info;
|
||||
isl_tiling_get_info(tiling, dim, msaa_layout, bpb, samples, &tile_info);
|
||||
|
||||
/* Sanity */
|
||||
t_assert(tile_info.tiling == tiling);
|
||||
t_assert(tile_info.format_bpb == bpb);
|
||||
|
||||
t_assert(tile_info.logical_extent_el.w == w);
|
||||
t_assert(tile_info.logical_extent_el.h == h);
|
||||
t_assert(tile_info.logical_extent_el.d == d);
|
||||
t_assert(tile_info.logical_extent_el.a == a);
|
||||
|
||||
bool is_Ys = tiling == ISL_TILING_SKL_Ys ||
|
||||
tiling == ISL_TILING_ICL_Ys;
|
||||
uint32_t tile_size = is_Ys ? 64 * 1024 : 4 * 1024;
|
||||
|
||||
assert(tile_size == tile_info.phys_extent_B.w *
|
||||
tile_info.phys_extent_B.h);
|
||||
|
||||
assert(tile_size == tile_info.logical_extent_el.w *
|
||||
tile_info.logical_extent_el.h *
|
||||
tile_info.logical_extent_el.d *
|
||||
tile_info.logical_extent_el.a *
|
||||
bpb / 8);
|
||||
}
|
||||
|
||||
static void
|
||||
assert_2d_tile_size(enum isl_tiling tiling, uint32_t bpb,
|
||||
uint32_t halign, uint32_t valign)
|
||||
{
|
||||
#define ASSERT_2D(tiling, bpb, samples, w, h, a) \
|
||||
assert_tile_size(tiling, ISL_SURF_DIM_2D, ISL_MSAA_LAYOUT_ARRAY, \
|
||||
bpb, samples, w, h, 1, a)
|
||||
|
||||
/* Single sampled */
|
||||
ASSERT_2D(tiling, bpb, 1, halign, valign, 1);
|
||||
|
||||
/* Multisampled */
|
||||
if (tiling == ISL_TILING_SKL_Yf) {
|
||||
ASSERT_2D(tiling, bpb, 2, halign, valign, 1);
|
||||
ASSERT_2D(tiling, bpb, 4, halign, valign, 1);
|
||||
ASSERT_2D(tiling, bpb, 8, halign, valign, 1);
|
||||
ASSERT_2D(tiling, bpb, 16, halign, valign, 1);
|
||||
} else {
|
||||
/* For gfx9 Ys and for both Yf and Ys on gfx11, we have to divide the
|
||||
* size by the number of samples.
|
||||
*/
|
||||
ASSERT_2D(tiling, bpb, 2, halign / 2, valign / 1, 2);
|
||||
ASSERT_2D(tiling, bpb, 4, halign / 2, valign / 2, 4);
|
||||
ASSERT_2D(tiling, bpb, 8, halign / 4, valign / 2, 8);
|
||||
ASSERT_2D(tiling, bpb, 16, halign / 4, valign / 4, 16);
|
||||
}
|
||||
|
||||
#undef ASSERT_2D
|
||||
}
|
||||
|
||||
static void
|
||||
test_2d_tile_dimensions()
|
||||
{
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Ys, 128, 64, 64);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Ys, 64, 128, 64);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Ys, 32, 128, 128);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Ys, 16, 256, 128);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Ys, 8, 256, 256);
|
||||
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Yf, 128, 16, 16);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Yf, 64, 32, 16);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Yf, 32, 32, 32);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Yf, 16, 64, 32);
|
||||
assert_2d_tile_size(ISL_TILING_SKL_Yf, 8, 64, 64);
|
||||
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Ys, 128, 64, 64);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Ys, 64, 128, 64);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Ys, 32, 128, 128);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Ys, 16, 256, 128);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Ys, 8, 256, 256);
|
||||
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Yf, 128, 16, 16);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Yf, 64, 32, 16);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Yf, 32, 32, 32);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Yf, 16, 64, 32);
|
||||
assert_2d_tile_size(ISL_TILING_ICL_Yf, 8, 64, 64);
|
||||
}
|
||||
|
||||
static void
|
||||
test_3d_tile_dimensions()
|
||||
{
|
||||
#define ASSERT_3D(tiling, bpb, halign, valign, dalign) \
|
||||
assert_tile_size(tiling, ISL_SURF_DIM_3D, ISL_MSAA_LAYOUT_ARRAY, \
|
||||
bpb, 1, halign, valign, dalign, 1)
|
||||
|
||||
ASSERT_3D(ISL_TILING_SKL_Ys, 128, 16, 16, 16);
|
||||
ASSERT_3D(ISL_TILING_SKL_Ys, 64, 32, 16, 16);
|
||||
ASSERT_3D(ISL_TILING_SKL_Ys, 32, 32, 32, 16);
|
||||
ASSERT_3D(ISL_TILING_SKL_Ys, 16, 32, 32, 32);
|
||||
ASSERT_3D(ISL_TILING_SKL_Ys, 8, 64, 32, 32);
|
||||
|
||||
ASSERT_3D(ISL_TILING_SKL_Yf, 128, 4, 8, 8);
|
||||
ASSERT_3D(ISL_TILING_SKL_Yf, 64, 8, 8, 8);
|
||||
ASSERT_3D(ISL_TILING_SKL_Yf, 32, 8, 16, 8);
|
||||
ASSERT_3D(ISL_TILING_SKL_Yf, 16, 8, 16, 16);
|
||||
ASSERT_3D(ISL_TILING_SKL_Yf, 8, 16, 16, 16);
|
||||
|
||||
ASSERT_3D(ISL_TILING_ICL_Ys, 128, 16, 16, 16);
|
||||
ASSERT_3D(ISL_TILING_ICL_Ys, 64, 32, 16, 16);
|
||||
ASSERT_3D(ISL_TILING_ICL_Ys, 32, 32, 32, 16);
|
||||
ASSERT_3D(ISL_TILING_ICL_Ys, 16, 32, 32, 32);
|
||||
ASSERT_3D(ISL_TILING_ICL_Ys, 8, 64, 32, 32);
|
||||
|
||||
ASSERT_3D(ISL_TILING_ICL_Yf, 128, 4, 8, 8);
|
||||
ASSERT_3D(ISL_TILING_ICL_Yf, 64, 8, 8, 8);
|
||||
ASSERT_3D(ISL_TILING_ICL_Yf, 32, 8, 16, 8);
|
||||
ASSERT_3D(ISL_TILING_ICL_Yf, 16, 8, 16, 16);
|
||||
ASSERT_3D(ISL_TILING_ICL_Yf, 8, 16, 16, 16);
|
||||
|
||||
#undef ASSERT_3D
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_2d_tile_dimensions();
|
||||
test_3d_tile_dimensions();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue