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 <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18167>
This commit is contained in:
Alyssa Rosenzweig 2022-06-12 14:14:58 -04:00 committed by Marge Bot
parent 5057d6787a
commit 6ff75da8aa
10 changed files with 436 additions and 77 deletions

9
src/asahi/layout/README Normal file
View file

@ -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.

186
src/asahi/layout/layout.c Normal file
View file

@ -0,0 +1,186 @@
/*
* Copyright (C) 2022 Alyssa Rosenzweig <alyssa@rosenzweig.io>
*
* 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");
}

159
src/asahi/layout/layout.h Normal file
View file

@ -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

View file

@ -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,
)

View file

@ -20,9 +20,10 @@
# SOFTWARE.
inc_asahi = include_directories([
'.', 'lib', 'compiler'
'.', 'layout', 'lib', 'compiler'
])
subdir('layout')
subdir('lib')
subdir('compiler')

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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 {

View file

@ -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;
}
}

View file

@ -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]
)