panfrost: Add a pan_image_layout object

Group the slices, dimension, modifier and array stride in a an object
representing the image layout. This way we shrink the number of
arguments passed to various pan_texture helpers and simplifies some
of the logic along the way.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8125>
This commit is contained in:
Boris Brezillon 2020-12-17 12:12:28 +01:00
parent e9e823ec83
commit 4dd7991422
11 changed files with 191 additions and 224 deletions

View file

@ -1042,7 +1042,7 @@ panfrost_update_sampler_view(struct panfrost_sampler_view *view,
{ {
struct panfrost_resource *rsrc = pan_resource(view->base.texture); struct panfrost_resource *rsrc = pan_resource(view->base.texture);
if (view->texture_bo != rsrc->bo->ptr.gpu || if (view->texture_bo != rsrc->bo->ptr.gpu ||
view->modifier != rsrc->modifier) { view->modifier != rsrc->layout.modifier) {
panfrost_bo_unreference(view->bo); panfrost_bo_unreference(view->bo);
panfrost_create_sampler_view_bo(view, pctx, &rsrc->base); panfrost_create_sampler_view_bo(view, pctx, &rsrc->base);
} }

View file

@ -1011,7 +1011,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
} }
so->texture_bo = prsrc->bo->ptr.gpu; so->texture_bo = prsrc->bo->ptr.gpu;
so->modifier = prsrc->modifier; so->modifier = prsrc->layout.modifier;
unsigned char user_swizzle[4] = { unsigned char user_swizzle[4] = {
so->base.swizzle_r, so->base.swizzle_r,
@ -1048,7 +1048,8 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
so->base.u.tex.first_layer, so->base.u.tex.first_layer,
so->base.u.tex.last_layer, so->base.u.tex.last_layer,
texture->nr_samples, texture->nr_samples,
type, prsrc->modifier); type,
prsrc->layout.modifier);
so->bo = panfrost_bo_create(device, size, 0); so->bo = panfrost_bo_create(device, size, 0);
@ -1060,20 +1061,17 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
payload.gpu += MALI_MIDGARD_TEXTURE_LENGTH; payload.gpu += MALI_MIDGARD_TEXTURE_LENGTH;
} }
panfrost_new_texture(device, tex, panfrost_new_texture(device, &prsrc->layout, tex,
texture->width0, texture->height0, texture->width0, texture->height0,
depth, array_size, depth, array_size,
format, format, type,
type, prsrc->modifier,
so->base.u.tex.first_level, so->base.u.tex.first_level,
so->base.u.tex.last_level, so->base.u.tex.last_level,
so->base.u.tex.first_layer, so->base.u.tex.first_layer,
so->base.u.tex.last_layer, so->base.u.tex.last_layer,
texture->nr_samples, texture->nr_samples,
prsrc->cubemap_stride,
panfrost_translate_swizzle_4(user_swizzle), panfrost_translate_swizzle_4(user_swizzle),
prsrc->bo->ptr.gpu, prsrc->bo->ptr.gpu, &payload);
prsrc->slices, &payload);
} }
static struct pipe_sampler_view * static struct pipe_sampler_view *

View file

