From 126c9562d98bf84b19140e318758ac0d4b0a9b5f Mon Sep 17 00:00:00 2001 From: Nanley Chery Date: Tue, 19 Mar 2019 18:23:46 -0700 Subject: [PATCH] isl: Redefine the CCS layout for Gen12 The CCS could be described in a number of ways, but this format was chosen to minimize churn in the drivers. We may decide on an different direction in the future. v2. Increase alignment for display surfaces. (Nanley) Reviewed-by: Jordan Justen (v1) Acked-by: Kenneth Graunke --- src/intel/isl/isl.c | 130 ++++++++++++++++++++++++---- src/intel/isl/isl.h | 7 ++ src/intel/isl/isl_drm.c | 1 + src/intel/isl/isl_format_layout.csv | 5 ++ src/intel/isl/isl_gen12.c | 8 ++ 5 files changed, 136 insertions(+), 15 deletions(-) diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c index a91c7204f66..5fd6aded2ae 100644 --- a/src/intel/isl/isl.c +++ b/src/intel/isl/isl.c @@ -311,6 +311,29 @@ isl_tiling_get_info(enum isl_tiling tiling, phys_B = isl_extent2d(128, 32); break; + case ISL_TILING_GEN12_CCS: + /* From the Bspec, Gen Graphics > Gen12 > Memory Data Formats > Memory + * Compression > Memory Compression - Gen12: + * + * 4 bits of auxiliary plane data are required for 2 cachelines of + * main surface data. This results in a single cacheline of auxiliary + * plane data mapping to 4 4K pages of main surface data for the 4K + * pages (tile Y ) and 1 64K Tile Ys page. + * + * The Y-tiled pairing bit of 9 shown in the table below that Bspec + * section expresses that the 2 cachelines of main surface data are + * horizontally adjacent. + * + * TODO: Handle Ys, Yf and their pairing bits. + * + * Therefore, each CCS cacheline represents a 512Bx32 row area and each + * element represents a 32Bx4 row area. + */ + assert(format_bpb == 4); + logical_el = isl_extent2d(16, 8); + phys_B = isl_extent2d(64, 1); + break; + default: unreachable("not reached"); } /* end switch */ @@ -391,7 +414,11 @@ isl_surf_choose_tiling(const struct isl_device *dev, /* CCS surfaces always use the CCS tiling */ if (info->usage & ISL_SURF_USAGE_CCS_BIT) { assert(isl_format_get_layout(info->format)->txc == ISL_TXC_CCS); - assert(tiling_flags == ISL_TILING_CCS_BIT); + UNUSED bool ivb_ccs = ISL_DEV_GEN(dev) < 12 && + tiling_flags == ISL_TILING_CCS_BIT; + UNUSED bool tgl_ccs = ISL_DEV_GEN(dev) >= 12 && + tiling_flags == ISL_TILING_GEN12_CCS_BIT; + assert(ivb_ccs != tgl_ccs); *tiling = isl_tiling_flag_to_enum(tiling_flags); return true; } @@ -919,7 +946,8 @@ isl_calc_array_pitch_el_rows_gen4_2d( assert(pitch_sa_rows % fmtl->bh == 0); uint32_t pitch_el_rows = pitch_sa_rows / fmtl->bh; - if (ISL_DEV_GEN(dev) >= 9 && fmtl->txc == ISL_TXC_CCS) { + if (ISL_DEV_GEN(dev) >= 9 && ISL_DEV_GEN(dev) <= 11 && + fmtl->txc == ISL_TXC_CCS) { /* * From the Sky Lake PRM Vol 7, "MCS Buffer for Render Target(s)" (p. 632): * @@ -937,6 +965,8 @@ isl_calc_array_pitch_el_rows_gen4_2d( * The first restriction is already handled by isl_choose_image_alignment_el * but the second restriction, which is an extension of the first, only * applies to qpitch and must be applied here. + * + * The second restriction disappears on Gen12. */ assert(fmtl->bh == 4); pitch_el_rows = isl_align(pitch_el_rows, 256 / 4); @@ -1544,6 +1574,15 @@ isl_surf_init_s(const struct isl_device *dev, tile_info.phys_extent_B.height; assert(isl_is_pow2(info->min_alignment_B) && isl_is_pow2(tile_size_B)); base_alignment_B = MAX(info->min_alignment_B, tile_size_B); + + /* The diagram in the Bspec section Memory Compression - Gen12, shows + * that the CCS is indexed in 256B chunks. However, the + * PLANE_AUX_DIST::Auxiliary Surface Distance field is in units of 4K + * pages. We currently don't assign the usage field like we do for main + * surfaces, so just use 4K for now. + */ + if (tiling == ISL_TILING_GEN12_CCS) + base_alignment_B = MAX(base_alignment_B, 4096); } if (ISL_DEV_GEN(dev) >= 12) { @@ -1817,9 +1856,35 @@ isl_surf_get_ccs_surf(const struct isl_device *dev, (surf->levels > 1 || surf->logical_level0_px.array_len > 1)) return false; + /* On Gen12, 8BPP surfaces cannot be compressed if any level is not + * 32Bx4row-aligned. For now, just reject the cases where alignment + * matters. + */ + if (ISL_DEV_GEN(dev) >= 12 && + isl_format_get_layout(surf->format)->bpb == 8 && surf->levels >= 3) { + isl_finishme("%s:%s: CCS for 8BPP textures with 3+ miplevels is " + "disabled, but support for more levels is possible.", + __FILE__, __func__); + return false; + } + + /* On Gen12, all CCS-compressed surface pitches must be multiples of 512B. + */ + if (ISL_DEV_GEN(dev) >= 12 && surf->row_pitch_B % 512 != 0) + return false; + if (isl_format_is_compressed(surf->format)) return false; + /* According to GEN:BUG:1406738321, 3D textures need a blit to a new + * surface in order to perform a resolve. For now, just disable CCS. + */ + if (ISL_DEV_GEN(dev) >= 12 && surf->dim == ISL_SURF_DIM_3D) { + isl_finishme("%s:%s: CCS for 3D textures is disabled, but a workaround" + " is available.", __FILE__, __func__); + return false; + } + /* TODO: More conditions where it can fail. */ /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render @@ -1836,7 +1901,21 @@ isl_surf_get_ccs_surf(const struct isl_device *dev, * TiledY/TileYs/TileYf non-MSRTs only. */ enum isl_format ccs_format; - if (ISL_DEV_GEN(dev) >= 9) { + if (ISL_DEV_GEN(dev) >= 12) { + /* TODO: Handle the other tiling formats */ + if (surf->tiling != ISL_TILING_Y0) + return false; + + switch (isl_format_get_layout(surf->format)->bpb) { + case 8: ccs_format = ISL_FORMAT_GEN12_CCS_8BPP_Y0; break; + case 16: ccs_format = ISL_FORMAT_GEN12_CCS_16BPP_Y0; break; + case 32: ccs_format = ISL_FORMAT_GEN12_CCS_32BPP_Y0; break; + case 64: ccs_format = ISL_FORMAT_GEN12_CCS_64BPP_Y0; break; + case 128: ccs_format = ISL_FORMAT_GEN12_CCS_128BPP_Y0; break; + default: + return false; + } + } else if (ISL_DEV_GEN(dev) >= 9) { if (!isl_tiling_is_any_y(surf->tiling)) return false; @@ -1867,18 +1946,39 @@ isl_surf_get_ccs_surf(const struct isl_device *dev, return false; } - return isl_surf_init(dev, ccs_surf, - .dim = surf->dim, - .format = ccs_format, - .width = surf->logical_level0_px.width, - .height = surf->logical_level0_px.height, - .depth = surf->logical_level0_px.depth, - .levels = surf->levels, - .array_len = surf->logical_level0_px.array_len, - .samples = 1, - .row_pitch_B = row_pitch_B, - .usage = ISL_SURF_USAGE_CCS_BIT, - .tiling_flags = ISL_TILING_CCS_BIT); + if (ISL_DEV_GEN(dev) >= 12) { + /* On Gen12, the CCS is a scaled-down version of the main surface. We + * model this as the CCS compressing a 2D-view of the entire surface. + */ + const bool ok = + isl_surf_init(dev, ccs_surf, + .dim = ISL_SURF_DIM_2D, + .format = ccs_format, + .width = isl_surf_get_row_pitch_el(surf), + .height = surf->size_B / surf->row_pitch_B, + .depth = 1, + .levels = 1, + .array_len = 1, + .samples = 1, + .row_pitch_B = row_pitch_B, + .usage = ISL_SURF_USAGE_CCS_BIT, + .tiling_flags = ISL_TILING_GEN12_CCS_BIT); + assert(!ok || ccs_surf->size_B == surf->size_B / 256); + return ok; + } else { + return isl_surf_init(dev, ccs_surf, + .dim = surf->dim, + .format = ccs_format, + .width = surf->logical_level0_px.width, + .height = surf->logical_level0_px.height, + .depth = surf->logical_level0_px.depth, + .levels = surf->levels, + .array_len = surf->logical_level0_px.array_len, + .samples = 1, + .row_pitch_B = row_pitch_B, + .usage = ISL_SURF_USAGE_CCS_BIT, + .tiling_flags = ISL_TILING_CCS_BIT); + } } #define isl_genX_call(dev, func, ...) \ diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h index 5b7458a2285..2a840f48f72 100644 --- a/src/intel/isl/isl.h +++ b/src/intel/isl/isl.h @@ -389,6 +389,11 @@ enum isl_format { ISL_FORMAT_GEN9_CCS_32BPP, ISL_FORMAT_GEN9_CCS_64BPP, ISL_FORMAT_GEN9_CCS_128BPP, + ISL_FORMAT_GEN12_CCS_8BPP_Y0, + ISL_FORMAT_GEN12_CCS_16BPP_Y0, + ISL_FORMAT_GEN12_CCS_32BPP_Y0, + ISL_FORMAT_GEN12_CCS_64BPP_Y0, + ISL_FORMAT_GEN12_CCS_128BPP_Y0, /* An upper bound on the supported format enumerations */ ISL_NUM_FORMATS, @@ -465,6 +470,7 @@ enum isl_tiling { ISL_TILING_Ys, /**< Standard 64K tiling. The 's' means "sixty-four". */ ISL_TILING_HIZ, /**< Tiling format for HiZ surfaces */ ISL_TILING_CCS, /**< Tiling format for CCS surfaces */ + ISL_TILING_GEN12_CCS, /**< Tiling format for Gen12 CCS surfaces */ }; /** @@ -480,6 +486,7 @@ typedef uint32_t isl_tiling_flags_t; #define ISL_TILING_Ys_BIT (1u << ISL_TILING_Ys) #define ISL_TILING_HIZ_BIT (1u << ISL_TILING_HIZ) #define ISL_TILING_CCS_BIT (1u << ISL_TILING_CCS) +#define ISL_TILING_GEN12_CCS_BIT (1u << ISL_TILING_GEN12_CCS) #define ISL_TILING_ANY_MASK (~0u) #define ISL_TILING_NON_LINEAR_MASK (~ISL_TILING_LINEAR_BIT) diff --git a/src/intel/isl/isl_drm.c b/src/intel/isl/isl_drm.c index 196ecf7f88c..cd8c2422e57 100644 --- a/src/intel/isl/isl_drm.c +++ b/src/intel/isl/isl_drm.c @@ -48,6 +48,7 @@ isl_tiling_to_i915_tiling(enum isl_tiling tiling) case ISL_TILING_W: case ISL_TILING_Yf: case ISL_TILING_Ys: + case ISL_TILING_GEN12_CCS: return I915_TILING_NONE; } diff --git a/src/intel/isl/isl_format_layout.csv b/src/intel/isl/isl_format_layout.csv index d9142623f07..81c9e39d735 100644 --- a/src/intel/isl/isl_format_layout.csv +++ b/src/intel/isl/isl_format_layout.csv @@ -343,3 +343,8 @@ GEN7_CCS_128BPP_Y , 1, 2, 4, 1, , , , , , GEN9_CCS_32BPP , 2, 8, 4, 1, , , , , , , , , , ccs GEN9_CCS_64BPP , 2, 4, 4, 1, , , , , , , , , , ccs GEN9_CCS_128BPP , 2, 2, 4, 1, , , , , , , , , , ccs +GEN12_CCS_8BPP_Y0 , 4, 32, 4, 1, , , , , , , , , , ccs +GEN12_CCS_16BPP_Y0 , 4, 16, 4, 1, , , , , , , , , , ccs +GEN12_CCS_32BPP_Y0 , 4, 8, 4, 1, , , , , , , , , , ccs +GEN12_CCS_64BPP_Y0 , 4, 4, 4, 1, , , , , , , , , , ccs +GEN12_CCS_128BPP_Y0 , 4, 2, 4, 1, , , , , , , , , , ccs diff --git a/src/intel/isl/isl_gen12.c b/src/intel/isl/isl_gen12.c index 44dd462cbbd..c177b487213 100644 --- a/src/intel/isl/isl_gen12.c +++ b/src/intel/isl/isl_gen12.c @@ -36,6 +36,14 @@ isl_gen12_choose_image_alignment_el(const struct isl_device *dev, /* Handled by isl_choose_image_alignment_el */ assert(info->format != ISL_FORMAT_HIZ); + const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); + if (fmtl->txc == ISL_TXC_CCS) { + /* This CCS compresses a 2D-view of the entire surface. */ + assert(info->levels == 1 && info->array_len == 1 && info->depth == 1); + *image_align_el = isl_extent3d(1, 1, 1); + return; + } + if (isl_surf_usage_is_depth(info->usage)) { /* The alignment parameters for depth buffers are summarized in the * following table: -- 2.30.2