[igt-dev] [PATCH i-g-t 5/6] lib/igt_fb: Add support for remapping CCS FBs

Juha-Pekka Heikkila juhapekka.heikkila at gmail.com
Tue Aug 31 17:49:28 UTC 2021


Look ok to me

Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila at gmail.com>

On 27.8.2021 17.57, Imre Deak wrote:
> Having a kernel support for this, CCS framebuffer strides don't need to
> be power-of-two aligned, the kernel will auto-pad the stride.
> 
> Only the main surface tiles can be remapped and the AUX surface must be
> generated to align with the POT padded main surface stride. Add the
> required AUX pagetable programming for this.
> 
> Since the AUX pagetable has a granularity of 64 kbytes on the main
> surface, mapped by one AUX PTE, the main surface stride must be either 8
> tiles, or the stride must be aligned to 16 tiles.
> 
> Signed-off-by: Imre Deak <imre.deak at intel.com>
> ---
>   lib/igt_fb.c            | 24 ++++++++-------
>   lib/intel_aux_pgtable.c | 66 ++++++++++++++++++++++++++++++++++++-----
>   2 files changed, 72 insertions(+), 18 deletions(-)
> 
> diff --git a/lib/igt_fb.c b/lib/igt_fb.c
> index 2e53d9225..72291f4f7 100644
> --- a/lib/igt_fb.c
> +++ b/lib/igt_fb.c
> @@ -780,23 +780,27 @@ static uint32_t calc_plane_stride(struct igt_fb *fb, int plane)
>   		return ALIGN(min_stride, align);
>   	} else {
>   		unsigned int tile_width, tile_height;
> -		uint32_t stride;
> +		int tile_align = 1;
>   
>   		igt_get_fb_tile_size(fb->fd, fb->modifier, fb->plane_bpp[plane],
>   				     &tile_width, &tile_height);
>   
>   		if (is_gen12_ccs_modifier(fb->modifier)) {
> -			stride = ALIGN(min_stride, tile_width * 4);
> -
> -			/* TODO: add support to kernel to POT align CCS format strides */
> -			if (is_i915_device(fb->fd) &&
> -			    IS_ALDERLAKE_P(intel_get_drm_devid(fb->fd)))
> -				stride = roundup_power_of_two(max(stride, tile_width * 8));
> -		} else {
> -			stride = ALIGN(min_stride, tile_width);
> +			if (IS_ALDERLAKE_P(intel_get_drm_devid(fb->fd)))
> +				/*
> +				 * The main surface stride must be aligned to the CCS AUX
> +				 * page table block size (covered by one AUX PTE). This
> +				 * block size is 64kb -> 16 tiles.
> +				 * We can do away padding an 8 tile stride to 16, since in
> +				 * this case one AUX PTE entry will cover 2 main surface
> +				 * tile rows.
> +				 */
> +				tile_align = (min_stride <= 8 * tile_width) ? 8 : 16;
> +			else
> +				tile_align = 4;
>   		}
>   
> -		return stride;
> +		return ALIGN(min_stride, tile_width * tile_align);
>   	}
>   }
>   
> diff --git a/lib/intel_aux_pgtable.c b/lib/intel_aux_pgtable.c
> index d89b0575a..fcc337b8d 100644
> --- a/lib/intel_aux_pgtable.c
> +++ b/lib/intel_aux_pgtable.c
> @@ -7,6 +7,8 @@
>   #include "intel_bufops.h"
>   #include "ioctl_wrappers.h"
>   
> +#include "lib/intel_chipset.h"
> +
>   #include "i915/gem_mman.h"
>   
>   #define BITS_PER_LONG_LONG	(sizeof(long long) * 8)
> @@ -356,22 +358,70 @@ pgt_populate_entries_for_buf(struct pgtable *pgt,
>   	uint64_t aux_addr = buf->addr.offset + buf->ccs[surface_idx].offset;
>   	uint64_t l1_flags = pgt_get_l1_flags(buf, surface_idx);
>   	uint64_t lx_flags = pgt_get_lx_flags();
> +	int surface_tile_align;
> +	int surface_src_row_tiles = buf->surface[surface_idx].stride / 128;
> +	/*
> +	 * The span of tiles in the FB object mapped by one AUX PTE
> +	 * entry, which can be one or more tile rows.
> +	 */
> +	int surface_src_span_tiles = ALIGN(surface_src_row_tiles, 16);
> +	int surface_src_span_size = surface_src_span_tiles * 4096;
> +	/*
> +	 * The number of tiles in a tile row on the surface auto-padded by
> +	 * the kernel if necessary (to a power-of-two size on ADL-P).
> +	 */
> +	int surface_dst_row_tiles;
> +	/*
> +	 * The span of tiles on the auto-padded surface, including the
> +	 * tiles in the FB object accounted by surface_src_span_tiles and
> +	 * any padding tiles.
> +	 */
> +	int surface_dst_span_tiles;
> +	/*
> +	 * The size of CCS data mapping a surface_dst_span_tiles sized area
> +	 * on the main surface.
> +	 */
> +	int aux_dst_span_size;
> +	int surface_span_offset = 0;
> +	int aux_span_offset = 0;
>   
> -	igt_assert(!(buf->surface[surface_idx].stride % 512));
> -	igt_assert_eq(buf->ccs[surface_idx].stride,
> -		      buf->surface[surface_idx].stride / 512 * 64);
> +	if (IS_ALDERLAKE_P(buf->ibb->devid)) {
> +		surface_tile_align = surface_src_row_tiles <= 8 ? 8 : 16;
> +		surface_dst_row_tiles = roundup_power_of_two(surface_src_row_tiles);
> +		surface_dst_span_tiles = roundup_power_of_two(surface_src_span_tiles);
> +	} else {
> +		surface_tile_align = 4;
> +		surface_dst_row_tiles = surface_src_row_tiles;
> +		surface_dst_span_tiles = surface_src_span_tiles;
> +	}
>   
> -	for (; surface_addr < surface_end;
> -	     surface_addr += MAIN_SURFACE_BLOCK_SIZE,
> -	     aux_addr += AUX_CCS_BLOCK_SIZE) {
> +	aux_dst_span_size = surface_dst_span_tiles / 16 * AUX_CCS_BLOCK_SIZE;
> +
> +	igt_assert_eq(buf->surface[surface_idx].stride % (128 * surface_tile_align), 0);
> +	igt_assert_eq(buf->ccs[surface_idx].stride, surface_dst_row_tiles / 4 * 64);
> +
> +	while (surface_addr + surface_span_offset < surface_end) {
>   		uint64_t table = top_table;
>   		int level;
>   
>   		for (level = pgt->levels - 1; level >= 1; level--)
>   			table = pgt_get_child_table(pgt, table, level,
> -						    surface_addr, lx_flags);
> +						    surface_addr + surface_span_offset, lx_flags);
>   
> -		pgt_set_l1_entry(pgt, table, surface_addr, aux_addr, l1_flags);
> +		pgt_set_l1_entry(pgt, table,
> +				 surface_addr + surface_span_offset,
> +				 aux_addr + aux_span_offset, l1_flags);
> +
> +		surface_span_offset += MAIN_SURFACE_BLOCK_SIZE;
> +		aux_span_offset += AUX_CCS_BLOCK_SIZE;
> +
> +		if (surface_span_offset >= surface_src_span_size) {
> +			surface_addr += surface_src_span_size;
> +			surface_span_offset = 0;
> +
> +			aux_addr += aux_dst_span_size;
> +			aux_span_offset = 0;
> +		}
>   	}
>   }
>   
> 



More information about the igt-dev mailing list