From 6ff75da8aa41b079e054865789d89269e2501736 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Sun, 12 Jun 2022 14:14:58 -0400 Subject: [PATCH] ail: Introduce image layout module Introduce ail, a small library for working with the image (and buffer) layouts encountered with AGX hardware. Its design is inspired by isl. In particular, ail strives to use isl unit suffixes and to represent quantities in a canonical, API-agnostic fashion [1]. ail replaces the old miptree code (based on some ad hoc heuristics that passed a few dEQP tests). It is based on a thorough reverse-engineering of AGX's twiddled format, courtesy of Asahi Lina, Dougall Johnson, and me. This corrects our handling of many common cases that were totally wrong in the old code, leading to GPU faults. Unlike the code, ail differentiates between pixels and elements consistently, allowing block-compressed formats like ETC2 to be supported correctly. These formats will be enabled later in the series. This commit fixes Inochi2D, glmark2 -brefract and -bterrain, and who knows what else. ail stands for { Asahi, AGX } Image { Layout, Library } at your convenience. ail is best served warm. Liberal use of ail is recommended. Yum! [1] https://docs.mesa3d.org/isl/units.html Signed-off-by: Alyssa Rosenzweig Part-of: --- src/asahi/layout/README | 9 ++ src/asahi/layout/layout.c | 186 ++++++++++++++++++++++++++ src/asahi/layout/layout.h | 159 ++++++++++++++++++++++ src/asahi/layout/meson.build | 32 +++++ src/asahi/meson.build | 3 +- src/gallium/drivers/asahi/agx_pipe.c | 71 ++++------ src/gallium/drivers/asahi/agx_state.c | 21 +-- src/gallium/drivers/asahi/agx_state.h | 26 +--- src/gallium/drivers/asahi/magic.c | 4 +- src/gallium/drivers/asahi/meson.build | 2 +- 10 files changed, 436 insertions(+), 77 deletions(-) create mode 100644 src/asahi/layout/README create mode 100644 src/asahi/layout/layout.c create mode 100644 src/asahi/layout/layout.h create mode 100644 src/asahi/layout/meson.build diff --git a/src/asahi/layout/README b/src/asahi/layout/README new file mode 100644 index 00000000000..a544d9e7079 --- /dev/null +++ b/src/asahi/layout/README @@ -0,0 +1,9 @@ +# ail + +ail is a small library for working with the image (and buffer) layouts +encountered with AGX hardware. Its design is inspired by isl. In +particular, ail strives to use isl unit suffixes and to represent +quantities in a canonical, API-agnostic fashion. + +See the isl documentation for conventions in mesa/docs/isl for the conventions +that ail tries to adhere to, in particular mesa/docs/isl/units.rst. diff --git a/src/asahi/layout/layout.c b/src/asahi/layout/layout.c new file mode 100644 index 00000000000..500b0b75f4d --- /dev/null +++ b/src/asahi/layout/layout.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2022 Alyssa Rosenzweig + * + * 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 "layout.h" + +static void +ail_initialize_linear(struct ail_layout *layout) +{ + /* Select the optimal stride if none is forced */ + if (layout->linear_stride_B == 0) { + uint32_t minimum_stride_B = + util_format_get_stride(layout->format, layout->width_px); + + layout->linear_stride_B = ALIGN_POT(minimum_stride_B, AIL_CACHELINE); + } + + assert((layout->linear_stride_B % 16) == 0 && "Strides must be aligned"); + + layout->size_B = layout->linear_stride_B * layout->height_px; +} + +/* + * Calculate the minimum integer l such that x 2^-l < y, where x is an integer + * and y is a power-of-two. + */ +static unsigned +ail_min_mip_below(unsigned x, unsigned y) +{ + assert(util_is_power_of_two_nonzero(y)); + + if (x < y) + return 0; + else if (util_is_power_of_two_or_zero(x)) + return util_logbase2(x) - util_logbase2(y) + 1; + else + return util_logbase2_ceil(x) - util_logbase2(y); +} + +/* + * Get the maximum tile size possible for a given block size. This satisfy + * width * height * blocksize = 16384 = page size, so each tile is one page. + */ +static inline struct ail_tile +ail_get_max_tile_size(unsigned blocksize_B) +{ + switch (blocksize_B) { + case 1: return (struct ail_tile) { 128, 128 }; + case 2: return (struct ail_tile) { 128, 64 }; + case 4: return (struct ail_tile) { 64, 64 }; + case 8: return (struct ail_tile) { 64, 32 }; + case 16: return (struct ail_tile) { 32, 32 }; + default: unreachable("Invalid blocksize"); + } +} + +static void +ail_initialize_twiddled(struct ail_layout *layout) +{ + unsigned offset_B = 0; + unsigned blocksize_B = util_format_get_blocksize(layout->format); + + unsigned w_el = util_format_get_nblocksx(layout->format, layout->width_px); + unsigned h_el = util_format_get_nblocksy(layout->format, layout->height_px); + + /* Calculate the tile size used for the large miptree, and the dimensions of + * level 0 given that tile size. + */ + struct ail_tile tilesize_el = ail_get_max_tile_size(blocksize_B); + unsigned stx_tiles = DIV_ROUND_UP(w_el, tilesize_el.width_el); + unsigned sty_tiles = DIV_ROUND_UP(h_el, tilesize_el.height_el); + unsigned sarea_tiles = stx_tiles * sty_tiles; + + /* Calculate which level the small power-of-two miptree begins at. The + * power-of-two miptree is used when either the width or the height is + * smaller than a single large tile. + */ + unsigned pot_level = + MIN2(ail_min_mip_below(w_el, tilesize_el.width_el), + ail_min_mip_below(h_el, tilesize_el.height_el)); + + /* First allocate the large miptree. All tiles in the large miptree are of + * size tilesize_el and have their dimensions given by stx/sty/sarea. + */ + for (unsigned l = 0; l < pot_level; ++l) { + unsigned tiles = (sarea_tiles >> (2 * l)); + + bool pad_left = (stx_tiles & BITFIELD_MASK(l)); + bool pad_bottom = (sty_tiles & BITFIELD_MASK(l)); + bool pad_corner = pad_left && pad_bottom; + + if (pad_left) + tiles += (sty_tiles >> l); + + if (pad_bottom) + tiles += (stx_tiles >> l); + + if (pad_corner) + tiles += 1; + + unsigned size_el = tiles * tilesize_el.width_el * tilesize_el.height_el; + layout->level_offsets_B[l] = offset_B; + offset_B = ALIGN_POT(offset_B + (blocksize_B * size_el), AIL_CACHELINE); + + layout->tilesize_el[l] = tilesize_el; + } + + /* Then begin the POT miptree. Note that we round up to a power-of-two + * outside the loop. That ensures correct handling of cases like 33x33 + * images, where the round-down error of right-shifting could cause incorrect + * tile size calculations. + */ + unsigned potw_el = util_next_power_of_two(u_minify(w_el, pot_level)); + unsigned poth_el = util_next_power_of_two(u_minify(h_el, pot_level)); + + /* Finally we allocate the POT miptree, starting at level pot_level. Each + * level uses the largest power-of-two tile that fits the level. + */ + for (unsigned l = pot_level; l < layout->levels; ++l) { + unsigned size_el = potw_el * poth_el; + layout->level_offsets_B[l] = offset_B; + offset_B = ALIGN_POT(offset_B + (blocksize_B * size_el), AIL_CACHELINE); + + unsigned tilesize_el = MIN2(potw_el, poth_el); + layout->tilesize_el[l] = (struct ail_tile) { tilesize_el, tilesize_el }; + + potw_el = u_minify(potw_el, 1); + poth_el = u_minify(poth_el, 1); + } + + /* Arrays and cubemaps have the entire miptree duplicated and page aligned */ + layout->layer_stride_B = ALIGN_POT(offset_B, AIL_PAGESIZE); + layout->size_B = layout->layer_stride_B * layout->depth_px; +} + +void +ail_make_miptree(struct ail_layout *layout) +{ + assert(layout->width_px >= 1 && "Invalid dimensions"); + assert(layout->height_px >= 1 && "Invalid dimensions"); + + if (layout->tiling == AIL_TILING_LINEAR) { + assert(layout->depth_px == 1 && "Invalid linear layout"); + assert(layout->levels == 1 && "Invalid linear layout"); + assert(util_format_get_blockwidth(layout->format) == 1 && + "Strided linear block formats unsupported"); + assert(util_format_get_blockheight(layout->format) == 1 && + "Strided linear block formats unsupported"); + } else { + assert(layout->linear_stride_B == 0 && "Invalid nonlinear layout"); + assert(layout->depth_px >= 1 && "Invalid dimensions"); + assert(layout->levels >= 1 && "Invalid dimensions"); + } + + assert(util_format_get_blockdepth(layout->format) == 1 && + "Deep formats unsupported"); + + if (layout->tiling == AIL_TILING_LINEAR) + ail_initialize_linear(layout); + else if (layout->tiling == AIL_TILING_TWIDDLED) + ail_initialize_twiddled(layout); + else + unreachable("Unsupported tiling"); + + layout->size_B = ALIGN_POT(layout->size_B, AIL_PAGESIZE); + assert(layout->size_B > 0 && "Invalid dimensions"); +} diff --git a/src/asahi/layout/layout.h b/src/asahi/layout/layout.h new file mode 100644 index 00000000000..8ef958f66bf --- /dev/null +++ b/src/asahi/layout/layout.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2022 Alyssa Rosenzweig + * + * 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. + * + */ + +#ifndef __AIL_LAYOUT_H_ +#define __AIL_LAYOUT_H_ + +#include "util/format/u_format.h" +#include "util/u_math.h" +#include "util/macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AIL_CACHELINE 0x80 +#define AIL_PAGESIZE 0x4000 +#define AIL_MAX_MIP_LEVELS 16 + +enum ail_tiling { + /** + * Strided linear (raster order). Only allowed for 1D or 2D, without + * mipmapping, multisampling, block-compression, or arrays. + */ + AIL_TILING_LINEAR, + + /** + * Twiddled (Morton order). Always allowed. + */ + AIL_TILING_TWIDDLED, +}; + +/* + * Represents the dimensions of a single tile. Used to describe tiled layouts. + * Width and height are in units of elements, not pixels, to model compressed + * textures corrects. + * + * Invariant: width_el and height_el are powers of two. + */ +struct ail_tile { + unsigned width_el, height_el; +}; + +/* + * An AGX image layout. + */ +struct ail_layout { + /** Width, height, and depth in pixels at level 0 */ + uint32_t width_px, height_px, depth_px; + + /** Number of miplevels. 1 if no mipmapping is used. */ + uint8_t levels; + + /** Tiling mode used */ + enum ail_tiling tiling; + + /** Texture format */ + enum pipe_format format; + + /** + * If tiling is LINEAR, the number of bytes between adjacent rows of + * elements. Otherwise, this field is zero. + */ + uint32_t linear_stride_B; + + /** + * Stride between layers of an array texture, including a cube map. Layer i + * begins at offset (i * layer_stride_B) from the beginning of the texture. + * + * If depth_px = 1, the value of this field is UNDEFINED. + */ + uint32_t layer_stride_B; + + /** + * Offsets of mip levels within a layer. + */ + uint32_t level_offsets_B[AIL_MAX_MIP_LEVELS]; + + /** + * If tiling is TWIDDLED, the tile size used for each mip level within a + * layer. Calculating tile sizes is the sole responsibility of + * ail_initialized_twiddled. + */ + struct ail_tile tilesize_el[AIL_MAX_MIP_LEVELS]; + + /* Size of entire texture */ + uint32_t size_B; +}; + +static inline uint32_t +ail_get_linear_stride_B(struct ail_layout *layout, ASSERTED uint8_t level) +{ + assert(layout->tiling == AIL_TILING_LINEAR && "Invalid usage"); + assert(level == 0 && "Strided linear mipmapped textures are unsupported"); + + return layout->linear_stride_B; +} + +static inline uint32_t +ail_get_layer_offset_B(struct ail_layout *layout, unsigned z_px) +{ + return z_px * layout->layer_stride_B; +} + +static inline uint32_t +ail_get_level_offset_B(struct ail_layout *layout, unsigned level) +{ + return layout->level_offsets_B[level]; +} + +static inline uint32_t +ail_get_layer_level_B(struct ail_layout *layout, unsigned z_px, unsigned level) +{ + return ail_get_layer_offset_B(layout, z_px) + + ail_get_level_offset_B(layout, level); +} + +static inline uint32_t +ail_get_linear_pixel_B(struct ail_layout *layout, ASSERTED unsigned level, + uint32_t x_px, uint32_t y_px, uint32_t z_px) +{ + assert(level == 0 && "Strided linear mipmapped textures are unsupported"); + assert(z_px == 0 && "Strided linear 3D textures are unsupported"); + assert(util_format_get_blockwidth(layout->format) == 1 && + "Strided linear block formats unsupported"); + assert(util_format_get_blockheight(layout->format) == 1 && + "Strided linear block formats unsupported"); + + return (y_px * ail_get_linear_stride_B(layout, level)) + + (x_px * util_format_get_blocksize(layout->format)); +} + +void ail_make_miptree(struct ail_layout *layout); + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif diff --git a/src/asahi/layout/meson.build b/src/asahi/layout/meson.build new file mode 100644 index 00000000000..2b8e5af7edd --- /dev/null +++ b/src/asahi/layout/meson.build @@ -0,0 +1,32 @@ +# Copyright © 2022 Alyssa Rosenzweig + +# 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 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. + +libasahi_layout_files = files( + 'layout.c', +) + +libasahi_layout = static_library( + 'asahi_layout', + [libasahi_layout_files], + include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_asahi], + c_args : [no_override_init_args], + gnu_symbol_visibility : 'hidden', + build_by_default : false, +) diff --git a/src/asahi/meson.build b/src/asahi/meson.build index f272e926c1c..8b251fd2dbe 100644 --- a/src/asahi/meson.build +++ b/src/asahi/meson.build @@ -20,9 +20,10 @@ # SOFTWARE. inc_asahi = include_directories([ - '.', 'lib', 'compiler' + '.', 'layout', 'lib', 'compiler' ]) +subdir('layout') subdir('lib') subdir('compiler') diff --git a/src/gallium/drivers/asahi/agx_pipe.c b/src/gallium/drivers/asahi/agx_pipe.c index 389b11f2150..cb639d5debb 100644 --- a/src/gallium/drivers/asahi/agx_pipe.c +++ b/src/gallium/drivers/asahi/agx_pipe.c @@ -167,35 +167,15 @@ agx_resource_create(struct pipe_screen *screen, nresource->mipmapped = (templ->last_level > 0); nresource->internal_format = nresource->base.format; - unsigned offset = 0; - unsigned blocksize = util_format_get_blocksize(templ->format); - - for (unsigned l = 0; l <= templ->last_level; ++l) { - unsigned width = u_minify(templ->width0, l); - unsigned height = u_minify(templ->height0, l); - - if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) { - unsigned tile = agx_select_tile_size(templ->width0, templ->height0, l, blocksize); - - width = ALIGN_POT(width, tile); - height = ALIGN_POT(height, tile); - } - - /* Align stride to presumed cache line */ - nresource->slices[l].line_stride = util_format_get_stride(templ->format, width); - if (nresource->modifier == DRM_FORMAT_MOD_LINEAR) { - nresource->slices[l].line_stride = ALIGN_POT(nresource->slices[l].line_stride, 64); - } - - nresource->slices[l].offset = offset; - nresource->slices[l].size = ALIGN_POT(nresource->slices[l].line_stride * height, 0x80); - - offset += nresource->slices[l].size; - } - - /* Arrays and cubemaps have the entire miptree duplicated and page aligned (16K) */ - nresource->array_stride = ALIGN_POT(offset, 0x4000); - unsigned size = nresource->array_stride * templ->array_size * templ->depth0; + nresource->layout = (struct ail_layout) { + .tiling = (nresource->modifier == DRM_FORMAT_MOD_LINEAR) ? + AIL_TILING_LINEAR : AIL_TILING_TWIDDLED, + .format = templ->format, + .width_px = templ->width0, + .height_px = templ->height0, + .depth_px = templ->depth0 * templ->array_size, + .levels = templ->last_level + 1 + }; pipe_reference_init(&nresource->base.reference, 1); @@ -204,26 +184,25 @@ agx_resource_create(struct pipe_screen *screen, if (templ->bind & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)) { - unsigned width0 = templ->width0, height0 = templ->height0; + unsigned width = templ->width0; + unsigned height = templ->height0; - if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) { - width0 = ALIGN_POT(width0, 64); - height0 = ALIGN_POT(height0, 64); + if (nresource->layout.tiling == AIL_TILING_TWIDDLED) { + width = ALIGN_POT(width, 64); + height = ALIGN_POT(height, 64); } nresource->dt = winsys->displaytarget_create(winsys, templ->bind, templ->format, - width0, - height0, + width, + height, 64, NULL /*map_front_private*/, &nresource->dt_stride); - nresource->slices[0].line_stride = nresource->dt_stride; - assert((nresource->dt_stride & 0xF) == 0); - - offset = nresource->slices[0].line_stride * ALIGN_POT(templ->height0, 64); + if (nresource->layout.tiling == AIL_TILING_LINEAR) + nresource->layout.linear_stride_B = nresource->dt_stride; if (nresource->dt == NULL) { FREE(nresource); @@ -231,7 +210,8 @@ agx_resource_create(struct pipe_screen *screen, } } - nresource->bo = agx_bo_create(dev, size, AGX_MEMORY_TYPE_FRAMEBUFFER); + ail_make_miptree(&nresource->layout); + nresource->bo = agx_bo_create(dev, nresource->layout.size_B, AGX_MEMORY_TYPE_FRAMEBUFFER); if (!nresource->bo) { FREE(nresource); @@ -322,17 +302,18 @@ agx_transfer_map(struct pipe_context *pctx, } else { assert (rsrc->modifier == DRM_FORMAT_MOD_LINEAR); - transfer->base.stride = rsrc->slices[level].line_stride; - transfer->base.layer_stride = rsrc->array_stride; + transfer->base.stride = ail_get_linear_stride_B(&rsrc->layout, level); + transfer->base.layer_stride = rsrc->layout.layer_stride_B; /* Be conservative for direct writes */ if ((usage & PIPE_MAP_WRITE) && (usage & PIPE_MAP_DIRECTLY)) BITSET_SET(rsrc->data_valid, level); - return (uint8_t *) agx_map_texture_cpu(rsrc, level, box->z) - + transfer->base.box.y * rsrc->slices[level].line_stride - + transfer->base.box.x * blocksize; + uint32_t offset = ail_get_linear_pixel_B(&rsrc->layout, level, box->x, + box->y, box->z); + + return ((uint8_t *) rsrc->bo->ptr.cpu) + offset; } } diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index b0612ba3c95..36296b544b9 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -483,9 +483,12 @@ agx_create_sampler_view(struct pipe_context *pctx, else cfg.depth = state->u.tex.last_layer - state->u.tex.first_layer + 1; - cfg.stride = (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) ? - (rsrc->slices[level].line_stride - 16) : - AGX_RT_STRIDE_TILED; + if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) { + cfg.stride = ail_get_linear_stride_B(&rsrc->layout, level) - 16; + } else { + assert(rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER); + cfg.stride = AGX_RT_STRIDE_TILED; + } } /* Initialize base object */ @@ -760,10 +763,12 @@ agx_set_framebuffer_state(struct pipe_context *pctx, if (tex->mipmapped) cfg.unk_55 = 0x8; - cfg.stride = (tex->modifier == DRM_FORMAT_MOD_LINEAR) ? - (tex->slices[level].line_stride - 4) : - tex->mipmapped ? AGX_RT_STRIDE_TILED_MIPMAPPED : - AGX_RT_STRIDE_TILED; + if (tex->modifier == DRM_FORMAT_MOD_LINEAR) { + cfg.stride = ail_get_linear_stride_B(&tex->layout, level) - 4; + } else { + cfg.stride = tex->mipmapped ? AGX_RT_STRIDE_TILED_MIPMAPPED : + AGX_RT_STRIDE_TILED; + } }; } } @@ -1353,7 +1358,7 @@ agx_build_reload_pipeline(struct agx_context *ctx, uint32_t code, struct pipe_su cfg.address = agx_map_texture_gpu(rsrc, level, layer); cfg.stride = (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) ? - (rsrc->slices[level].line_stride - 16) : + (ail_get_linear_stride_B(&rsrc->layout, level) - 16) : AGX_RT_STRIDE_TILED; } diff --git a/src/gallium/drivers/asahi/agx_state.h b/src/gallium/drivers/asahi/agx_state.h index 94f4b2796b1..791c95b44c8 100644 --- a/src/gallium/drivers/asahi/agx_state.h +++ b/src/gallium/drivers/asahi/agx_state.h @@ -34,6 +34,7 @@ #include "asahi/lib/agx_device.h" #include "asahi/lib/pool.h" #include "asahi/compiler/agx_compile.h" +#include "asahi/layout/layout.h" #include "compiler/nir/nir_lower_blend.h" #include "util/hash_table.h" #include "util/bitset.h" @@ -248,14 +249,7 @@ struct agx_resource { BITSET_DECLARE(data_valid, PIPE_MAX_TEXTURE_LEVELS); - struct { - unsigned offset; - unsigned line_stride; - unsigned size; - } slices[PIPE_MAX_TEXTURE_LEVELS]; - - /* Bytes from one miptree to the next */ - unsigned array_stride; + struct ail_layout layout; /* Metal does not support packed depth/stencil formats; presumably AGX does * not either. Instead, we create separate depth and stencil resources, @@ -274,26 +268,18 @@ agx_resource(struct pipe_resource *pctx) return (struct agx_resource *) pctx; } -/* - * Within a resource containing multiple layers and multiple mip levels, - * returns the offset from the start of the backing BO of a given level/slice. - */ -static inline uint32_t -agx_texture_offset(struct agx_resource *rsrc, unsigned level, unsigned z) -{ - return rsrc->slices[level].offset + (z * rsrc->array_stride); -} - static inline void * agx_map_texture_cpu(struct agx_resource *rsrc, unsigned level, unsigned z) { - return ((uint8_t *) rsrc->bo->ptr.cpu) + agx_texture_offset(rsrc, level, z); + return ((uint8_t *) rsrc->bo->ptr.cpu) + + ail_get_layer_level_B(&rsrc->layout, z, level); } static inline uint64_t agx_map_texture_gpu(struct agx_resource *rsrc, unsigned level, unsigned z) { - return rsrc->bo->ptr.gpu + (uint64_t) agx_texture_offset(rsrc, level, z); + return rsrc->bo->ptr.gpu + + (uint64_t) ail_get_layer_level_B(&rsrc->layout, z, level); } struct agx_transfer { diff --git a/src/gallium/drivers/asahi/magic.c b/src/gallium/drivers/asahi/magic.c index d7307776c1e..dcf051bed95 100644 --- a/src/gallium/drivers/asahi/magic.c +++ b/src/gallium/drivers/asahi/magic.c @@ -54,7 +54,7 @@ static size_t asahi_size_resource(struct pipe_resource *prsrc, unsigned level) { struct agx_resource *rsrc = agx_resource(prsrc); - size_t size = rsrc->slices[level].size; + size_t size = rsrc->layout.size_B; if (rsrc->separate_stencil) size += asahi_size_resource(&rsrc->separate_stencil->base, level); @@ -118,7 +118,7 @@ asahi_pack_iogpu_attachment(void *out, struct agx_resource *rsrc, agx_pack(out, IOGPU_ATTACHMENT, cfg) { cfg.type = asahi_classify_attachment(rsrc->base.format); cfg.address = agx_map_surface_resource(surf, rsrc); - cfg.size = rsrc->slices[surf->u.tex.level].size; + cfg.size = rsrc->layout.size_B; cfg.percent = (100 * cfg.size) / total_size; } } diff --git a/src/gallium/drivers/asahi/meson.build b/src/gallium/drivers/asahi/meson.build index 24da3bc10cf..c19ae0f20bf 100644 --- a/src/gallium/drivers/asahi/meson.build +++ b/src/gallium/drivers/asahi/meson.build @@ -37,5 +37,5 @@ libasahi = static_library( driver_asahi = declare_dependency( compile_args : '-DGALLIUM_ASAHI', - link_with : [libasahi, libasahi_compiler, libasahi_lib, libasahi_decode] + link_with : [libasahi, libasahi_compiler, libasahi_lib, libasahi_layout, libasahi_decode] )