@ -42,7 +42,7 @@ panfrost_initialize_surface(
unsigned level = surf->u.tex.level; unsigned level = surf->u.tex.level;
struct panfrost_resource *rsrc = pan_resource(surf->texture); struct panfrost_resource *rsrc = pan_resource(surf->texture);
rsrc->slices[level].initialized = true; rsrc->layout.slices[level].initialized = true;
} }
/* Generate a fragment job. This should be called once per frame. (According to /* Generate a fragment job. This should be called once per frame. (According to

View file

@ -759,7 +759,7 @@ panfrost_load_surface(struct panfrost_batch *batch, struct pipe_surface *surf, u
struct panfrost_resource *rsrc = pan_resource(surf->texture); struct panfrost_resource *rsrc = pan_resource(surf->texture);
unsigned level = surf->u.tex.level; unsigned level = surf->u.tex.level;
if (!rsrc->slices[level].initialized) if (!rsrc->layout.slices[level].initialized)
return; return;
if (!rsrc->damage.inverted_len) if (!rsrc->damage.inverted_len)
@ -808,16 +808,14 @@ panfrost_load_surface(struct panfrost_batch *batch, struct pipe_surface *surf, u
.depth0 = rsrc->base.depth0, .depth0 = rsrc->base.depth0,
.format = format, .format = format,
.dim = dim, .dim = dim,
.modifier = rsrc->modifier,
.array_size = rsrc->base.array_size, .array_size = rsrc->base.array_size,
.first_level = level, .first_level = level,
.last_level = level, .last_level = level,
.first_layer = surf->u.tex.first_layer, .first_layer = surf->u.tex.first_layer,
.last_layer = surf->u.tex.last_layer, .last_layer = surf->u.tex.last_layer,
.nr_samples = rsrc->base.nr_samples, .nr_samples = rsrc->base.nr_samples,
.cubemap_stride = rsrc->cubemap_stride,
.bo = rsrc->bo, .bo = rsrc->bo,
.slices = rsrc->slices .layout = &rsrc->layout,
}; };
mali_ptr blend_shader = 0; mali_ptr blend_shader = 0;

View file

@ -134,12 +134,12 @@ panfrost_mfbd_rt_set_buf(struct pipe_surface *surf,
unsigned level = surf->u.tex.level; unsigned level = surf->u.tex.level;
unsigned first_layer = surf->u.tex.first_layer; unsigned first_layer = surf->u.tex.first_layer;
assert(surf->u.tex.last_layer == first_layer); assert(surf->u.tex.last_layer == first_layer);
int row_stride = rsrc->slices[level].row_stride; int row_stride = rsrc->layout.slices[level].row_stride;
/* Only set layer_stride for layered MSAA rendering */ /* Only set layer_stride for layered MSAA rendering */
unsigned nr_samples = surf->texture->nr_samples; unsigned nr_samples = surf->texture->nr_samples;
unsigned layer_stride = (nr_samples > 1) ? rsrc->slices[level].surface_stride : 0; unsigned layer_stride = (nr_samples > 1) ? rsrc->layout.slices[level].surface_stride : 0;
mali_ptr base = panfrost_get_texture_address(rsrc, level, first_layer, 0); mali_ptr base = panfrost_get_texture_address(rsrc, level, first_layer, 0);
if (layer_stride) if (layer_stride)
@ -151,7 +151,7 @@ panfrost_mfbd_rt_set_buf(struct pipe_surface *surf,
panfrost_mfbd_rt_init_format(surf, rt); panfrost_mfbd_rt_init_format(surf, rt);
if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) { if (rsrc->layout.modifier == DRM_FORMAT_MOD_LINEAR) {
if (version >= 7) if (version >= 7)
rt->bifrost_v7.writeback_block_format = MALI_BLOCK_FORMAT_V7_LINEAR; rt->bifrost_v7.writeback_block_format = MALI_BLOCK_FORMAT_V7_LINEAR;
else else
@ -160,7 +160,7 @@ panfrost_mfbd_rt_set_buf(struct pipe_surface *surf,
rt->rgb.base = base; rt->rgb.base = base;
rt->rgb.row_stride = row_stride; rt->rgb.row_stride = row_stride;
rt->rgb.surface_stride = layer_stride; rt->rgb.surface_stride = layer_stride;
} else if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { } else if (rsrc->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
if (version >= 7) if (version >= 7)
rt->bifrost_v7.writeback_block_format = MALI_BLOCK_FORMAT_V7_TILED_U_INTERLEAVED; rt->bifrost_v7.writeback_block_format = MALI_BLOCK_FORMAT_V7_TILED_U_INTERLEAVED;
else else
@ -169,13 +169,13 @@ panfrost_mfbd_rt_set_buf(struct pipe_surface *surf,
rt->rgb.base = base; rt->rgb.base = base;
rt->rgb.row_stride = row_stride; rt->rgb.row_stride = row_stride;
rt->rgb.surface_stride = layer_stride; rt->rgb.surface_stride = layer_stride;
} else if (drm_is_afbc(rsrc->modifier)) { } else if (drm_is_afbc(rsrc->layout.modifier)) {
if (version >= 7) if (version >= 7)
rt->bifrost_v7.writeback_block_format = MALI_BLOCK_FORMAT_V7_AFBC; rt->bifrost_v7.writeback_block_format = MALI_BLOCK_FORMAT_V7_AFBC;
else else
rt->midgard.writeback_block_format = MALI_BLOCK_FORMAT_AFBC; rt->midgard.writeback_block_format = MALI_BLOCK_FORMAT_AFBC;
unsigned header_size = rsrc->slices[level].header_size; unsigned header_size = rsrc->layout.slices[level].header_size;
rt->afbc.header = base; rt->afbc.header = base;
rt->afbc.chunk_size = 9; rt->afbc.chunk_size = 9;
@ -184,7 +184,7 @@ panfrost_mfbd_rt_set_buf(struct pipe_surface *surf,
if (!(dev->quirks & IS_BIFROST)) if (!(dev->quirks & IS_BIFROST))
rt->midgard_afbc.sparse = true; rt->midgard_afbc.sparse = true;
if (rsrc->modifier & AFBC_FORMAT_MOD_YTR) if (rsrc->layout.modifier & AFBC_FORMAT_MOD_YTR)
rt->afbc.yuv_transform_enable = true; rt->afbc.yuv_transform_enable = true;
/* TODO: The blob sets this to something nonzero, but it's not /* TODO: The blob sets this to something nonzero, but it's not
@ -254,7 +254,7 @@ panfrost_mfbd_zs_crc_ext_set_bufs(struct panfrost_batch *batch,
if (rsrc->checksummed) { if (rsrc->checksummed) {
unsigned level = c_surf->u.tex.level; unsigned level = c_surf->u.tex.level;
struct panfrost_slice *slice = &rsrc->slices[level]; struct panfrost_slice *slice = &rsrc->layout.slices[level];
ext->crc_row_stride = slice->crc.stride; ext->crc_row_stride = slice->crc.stride;
if (rsrc->checksum_bo) if (rsrc->checksum_bo)
@ -291,8 +291,8 @@ panfrost_mfbd_zs_crc_ext_set_bufs(struct panfrost_batch *batch,
else else
ext->zs_msaa_v7 = nr_samples > 1 ? MALI_MSAA_LAYERED : MALI_MSAA_SINGLE; ext->zs_msaa_v7 = nr_samples > 1 ? MALI_MSAA_LAYERED : MALI_MSAA_SINGLE;
if (drm_is_afbc(rsrc->modifier)) { if (drm_is_afbc(rsrc->layout.modifier)) {
unsigned header_size = rsrc->slices[level].header_size; unsigned header_size = rsrc->layout.slices[level].header_size;
ext->zs_afbc_header = base; ext->zs_afbc_header = base;
ext->zs_afbc_body = base + header_size; ext->zs_afbc_body = base + header_size;
ext->zs_afbc_body_size = 0x1000; ext->zs_afbc_body_size = 0x1000;
@ -304,19 +304,18 @@ panfrost_mfbd_zs_crc_ext_set_bufs(struct panfrost_batch *batch,
else else
ext->zs_block_format = MALI_BLOCK_FORMAT_AFBC; ext->zs_block_format = MALI_BLOCK_FORMAT_AFBC;
} else { } else {
assert(rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED || assert(rsrc->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||
rsrc->modifier == DRM_FORMAT_MOD_LINEAR); rsrc->layout.modifier == DRM_FORMAT_MOD_LINEAR);
/* TODO: Z32F(S8) support, which is always linear */ /* TODO: Z32F(S8) support, which is always linear */
int row_stride = rsrc->slices[level].row_stride;
unsigned layer_stride = (nr_samples > 1) ? rsrc->slices[level].surface_stride : 0;
ext->zs_writeback_base = base; ext->zs_writeback_base = base;
ext->zs_writeback_row_stride = row_stride; ext->zs_writeback_row_stride =
ext->zs_writeback_surface_stride = layer_stride; rsrc->layout.slices[level].row_stride;
ext->zs_writeback_surface_stride =
(nr_samples > 1) ?
rsrc->layout.slices[level].surface_stride : 0;
if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) { if (rsrc->layout.modifier == DRM_FORMAT_MOD_LINEAR) {
if (version >= 7) if (version >= 7)
ext->zs_block_format_v7 = MALI_BLOCK_FORMAT_V7_LINEAR; ext->zs_block_format_v7 = MALI_BLOCK_FORMAT_V7_LINEAR;
else else
@ -358,12 +357,14 @@ panfrost_mfbd_zs_crc_ext_set_bufs(struct panfrost_batch *batch,
} }
struct panfrost_resource *stencil = rsrc->separate_stencil; struct panfrost_resource *stencil = rsrc->separate_stencil;
struct panfrost_slice stencil_slice = stencil->slices[level]; struct panfrost_slice *stencil_slice =
unsigned stencil_layer_stride = (nr_samples > 1) ? stencil_slice.surface_stride : 0; &stencil->layout.slices[level];
ext->s_writeback_base = panfrost_get_texture_address(stencil, level, first_layer, 0); ext->s_writeback_base =
ext->s_writeback_row_stride = stencil_slice.row_stride; panfrost_get_texture_address(stencil, level, first_layer, 0);
ext->s_writeback_surface_stride = stencil_layer_stride; ext->s_writeback_row_stride = stencil_slice->row_stride;
ext->s_writeback_surface_stride =
(nr_samples > 1) ? stencil_slice->surface_stride : 0;
break; break;
default: default:
unreachable("Unsupported depth/stencil format."); unreachable("Unsupported depth/stencil format.");

View file

@ -96,36 +96,39 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
rsc->bo = panfrost_bo_import(dev, whandle->handle); rsc->bo = panfrost_bo_import(dev, whandle->handle);
rsc->internal_format = templat->format; rsc->internal_format = templat->format;
rsc->modifier = (whandle->modifier == DRM_FORMAT_MOD_INVALID) ? rsc->layout.modifier = (whandle->modifier == DRM_FORMAT_MOD_INVALID) ?
DRM_FORMAT_MOD_LINEAR : whandle->modifier; DRM_FORMAT_MOD_LINEAR : whandle->modifier;
rsc->layout.dim = panfrost_translate_texture_dimension(templat->target);
rsc->modifier_constant = true; rsc->modifier_constant = true;
rsc->slices[0].line_stride = whandle->stride; rsc->layout.slices[0].line_stride = whandle->stride;
rsc->slices[0].row_stride = whandle->stride; rsc->layout.slices[0].row_stride = whandle->stride;
if (rsc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED || if (rsc->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||
drm_is_afbc(rsc->modifier)) { drm_is_afbc(rsc->layout.modifier)) {
unsigned tile_h = panfrost_block_dim(rsc->modifier, false, 0); unsigned tile_h = panfrost_block_dim(rsc->layout.modifier, false, 0);
if (util_format_is_compressed(rsc->internal_format)) if (util_format_is_compressed(rsc->internal_format))
tile_h >>= 2; tile_h >>= 2;
rsc->slices[0].row_stride *= tile_h; rsc->layout.slices[0].row_stride *= tile_h;
} }
rsc->slices[0].offset = whandle->offset; rsc->layout.slices[0].offset = whandle->offset;
rsc->slices[0].initialized = true; rsc->layout.slices[0].initialized = true;
panfrost_resource_set_damage_region(NULL, &rsc->base, 0, NULL); panfrost_resource_set_damage_region(NULL, &rsc->base, 0, NULL);
if (dev->quirks & IS_BIFROST && if (dev->quirks & IS_BIFROST &&
templat->bind & PIPE_BIND_RENDER_TARGET) { templat->bind & PIPE_BIND_RENDER_TARGET) {
unsigned size = panfrost_compute_checksum_size( unsigned size =
&rsc->slices[0], templat->width0, templat->height0); panfrost_compute_checksum_size(&rsc->layout.slices[0],
templat->width0,
templat->height0);
rsc->checksum_bo = panfrost_bo_create(dev, size, 0); rsc->checksum_bo = panfrost_bo_create(dev, size, 0);
rsc->checksummed = true; rsc->checksummed = true;
} }
if (drm_is_afbc(whandle->modifier)) { if (drm_is_afbc(whandle->modifier)) {
rsc->slices[0].header_size = rsc->layout.slices[0].header_size =
panfrost_afbc_header_size(templat->width0, templat->height0); panfrost_afbc_header_size(templat->width0, templat->height0);
} }
@ -149,7 +152,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
struct panfrost_resource *rsrc = (struct panfrost_resource *) pt; struct panfrost_resource *rsrc = (struct panfrost_resource *) pt;
struct renderonly_scanout *scanout = rsrc->scanout; struct renderonly_scanout *scanout = rsrc->scanout;
handle->modifier = rsrc->modifier; handle->modifier = rsrc->layout.modifier;
rsrc->modifier_constant = true; rsrc->modifier_constant = true;
if (handle->type == WINSYS_HANDLE_TYPE_SHARED) { if (handle->type == WINSYS_HANDLE_TYPE_SHARED) {
@ -159,8 +162,8 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
return true; return true;
handle->handle = rsrc->bo->gem_handle; handle->handle = rsrc->bo->gem_handle;
handle->stride = rsrc->slices[0].line_stride; handle->stride = rsrc->layout.slices[0].line_stride;
handle->offset = rsrc->slices[0].offset; handle->offset = rsrc->layout.slices[0].offset;
return TRUE; return TRUE;
} else if (handle->type == WINSYS_HANDLE_TYPE_FD) { } else if (handle->type == WINSYS_HANDLE_TYPE_FD) {
if (scanout) { if (scanout) {
@ -184,8 +187,8 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
return false; return false;
handle->handle = fd; handle->handle = fd;
handle->stride = rsrc->slices[0].line_stride; handle->stride = rsrc->layout.slices[0].line_stride;
handle->offset = rsrc->slices[0].offset; handle->offset = rsrc->layout.slices[0].offset;
return true; return true;
} }
} }
@ -311,7 +314,7 @@ panfrost_create_scanout_res(struct pipe_screen *screen,
/* Setup the mip tree given a particular modifier, possibly with checksumming */ /* Setup the mip tree given a particular modifier, possibly with checksumming */
static void static void
panfrost_setup_slices(struct panfrost_device *dev, panfrost_setup_layout(struct panfrost_device *dev,
struct panfrost_resource *pres, struct panfrost_resource *pres,
size_t *bo_size) size_t *bo_size)
{ {
@ -343,24 +346,23 @@ panfrost_setup_slices(struct panfrost_device *dev,
bool renderable = res->bind & bool renderable = res->bind &
(PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL) && (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL) &&
res->target != PIPE_BUFFER; res->target != PIPE_BUFFER;
bool afbc = drm_is_afbc(pres->modifier); bool afbc = drm_is_afbc(pres->layout.modifier);
bool tiled = pres->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; bool tiled = pres->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
bool linear = pres->modifier == DRM_FORMAT_MOD_LINEAR; bool linear = pres->layout.modifier == DRM_FORMAT_MOD_LINEAR;
bool should_align = renderable || tiled || afbc; bool should_align = renderable || tiled || afbc;
unsigned offset = 0; unsigned offset = 0;
unsigned size_2d = 0;
unsigned tile_h = 1, tile_w = 1, tile_shift = 0; unsigned tile_h = 1, tile_w = 1, tile_shift = 0;
if (tiled || afbc) { if (tiled || afbc) {
tile_w = panfrost_block_dim(pres->modifier, true, 0); tile_w = panfrost_block_dim(pres->layout.modifier, true, 0);
tile_h = panfrost_block_dim(pres->modifier, false, 0); tile_h = panfrost_block_dim(pres->layout.modifier, false, 0);
if (util_format_is_compressed(pres->internal_format)) if (util_format_is_compressed(pres->internal_format))
tile_shift = 2; tile_shift = 2;
} }
for (unsigned l = 0; l <= res->last_level; ++l) { for (unsigned l = 0; l <= res->last_level; ++l) {
struct panfrost_slice *slice = &pres->slices[l]; struct panfrost_slice *slice = &pres->layout.slices[l];
unsigned effective_width = width; unsigned effective_width = width;
unsigned effective_height = height; unsigned effective_height = height;
@ -399,11 +401,6 @@ panfrost_setup_slices(struct panfrost_device *dev,
slice->surface_stride = slice_one_size; slice->surface_stride = slice_one_size;
/* Report 2D size for 3D texturing */
if (l == 0)
size_2d = slice_one_size;
/* Compute AFBC sizes if necessary */ /* Compute AFBC sizes if necessary */
if (afbc) { if (afbc) {
slice->header_size = slice->header_size =
@ -431,20 +428,10 @@ panfrost_setup_slices(struct panfrost_device *dev,
assert(res->array_size); assert(res->array_size);
if (res->target != PIPE_TEXTURE_3D) { /* Arrays and cubemaps have the entire miptree duplicated */
/* Arrays and cubemaps have the entire miptree duplicated */ pres->layout.array_stride = ALIGN_POT(offset, 64);
if (bo_size)
pres->cubemap_stride = ALIGN_POT(offset, 64); *bo_size = ALIGN_POT(pres->layout.array_stride * res->array_size, 4096);
if (bo_size)
*bo_size = ALIGN_POT(pres->cubemap_stride * res->array_size, 4096);
} else {
/* 3D strides across the 2D layers */
assert(res->array_size == 1);
pres->cubemap_stride = size_2d;
if (bo_size)
*bo_size = ALIGN_POT(offset, 4096);
}
} }
/* Based on the usage, determine if it makes sense to use u-inteleaved tiling. /* Based on the usage, determine if it makes sense to use u-inteleaved tiling.
@ -550,16 +537,16 @@ static void
panfrost_resource_setup(struct panfrost_device *dev, struct panfrost_resource *pres, panfrost_resource_setup(struct panfrost_device *dev, struct panfrost_resource *pres,
size_t *bo_size, uint64_t modifier) size_t *bo_size, uint64_t modifier)
{ {
pres->modifier = (modifier != DRM_FORMAT_MOD_INVALID) ? modifier : pres->layout.modifier = (modifier != DRM_FORMAT_MOD_INVALID) ? modifier :
panfrost_best_modifier(dev, pres); panfrost_best_modifier(dev, pres);
pres->checksummed = (pres->base.bind & PIPE_BIND_RENDER_TARGET); pres->checksummed = (pres->base.bind & PIPE_BIND_RENDER_TARGET);
/* We can only switch tiled->linear if the resource isn't already /* We can only switch tiled->linear if the resource isn't already
* linear and if we control the modifier */ * linear and if we control the modifier */
pres->modifier_constant = !((pres->modifier != DRM_FORMAT_MOD_LINEAR) pres->modifier_constant = !((pres->layout.modifier != DRM_FORMAT_MOD_LINEAR)
&& (modifier == DRM_FORMAT_MOD_INVALID)); && (modifier == DRM_FORMAT_MOD_INVALID));
panfrost_setup_slices(dev, pres, bo_size); panfrost_setup_layout(dev, pres, bo_size);
} }
void void
@ -639,6 +626,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
so->base = *template; so->base = *template;
so->base.screen = screen; so->base.screen = screen;
so->internal_format = template->format; so->internal_format = template->format;
so->layout.dim = panfrost_translate_texture_dimension(template->target);
pipe_reference_init(&so->base.reference, 1); pipe_reference_init(&so->base.reference, 1);
@ -814,7 +802,7 @@ panfrost_ptr_map(struct pipe_context *pctx,
struct panfrost_bo *bo = rsrc->bo; struct panfrost_bo *bo = rsrc->bo;
/* Can't map tiled/compressed directly */ /* Can't map tiled/compressed directly */
if ((usage & PIPE_MAP_DIRECTLY) && rsrc->modifier != DRM_FORMAT_MOD_LINEAR) if ((usage & PIPE_MAP_DIRECTLY) && rsrc->layout.modifier != DRM_FORMAT_MOD_LINEAR)
return NULL; return NULL;
struct panfrost_transfer *transfer = rzalloc(pctx, struct panfrost_transfer); struct panfrost_transfer *transfer = rzalloc(pctx, struct panfrost_transfer);
@ -826,9 +814,9 @@ panfrost_ptr_map(struct pipe_context *pctx,
*out_transfer = &transfer->base; *out_transfer = &transfer->base;
/* We don't have s/w routines for AFBC, so use a staging texture */ /* We don't have s/w routines for AFBC, so use a staging texture */
if (drm_is_afbc(rsrc->modifier)) { if (drm_is_afbc(rsrc->layout.modifier)) {
struct panfrost_resource *staging = pan_alloc_staging(ctx, rsrc, level, box); struct panfrost_resource *staging = pan_alloc_staging(ctx, rsrc, level, box);
transfer->base.stride = staging->slices[0].line_stride; transfer->base.stride = staging->layout.slices[0].line_stride;
transfer->base.layer_stride = transfer->base.stride * box->height; transfer->base.layer_stride = transfer->base.stride * box->height;
transfer->staging.rsrc = &staging->base; transfer->staging.rsrc = &staging->base;
@ -845,7 +833,7 @@ panfrost_ptr_map(struct pipe_context *pctx,
* from a pending batch XXX */ * from a pending batch XXX */
panfrost_flush_batches_accessing_bo(ctx, rsrc->bo, true); panfrost_flush_batches_accessing_bo(ctx, rsrc->bo, true);
if ((usage & PIPE_MAP_READ) && rsrc->slices[level].initialized) { if ((usage & PIPE_MAP_READ) && rsrc->layout.slices[level].initialized) {
pan_blit_to_staging(pctx, transfer); pan_blit_to_staging(pctx, transfer);
panfrost_flush_batches_accessing_bo(ctx, staging->bo, true); panfrost_flush_batches_accessing_bo(ctx, staging->bo, true);
panfrost_bo_wait(staging->bo, INT64_MAX, false); panfrost_bo_wait(staging->bo, INT64_MAX, false);
@ -932,25 +920,25 @@ panfrost_ptr_map(struct pipe_context *pctx,
} }
} }
if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { if (rsrc->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
transfer->base.stride = box->width * bytes_per_pixel; transfer->base.stride = box->width * bytes_per_pixel;
transfer->base.layer_stride = transfer->base.stride * box->height; transfer->base.layer_stride = transfer->base.stride * box->height;
transfer->map = ralloc_size(transfer, transfer->base.layer_stride * box->depth); transfer->map = ralloc_size(transfer, transfer->base.layer_stride * box->depth);
assert(box->depth == 1); assert(box->depth == 1);
if ((usage & PIPE_MAP_READ) && rsrc->slices[level].initialized) { if ((usage & PIPE_MAP_READ) && rsrc->layout.slices[level].initialized) {
panfrost_load_tiled_image( panfrost_load_tiled_image(
transfer->map, transfer->map,
bo->ptr.cpu + rsrc->slices[level].offset, bo->ptr.cpu + rsrc->layout.slices[level].offset,
box->x, box->y, box->width, box->height, box->x, box->y, box->width, box->height,
transfer->base.stride, transfer->base.stride,
rsrc->slices[level].line_stride, rsrc->layout.slices[level].line_stride,
rsrc->internal_format); rsrc->internal_format);
} }
return transfer->map; return transfer->map;
} else { } else {
assert (rsrc->modifier == DRM_FORMAT_MOD_LINEAR); assert (rsrc->layout.modifier == DRM_FORMAT_MOD_LINEAR);
/* Direct, persistent writes create holes in time for /* Direct, persistent writes create holes in time for
* caching... I don't know if this is actually possible but we * caching... I don't know if this is actually possible but we
@ -961,23 +949,22 @@ panfrost_ptr_map(struct pipe_context *pctx,
if ((usage & dpw) == dpw && rsrc->index_cache) if ((usage & dpw) == dpw && rsrc->index_cache)
return NULL; return NULL;
transfer->base.stride = rsrc->slices[level].line_stride; transfer->base.stride = rsrc->layout.slices[level].line_stride;
transfer->base.layer_stride = panfrost_get_layer_stride( transfer->base.layer_stride =
rsrc->slices, rsrc->base.target == PIPE_TEXTURE_3D, panfrost_get_layer_stride(&rsrc->layout, level);
rsrc->cubemap_stride, level);
/* By mapping direct-write, we're implicitly already /* By mapping direct-write, we're implicitly already
* initialized (maybe), so be conservative */ * initialized (maybe), so be conservative */
if (usage & PIPE_MAP_WRITE) { if (usage & PIPE_MAP_WRITE) {
rsrc->slices[level].initialized = true; rsrc->layout.slices[level].initialized = true;
panfrost_minmax_cache_invalidate(rsrc->index_cache, &transfer->base); panfrost_minmax_cache_invalidate(rsrc->index_cache, &transfer->base);
} }
return bo->ptr.cpu return bo->ptr.cpu
+ rsrc->slices[level].offset + rsrc->layout.slices[level].offset
+ transfer->base.box.z * transfer->base.layer_stride + transfer->base.box.z * transfer->base.layer_stride
+ transfer->base.box.y * rsrc->slices[level].line_stride + transfer->base.box.y * rsrc->layout.slices[level].line_stride
+ transfer->base.box.x * bytes_per_pixel; + transfer->base.box.x * bytes_per_pixel;
} }
} }
@ -1050,9 +1037,9 @@ panfrost_ptr_unmap(struct pipe_context *pctx,
struct panfrost_bo *bo = prsrc->bo; struct panfrost_bo *bo = prsrc->bo;
if (transfer->usage & PIPE_MAP_WRITE) { if (transfer->usage & PIPE_MAP_WRITE) {
prsrc->slices[transfer->level].initialized = true; prsrc->layout.slices[transfer->level].initialized = true;
if (prsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { if (prsrc->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
assert(transfer->box.depth == 1); assert(transfer->box.depth == 1);
if (panfrost_should_linear_convert(prsrc, transfer)) { if (panfrost_should_linear_convert(prsrc, transfer)) {
@ -1066,9 +1053,9 @@ panfrost_ptr_unmap(struct pipe_context *pctx,
} }
util_copy_rect( util_copy_rect(
bo->ptr.cpu + prsrc->slices[0].offset, bo->ptr.cpu + prsrc->layout.slices[0].offset,
prsrc->base.format, prsrc->base.format,
prsrc->slices[0].line_stride, prsrc->layout.slices[0].line_stride,
0, 0, 0, 0,
transfer->box.width, transfer->box.width,
transfer->box.height, transfer->box.height,
@ -1077,11 +1064,11 @@ panfrost_ptr_unmap(struct pipe_context *pctx,
0, 0); 0, 0);
} else { } else {
panfrost_store_tiled_image( panfrost_store_tiled_image(
bo->ptr.cpu + prsrc->slices[transfer->level].offset, bo->ptr.cpu + prsrc->layout.slices[transfer->level].offset,
trans->map, trans->map,
transfer->box.x, transfer->box.y, transfer->box.x, transfer->box.y,
transfer->box.width, transfer->box.height, transfer->box.width, transfer->box.height,
prsrc->slices[transfer->level].line_stride, prsrc->layout.slices[transfer->level].line_stride,
transfer->stride, transfer->stride,
prsrc->internal_format); prsrc->internal_format);
} }
@ -1116,7 +1103,7 @@ panfrost_ptr_flush_region(struct pipe_context *pctx,
transfer->box.x + box->x + box->width); transfer->box.x + box->x + box->width);
} else { } else {
unsigned level = transfer->level; unsigned level = transfer->level;
rsc->slices[level].initialized = true; rsc->layout.slices[level].initialized = true;
} }
} }
@ -1151,7 +1138,7 @@ panfrost_generate_mipmap(
assert(rsrc->bo); assert(rsrc->bo);
for (unsigned l = base_level + 1; l <= last_level; ++l) for (unsigned l = base_level + 1; l <= last_level; ++l)
rsrc->slices[l].initialized = false; rsrc->layout.slices[l].initialized = false;
/* Beyond that, we just delegate the hard stuff. */ /* Beyond that, we just delegate the hard stuff. */
@ -1167,15 +1154,16 @@ panfrost_generate_mipmap(
/* Computes the address to a texture at a particular slice */ /* Computes the address to a texture at a particular slice */
mali_ptr mali_ptr
panfrost_get_texture_address( panfrost_get_texture_address(struct panfrost_resource *rsrc,
struct panfrost_resource *rsrc, unsigned level, unsigned layer,
unsigned level, unsigned face, unsigned sample) unsigned sample)
{ {
bool is_3d = rsrc->base.target == PIPE_TEXTURE_3D; bool is_3d = rsrc->base.target == PIPE_TEXTURE_3D;
unsigned array_idx = is_3d ? 0 : layer;
unsigned surface_idx = is_3d ? layer : sample;
return rsrc->bo->ptr.gpu + return rsrc->bo->ptr.gpu +
panfrost_texture_offset(rsrc->slices, is_3d, panfrost_texture_offset(&rsrc->layout, level,
rsrc->cubemap_stride, array_idx, surface_idx);
level, face, sample);
} }
static void static void

View file

@ -52,14 +52,8 @@ struct panfrost_resource {
struct util_range valid_buffer_range; struct util_range valid_buffer_range;
/* Description of the mip levels */ /* Description of the resource layout */
struct panfrost_slice slices[MAX_MIP_LEVELS]; struct pan_image_layout layout;
/* Distance from tree to tree */
unsigned cubemap_stride;
/* DRM fourcc code: linear, 16x16 u-interleaved, AFBC */
uint64_t modifier;
/* Whether the modifier can be changed */ /* Whether the modifier can be changed */
bool modifier_constant; bool modifier_constant;
@ -101,9 +95,9 @@ pan_transfer(struct pipe_transfer *p)
} }
mali_ptr mali_ptr
panfrost_get_texture_address( panfrost_get_texture_address(struct panfrost_resource *rsrc,
struct panfrost_resource *rsrc, unsigned level, unsigned layer,
unsigned level, unsigned face, unsigned sample); unsigned sample);
void panfrost_resource_screen_init(struct pipe_screen *screen); void panfrost_resource_screen_init(struct pipe_screen *screen);

View file

@ -84,7 +84,7 @@ panfrost_sfbd_set_cbuf(
unsigned level = surf->u.tex.level; unsigned level = surf->u.tex.level;
unsigned first_layer = surf->u.tex.first_layer; unsigned first_layer = surf->u.tex.first_layer;
assert(surf->u.tex.last_layer == first_layer); assert(surf->u.tex.last_layer == first_layer);
signed row_stride = rsrc->slices[level].row_stride; signed row_stride = rsrc->layout.slices[level].row_stride;
mali_ptr base = panfrost_get_texture_address(rsrc, level, first_layer, 0); mali_ptr base = panfrost_get_texture_address(rsrc, level, first_layer, 0);
@ -94,9 +94,9 @@ panfrost_sfbd_set_cbuf(
fb->color_writeback.base = base; fb->color_writeback.base = base;
fb->color_writeback.row_stride = row_stride; fb->color_writeback.row_stride = row_stride;
if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) if (rsrc->layout.modifier == DRM_FORMAT_MOD_LINEAR)
fb->color_block_format = MALI_BLOCK_FORMAT_LINEAR; fb->color_block_format = MALI_BLOCK_FORMAT_LINEAR;
else if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { else if (rsrc->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
fb->color_block_format = MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED; fb->color_block_format = MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED;
} else { } else {
fprintf(stderr, "Invalid render modifier\n"); fprintf(stderr, "Invalid render modifier\n");
@ -114,12 +114,12 @@ panfrost_sfbd_set_zsbuf(
unsigned level = surf->u.tex.level; unsigned level = surf->u.tex.level;
assert(surf->u.tex.first_layer == 0); assert(surf->u.tex.first_layer == 0);
fb->zs_writeback.base = rsrc->bo->ptr.gpu + rsrc->slices[level].offset; fb->zs_writeback.base = rsrc->bo->ptr.gpu + rsrc->layout.slices[level].offset;
fb->zs_writeback.row_stride = rsrc->slices[level].row_stride; fb->zs_writeback.row_stride = rsrc->layout.slices[level].row_stride;
if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) if (rsrc->layout.modifier == DRM_FORMAT_MOD_LINEAR)
fb->zs_block_format = MALI_BLOCK_FORMAT_LINEAR; fb->zs_block_format = MALI_BLOCK_FORMAT_LINEAR;
else if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { else if (rsrc->layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
fb->zs_block_format = MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED; fb->zs_block_format = MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED;
} else { } else {
fprintf(stderr, "Invalid render modifier\n"); fprintf(stderr, "Invalid render modifier\n");
@ -230,7 +230,7 @@ panfrost_sfbd_fragment(struct panfrost_batch *batch, bool has_draws)
if (rsrc->checksummed) { if (rsrc->checksummed) {
unsigned level = surf->u.tex.level; unsigned level = surf->u.tex.level;
struct panfrost_slice *slice = &rsrc->slices[level]; struct panfrost_slice *slice = &rsrc->layout.slices[level];
params.crc_buffer.row_stride = slice->crc.stride; params.crc_buffer.row_stride = slice->crc.stride;
params.crc_buffer.base = bo->ptr.gpu + slice->crc.offset; params.crc_buffer.base = bo->ptr.gpu + slice->crc.offset;

View file

@ -316,21 +316,20 @@ midgard_load_emit_texture(struct pan_pool *pool, struct MALI_DRAW *draw,
* itself is for a 2D texture with array size 1 even for 3D/array * itself is for a 2D texture with array size 1 even for 3D/array
* textures, removing the need to separately key the blit shaders for * textures, removing the need to separately key the blit shaders for
* 2D and 3D variants */ * 2D and 3D variants */
panfrost_new_texture(pool->dev, texture.cpu,
image->width0, image->height0, unsigned offset =
MAX2(image->nr_samples, 1), 1, image->first_layer *
image->format, MALI_TEXTURE_DIMENSION_2D, panfrost_get_layer_stride(image->layout, image->first_level);
image->modifier,
image->first_level, image->last_level, panfrost_new_texture(pool->dev, image->layout, texture.cpu,
0, 0, image->width0, image->height0,
image->nr_samples, MAX2(image->nr_samples, 1), 1,
0, image->format, MALI_TEXTURE_DIMENSION_2D,
PAN_V6_SWIZZLE(R, G, B, A), image->first_level, image->last_level,
image->bo->ptr.gpu + image->first_layer * 0, 0,
panfrost_get_layer_stride(image->slices, image->nr_samples,
image->dim == MALI_TEXTURE_DIMENSION_3D, PAN_V6_SWIZZLE(R, G, B, A),
image->cubemap_stride, image->first_level), image->bo->ptr.gpu + offset, &payload);
image->slices, &payload);
pan_pack(sampler.cpu, MIDGARD_SAMPLER, cfg) pan_pack(sampler.cpu, MIDGARD_SAMPLER, cfg)
cfg.normalized_coordinates = false; cfg.normalized_coordinates = false;
@ -492,21 +491,19 @@ bifrost_load_emit_texture(struct pan_pool *pool, struct MALI_DRAW *draw,
.gpu = texture.gpu + MALI_BIFROST_TEXTURE_LENGTH, .gpu = texture.gpu + MALI_BIFROST_TEXTURE_LENGTH,
}; };
panfrost_new_texture(pool->dev, (void *)texture.cpu, unsigned offset =
image->first_layer *
panfrost_get_layer_stride(image->layout, image->first_level);
panfrost_new_texture(pool->dev, image->layout, texture.cpu,
image->width0, image->height0, image->width0, image->height0,
MAX2(image->nr_samples, 1), 1, MAX2(image->nr_samples, 1), 1,
image->format, MALI_TEXTURE_DIMENSION_2D, image->format, MALI_TEXTURE_DIMENSION_2D,
image->modifier,
image->first_level, image->last_level, image->first_level, image->last_level,
0, 0, 0, 0,
image->nr_samples, image->nr_samples,
0,
PAN_V6_SWIZZLE(R, G, B, A), PAN_V6_SWIZZLE(R, G, B, A),
image->bo->ptr.gpu + image->first_layer * image->bo->ptr.gpu + offset, &payload);
panfrost_get_layer_stride(image->slices,
image->dim == MALI_TEXTURE_DIMENSION_3D,
image->cubemap_stride, image->first_level),
image->slices, &payload);
pan_pack(sampler.cpu, BIFROST_SAMPLER, cfg) { pan_pack(sampler.cpu, BIFROST_SAMPLER, cfg) {
cfg.seamless_cube_map = false; cfg.seamless_cube_map = false;

View file

@ -79,9 +79,8 @@ panfrost_modifier_to_layout(uint64_t modifier)
static bool static bool
panfrost_needs_explicit_stride(const struct panfrost_device *dev, panfrost_needs_explicit_stride(const struct panfrost_device *dev,
uint64_t modifier, const struct pan_image_layout *layout,
enum pipe_format format, enum pipe_format format,
struct panfrost_slice *slices,
uint16_t width, uint16_t width,
unsigned first_level, unsigned first_level,
unsigned last_level) unsigned last_level)
@ -90,14 +89,14 @@ panfrost_needs_explicit_stride(const struct panfrost_device *dev,
if (dev->quirks & IS_BIFROST) if (dev->quirks & IS_BIFROST)
return true; return true;
if (modifier != DRM_FORMAT_MOD_LINEAR) if (layout->modifier != DRM_FORMAT_MOD_LINEAR)
return false; return false;
unsigned bytes_per_block = util_format_get_blocksize(format); unsigned bytes_per_block = util_format_get_blocksize(format);
unsigned block_w = util_format_get_blockwidth(format); unsigned block_w = util_format_get_blockwidth(format);
for (unsigned l = first_level; l <= last_level; ++l) { for (unsigned l = first_level; l <= last_level; ++l) {
unsigned actual = slices[l].line_stride; unsigned actual = layout->slices[l].line_stride;
unsigned expected = unsigned expected =
DIV_ROUND_UP(u_minify(width, l), block_w) * DIV_ROUND_UP(u_minify(width, l), block_w) *
bytes_per_block; bytes_per_block;
@ -269,34 +268,22 @@ panfrost_block_dim(uint64_t modifier, bool width, unsigned plane)
} }
static uint64_t static uint64_t
panfrost_get_surface_strides(struct panfrost_slice *slices, panfrost_get_surface_strides(const struct pan_image_layout *layout,
const struct util_format_description *desc, unsigned l)
enum mali_texture_dimension dim,
uint64_t modifier,
unsigned width, unsigned height,
unsigned l, unsigned cube_stride)
{ {
bool is_3d = dim == MALI_TEXTURE_DIMENSION_3D; return ((uint64_t)layout->slices[l].surface_stride << 32) |
layout->slices[l].row_stride;
unsigned line_stride = slices[l].row_stride;
unsigned layer_stride =
panfrost_get_layer_stride(slices, is_3d, cube_stride, l);
return ((uint64_t)layer_stride << 32) | line_stride;
} }
static mali_ptr static mali_ptr
panfrost_get_surface_pointer(mali_ptr base, struct panfrost_slice *slices, panfrost_get_surface_pointer(const struct pan_image_layout *layout,
enum mali_texture_dimension dim, enum mali_texture_dimension dim,
unsigned l, unsigned w, unsigned f, unsigned s, mali_ptr base,
unsigned cube_stride) unsigned l, unsigned w, unsigned f, unsigned s)
{ {
unsigned face_mult = dim == MALI_TEXTURE_DIMENSION_CUBE ? 6 : 1; unsigned face_mult = dim == MALI_TEXTURE_DIMENSION_CUBE ? 6 : 1;
bool is_3d = dim == MALI_TEXTURE_DIMENSION_3D;
return base + return base + panfrost_texture_offset(layout, l, w * face_mult + f, s);
panfrost_texture_offset(slices, is_3d, cube_stride,
l, w * face_mult + f, s);
} }
struct panfrost_surface_iter { struct panfrost_surface_iter {
@ -357,28 +344,27 @@ panfrost_surface_iter_next(const struct panfrost_device *dev,
static void static void
panfrost_emit_texture_payload(const struct panfrost_device *dev, panfrost_emit_texture_payload(const struct panfrost_device *dev,
const struct pan_image_layout *layout,
mali_ptr *payload, mali_ptr *payload,
const struct util_format_description *desc, const struct util_format_description *desc,
enum mali_texture_dimension dim, enum mali_texture_dimension dim,
uint64_t modifier,
unsigned width, unsigned height,
unsigned first_level, unsigned last_level, unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer, unsigned first_layer, unsigned last_layer,
unsigned nr_samples, unsigned nr_samples,
unsigned cube_stride,
bool manual_stride, bool manual_stride,
mali_ptr base, mali_ptr base)
struct panfrost_slice *slices)
{ {
base |= panfrost_compression_tag(dev, desc, dim, modifier); base |= panfrost_compression_tag(dev, desc, dim, layout->modifier);
/* Inject the addresses in, interleaving array indices, mip levels, /* Inject the addresses in, interleaving array indices, mip levels,
* cube faces, and strides in that order */ * cube faces, and strides in that order */
unsigned first_face = 0, last_face = 0; unsigned first_face = 0, last_face = 0;
if (dim == MALI_TEXTURE_DIMENSION_CUBE) if (dim == MALI_TEXTURE_DIMENSION_CUBE) {
panfrost_adjust_cube_dimensions(&first_face, &last_face, &first_layer, &last_layer); panfrost_adjust_cube_dimensions(&first_face, &last_face,
&first_layer, &last_layer);
}
nr_samples = MAX2(nr_samples, 1); nr_samples = MAX2(nr_samples, 1);
@ -391,36 +377,31 @@ panfrost_emit_texture_payload(const struct panfrost_device *dev,
!panfrost_surface_iter_end(&iter); !panfrost_surface_iter_end(&iter);
panfrost_surface_iter_next(dev, &iter)) { panfrost_surface_iter_next(dev, &iter)) {
payload[idx++] = payload[idx++] =
panfrost_get_surface_pointer(base, slices, dim, panfrost_get_surface_pointer(layout, dim, base,
iter.level, iter.layer, iter.level, iter.layer,
iter.face, iter.sample, iter.face, iter.sample);
cube_stride);
if (!manual_stride) if (!manual_stride)
continue; continue;
payload[idx++] = payload[idx++] =
panfrost_get_surface_strides(slices, desc, dim, panfrost_get_surface_strides(layout, iter.level);
modifier, width, height,
iter.level, cube_stride);
} }
} }
void void
panfrost_new_texture(const struct panfrost_device *dev, panfrost_new_texture(const struct panfrost_device *dev,
const struct pan_image_layout *layout,
void *out, void *out,
uint16_t width, uint16_t height, uint16_t width, uint16_t height,
uint16_t depth, uint16_t array_size, uint16_t depth, uint16_t array_size,
enum pipe_format format, enum pipe_format format,
enum mali_texture_dimension dim, enum mali_texture_dimension dim,
uint64_t modifier,
unsigned first_level, unsigned last_level, unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer, unsigned first_layer, unsigned last_layer,
unsigned nr_samples, unsigned nr_samples,
unsigned cube_stride,
unsigned swizzle, unsigned swizzle,
mali_ptr base, mali_ptr base,
struct panfrost_slice *slices,
const struct panfrost_ptr *payload) const struct panfrost_ptr *payload)
{ {
const struct util_format_description *desc = const struct util_format_description *desc =
@ -428,22 +409,17 @@ panfrost_new_texture(const struct panfrost_device *dev,
bool is_bifrost = dev->quirks & IS_BIFROST; bool is_bifrost = dev->quirks & IS_BIFROST;
bool manual_stride = bool manual_stride =
panfrost_needs_explicit_stride(dev, modifier, format, slices, panfrost_needs_explicit_stride(dev, layout, format, width,
width, first_level, last_level); first_level, last_level);
panfrost_emit_texture_payload(dev, panfrost_emit_texture_payload(dev, layout,
payload->cpu, payload->cpu,
desc, desc, dim,
dim,
modifier,
width, height,
first_level, last_level, first_level, last_level,
first_layer, last_layer, first_layer, last_layer,
nr_samples, nr_samples,
cube_stride,
manual_stride, manual_stride,
base, base);
slices);
if (is_bifrost) { if (is_bifrost) {
pan_pack(out, BIFROST_TEXTURE, cfg) { pan_pack(out, BIFROST_TEXTURE, cfg) {
@ -456,7 +432,8 @@ panfrost_new_texture(const struct panfrost_device *dev,
else else
cfg.sample_count = MAX2(nr_samples, 1); cfg.sample_count = MAX2(nr_samples, 1);
cfg.swizzle = swizzle; cfg.swizzle = swizzle;
cfg.texel_ordering = panfrost_modifier_to_layout(modifier); cfg.texel_ordering =
panfrost_modifier_to_layout(layout->modifier);
cfg.levels = last_level - first_level + 1; cfg.levels = last_level - first_level + 1;
cfg.array_size = array_size; cfg.array_size = array_size;
cfg.surfaces = payload->gpu; cfg.surfaces = payload->gpu;
@ -477,7 +454,8 @@ panfrost_new_texture(const struct panfrost_device *dev,
cfg.array_size = array_size; cfg.array_size = array_size;
cfg.format = panfrost_pipe_format_v6[format].hw; cfg.format = panfrost_pipe_format_v6[format].hw;
cfg.dimension = dim; cfg.dimension = dim;
cfg.texel_ordering = panfrost_modifier_to_layout(modifier); cfg.texel_ordering =
panfrost_modifier_to_layout(layout->modifier);
cfg.manual_stride = manual_stride; cfg.manual_stride = manual_stride;
cfg.levels = last_level - first_level + 1; cfg.levels = last_level - first_level + 1;
cfg.swizzle = swizzle; cfg.swizzle = swizzle;
@ -511,17 +489,24 @@ panfrost_compute_checksum_size(
} }
unsigned unsigned
panfrost_get_layer_stride(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level) panfrost_get_layer_stride(const struct pan_image_layout *layout,
unsigned level)
{ {
return is_3d ? slices[level].surface_stride : cube_stride; if (layout->dim == MALI_TEXTURE_DIMENSION_3D)
return layout->slices[level].surface_stride;
return layout->array_stride;
} }
/* Computes the offset into a texture at a particular level/face. Add to /* Computes the offset into a texture at a particular level/face. Add to
* the base address of a texture to get the address to that level/face */ * the base address of a texture to get the address to that level/face */
unsigned unsigned
panfrost_texture_offset(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level, unsigned face, unsigned sample) panfrost_texture_offset(const struct pan_image_layout *layout,
unsigned level, unsigned array_idx,
unsigned surface_idx)
{ {
unsigned layer_stride = panfrost_get_layer_stride(slices, is_3d, cube_stride, level); return layout->slices[level].offset +
return slices[level].offset + (face * layer_stride) + (sample * slices[level].surface_stride); (array_idx * layout->array_stride) +
(surface_idx * layout->slices[level].surface_stride);
} }

View file

@ -59,6 +59,13 @@ struct panfrost_slice {
bool initialized; bool initialized;
}; };
struct pan_image_layout {
uint64_t modifier;
enum mali_texture_dimension dim;
struct panfrost_slice slices[MAX_MIP_LEVELS];
unsigned array_stride;
};
struct pan_image { struct pan_image {
/* Format and size */ /* Format and size */
uint16_t width0, height0, depth0, array_size; uint16_t width0, height0, depth0, array_size;
@ -68,9 +75,7 @@ struct pan_image {
unsigned first_layer, last_layer; unsigned first_layer, last_layer;
unsigned nr_samples; unsigned nr_samples;
struct panfrost_bo *bo; struct panfrost_bo *bo;
struct panfrost_slice *slices; const struct pan_image_layout *layout;
unsigned cubemap_stride;
uint64_t modifier;
}; };
unsigned unsigned
@ -102,26 +107,27 @@ panfrost_estimate_texture_payload_size(
void void
panfrost_new_texture(const struct panfrost_device *dev, panfrost_new_texture(const struct panfrost_device *dev,
const struct pan_image_layout *layout,
void *out, void *out,
uint16_t width, uint16_t height, uint16_t width, uint16_t height,
uint16_t depth, uint16_t array_size, uint16_t depth, uint16_t array_size,
enum pipe_format format, enum pipe_format format,
enum mali_texture_dimension dim, enum mali_texture_dimension dim,
uint64_t modifier,
unsigned first_level, unsigned last_level, unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer, unsigned first_layer, unsigned last_layer,
unsigned nr_samples, unsigned nr_samples,
unsigned cube_stride,
unsigned swizzle, unsigned swizzle,
mali_ptr base, mali_ptr base,
struct panfrost_slice *slices,
const struct panfrost_ptr *payload); const struct panfrost_ptr *payload);
unsigned unsigned
panfrost_get_layer_stride(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level); panfrost_get_layer_stride(const struct pan_image_layout *layout,
unsigned level);
unsigned unsigned
panfrost_texture_offset(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level, unsigned face, unsigned sample); panfrost_texture_offset(const struct pan_image_layout *layout,
unsigned level, unsigned array_idx,
unsigned surface_idx);
/* Formats */ /* Formats */