panfrost: Patch the gallium driver to use pan_image_layout_init()

Now that we have a generic implementation, we can use it and get rid
of panfrost_setup_layout().

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/10033>
This commit is contained in:
Boris Brezillon
2021-03-26 11:14:28 +01:00
committed by Marge Bot
parent 051d62cf04
commit 9d0ad7fd2e

View File

@@ -78,44 +78,39 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
pipe_reference_init(&prsc->reference, 1);
prsc->screen = pscreen;
rsc->image.data.bo = panfrost_bo_import(dev, whandle->handle);
rsc->image.layout.format = templat->format;
rsc->image.layout.modifier = (whandle->modifier == DRM_FORMAT_MOD_INVALID) ?
DRM_FORMAT_MOD_LINEAR : whandle->modifier;
rsc->image.layout.dim = panfrost_translate_texture_dimension(templat->target);
rsc->modifier_constant = true;
rsc->image.layout.slices[0].line_stride = whandle->stride;
rsc->image.layout.slices[0].row_stride = whandle->stride;
rsc->image.layout.width = prsc->width0;
rsc->image.layout.height = prsc->height0;
rsc->image.layout.depth = prsc->depth0;
rsc->image.layout.nr_samples = prsc->nr_samples;
rsc->image.layout.array_size = prsc->array_size;
rsc->image.layout.data_size = rsc->image.data.bo->size;
uint64_t mod = whandle->modifier == DRM_FORMAT_MOD_INVALID ?
DRM_FORMAT_MOD_LINEAR : whandle->modifier;
enum mali_texture_dimension dim =
panfrost_translate_texture_dimension(templat->target);
enum pan_image_crc_mode crc_mode =
panfrost_should_checksum(dev, rsc) ?
PAN_IMAGE_CRC_OOB : PAN_IMAGE_CRC_NONE;
struct pan_image_explicit_layout explicit_layout = {
.offset = whandle->offset,
.line_stride = whandle->stride,
};
if (rsc->image.layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||
drm_is_afbc(rsc->image.layout.modifier)) {
unsigned tile_h = panfrost_block_dim(rsc->image.layout.modifier, false, 0);
bool valid = pan_image_layout_init(dev, &rsc->image.layout, mod,
templat->format, dim,
prsc->width0, prsc->height0,
prsc->depth0, prsc->array_size,
MAX2(prsc->nr_samples, 1), 1,
crc_mode, &explicit_layout);
if (util_format_is_compressed(rsc->image.layout.format))
tile_h >>= 2;
rsc->image.layout.slices[0].row_stride *= tile_h;
if (!valid) {
ralloc_free(rsc);
return NULL;
}
rsc->image.layout.slices[0].offset = whandle->offset;
rsc->image.data.bo = panfrost_bo_import(dev, whandle->handle);
if (rsc->image.layout.crc_mode == PAN_IMAGE_CRC_OOB)
rsc->image.crc.bo = panfrost_bo_create(dev, rsc->image.layout.crc_size, 0);
rsc->modifier_constant = true;
rsc->state.slices[0].data_valid = true;
panfrost_resource_set_damage_region(NULL, &rsc->base, 0, NULL);
if (panfrost_should_checksum(dev, rsc)) {
unsigned size =
panfrost_compute_checksum_size(&rsc->image.layout.slices[0],
templat->width0,
templat->height0);
rsc->image.crc.bo = panfrost_bo_create(dev, size, 0);
rsc->image.layout.crc_mode = PAN_IMAGE_CRC_OOB;
}
/* If we import an AFBC resource, it should be in a format that's
* supported, otherwise we don't know if the fixup is expected to be
* applied or not. In practice that's not a problem if the buffer has
@@ -126,23 +121,6 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
assert(!drm_is_afbc(whandle->modifier) ||
!panfrost_afbc_format_needs_fixup(dev, rsc->image.layout.format));
if (drm_is_afbc(whandle->modifier)) {
unsigned tile_w =
panfrost_block_dim(whandle->modifier, true, 0);
unsigned tile_h =
panfrost_block_dim(whandle->modifier, false, 0);
rsc->image.layout.slices[0].afbc.header_size =
panfrost_afbc_header_size(templat->width0, templat->height0);
rsc->image.layout.slices[0].afbc.row_stride =
DIV_ROUND_UP(templat->width0, tile_w) *
AFBC_HEADER_BYTES_PER_TILE;
rsc->image.layout.slices[0].afbc.body_size =
rsc->image.layout.slices[0].row_stride *
DIV_ROUND_UP(templat->height0, tile_h);
}
if (dev->ro) {
rsc->scanout =
renderonly_create_gpu_import_for_resource(prsc, dev->ro, NULL);
@@ -332,161 +310,6 @@ panfrost_create_scanout_res(struct pipe_screen *screen,
return res;
}
/* Setup the mip tree given a particular modifier, possibly with checksumming */
static void
panfrost_setup_layout(struct panfrost_device *dev,
struct panfrost_resource *pres,
size_t *bo_size)
{
struct pipe_resource *res = &pres->base;
unsigned width = res->width0;
unsigned height = res->height0;
unsigned depth = res->depth0;
unsigned bytes_per_pixel = util_format_get_blocksize(pres->image.layout.format);
pres->image.layout.width = width;
pres->image.layout.height = height;
pres->image.layout.depth = height;
pres->image.layout.array_size = res->array_size;
/* MSAA is implemented as a 3D texture with z corresponding to the
* sample #, horrifyingly enough */
unsigned nr_samples = MAX2(res->nr_samples, 1);
pres->image.layout.nr_samples = nr_samples;
assert(depth == 1 || nr_samples == 1);
/* Tiled operates blockwise; linear is packed. Also, anything
* we render to has to be tile-aligned. Maybe not strictly
* necessary, but we're not *that* pressed for memory and it
* makes code a lot simpler */
bool renderable = res->bind &
(PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL) &&
res->target != PIPE_BUFFER;
bool afbc = drm_is_afbc(pres->image.layout.modifier);
bool tiled = pres->image.layout.modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
bool linear = pres->image.layout.modifier == DRM_FORMAT_MOD_LINEAR;
bool should_align = renderable || tiled || afbc;
bool is_3d = res->target == PIPE_TEXTURE_3D;
unsigned oob_crc_offset = 0;
unsigned offset = 0;
unsigned tile_h = 1, tile_w = 1, tile_shift = 0;
if (tiled || afbc) {
tile_w = panfrost_block_dim(pres->image.layout.modifier, true, 0);
tile_h = panfrost_block_dim(pres->image.layout.modifier, false, 0);
if (util_format_is_compressed(pres->image.layout.format))
tile_shift = 2;
}
for (unsigned l = 0; l <= res->last_level; ++l) {
struct pan_image_slice_layout *slice = &pres->image.layout.slices[l];
unsigned effective_width = width;
unsigned effective_height = height;
unsigned effective_depth = depth;
if (should_align) {
effective_width = ALIGN_POT(effective_width, tile_w) >> tile_shift;
effective_height = ALIGN_POT(effective_height, tile_h);
/* We don't need to align depth */
}
/* Align levels to cache-line as a performance improvement for
* linear/tiled and as a requirement for AFBC */
offset = ALIGN_POT(offset, 64);
slice->offset = offset;
/* Compute the would-be stride */
unsigned stride = bytes_per_pixel * effective_width;
/* On Bifrost, pixel lines have to be aligned on 64 bytes otherwise
* we end up with DATA_INVALID faults. That doesn't seem to be
* mandatory on Midgard, but we keep the alignment for performance.
*/
if (linear)
stride = ALIGN_POT(stride, 64);
slice->line_stride = stride;
slice->row_stride = stride * (tile_h >> tile_shift);
unsigned slice_one_size = slice->line_stride * effective_height;
/* Compute AFBC sizes if necessary */
if (afbc) {
slice->afbc.header_size =
panfrost_afbc_header_size(width, height);
/* Stride between two rows of AFBC headers */
slice->afbc.row_stride =
(effective_width / tile_w) *
AFBC_HEADER_BYTES_PER_TILE;
/* AFBC body size */
slice->afbc.body_size = slice_one_size;
/* 3D AFBC resources have all headers placed at the
* beginning instead of having them split per depth
* level
*/
if (is_3d) {
slice->afbc.surface_stride =
slice->afbc.header_size;
slice->afbc.header_size *= effective_depth;
slice->afbc.body_size *= effective_depth;
offset += slice->afbc.header_size;
} else {
slice_one_size += slice->afbc.header_size;
slice->afbc.surface_stride = slice_one_size;
}
}
unsigned slice_full_size =
slice_one_size * effective_depth * nr_samples;
slice->surface_stride = slice_one_size;
/* Compute AFBC sizes if necessary */
offset += slice_full_size;
/* Add a checksum region if necessary */
if (pres->image.layout.crc_mode != PAN_IMAGE_CRC_NONE) {
unsigned size = panfrost_compute_checksum_size(
slice, width, height);
if (pres->image.layout.crc_mode == PAN_IMAGE_CRC_INBAND) {
slice->crc.offset = offset;
offset += size;
} else {
slice->crc.offset = oob_crc_offset;
oob_crc_offset += size;
}
}
width = u_minify(width, 1);
height = u_minify(height, 1);
depth = u_minify(depth, 1);
}
assert(res->array_size);
/* Arrays and cubemaps have the entire miptree duplicated */
pres->image.layout.array_stride = ALIGN_POT(offset, 64);
pres->image.layout.data_size =
ALIGN_POT(pres->image.layout.array_stride * res->array_size, 4096);
pres->image.layout.crc_size = oob_crc_offset;
if (bo_size)
*bo_size = pres->image.layout.data_size;
}
static inline bool
panfrost_is_2d(const struct panfrost_resource *pres)
{
@@ -502,7 +325,9 @@ panfrost_is_2d(const struct panfrost_resource *pres)
* On platforms where it is supported, AFBC is even better. */
static bool
panfrost_should_afbc(struct panfrost_device *dev, const struct panfrost_resource *pres)
panfrost_should_afbc(struct panfrost_device *dev,
const struct panfrost_resource *pres,
enum pipe_format fmt)
{
/* AFBC resources may be rendered to, textured from, or shared across
* processes, but may not be used as e.g buffers */
@@ -527,7 +352,7 @@ panfrost_should_afbc(struct panfrost_device *dev, const struct panfrost_resource
return false;
/* Only a small selection of formats are AFBC'able */
if (!panfrost_format_supports_afbc(dev, pres->image.layout.format))
if (!panfrost_format_supports_afbc(dev, fmt))
return false;
/* AFBC does not support layered (GLES3 style) multisampling. Use
@@ -561,7 +386,7 @@ panfrost_should_afbc(struct panfrost_device *dev, const struct panfrost_resource
* share the buffer we can fake those formats since we're in control
* of the format/swizzle we apply to the textures/RTs.
*/
if (panfrost_afbc_format_needs_fixup(dev, pres->image.layout.format) &&
if (panfrost_afbc_format_needs_fixup(dev, fmt) &&
(pres->base.bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)))
return false;
@@ -571,7 +396,9 @@ panfrost_should_afbc(struct panfrost_device *dev, const struct panfrost_resource
}
static bool
panfrost_should_tile(struct panfrost_device *dev, const struct panfrost_resource *pres)
panfrost_should_tile(struct panfrost_device *dev,
const struct panfrost_resource *pres,
enum pipe_format fmt)
{
const unsigned valid_binding =
PIPE_BIND_DEPTH_STENCIL |
@@ -582,7 +409,7 @@ panfrost_should_tile(struct panfrost_device *dev, const struct panfrost_resource
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED;
unsigned bpp = util_format_get_blocksizebits(pres->image.layout.format);
unsigned bpp = util_format_get_blocksizebits(fmt);
bool is_sane_bpp =
bpp == 8 || bpp == 16 || bpp == 24 || bpp == 32 ||
@@ -597,9 +424,10 @@ panfrost_should_tile(struct panfrost_device *dev, const struct panfrost_resource
static uint64_t
panfrost_best_modifier(struct panfrost_device *dev,
const struct panfrost_resource *pres)
const struct panfrost_resource *pres,
enum pipe_format fmt)
{
if (panfrost_should_afbc(dev, pres)) {
if (panfrost_should_afbc(dev, pres, fmt)) {
uint64_t afbc =
AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
AFBC_FORMAT_MOD_SPARSE;
@@ -608,7 +436,7 @@ panfrost_best_modifier(struct panfrost_device *dev,
afbc |= AFBC_FORMAT_MOD_YTR;
return DRM_FORMAT_MOD_ARM_AFBC(afbc);
} else if (panfrost_should_tile(dev, pres))
} else if (panfrost_should_tile(dev, pres, fmt))
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
else
return DRM_FORMAT_MOD_LINEAR;
@@ -633,26 +461,41 @@ panfrost_should_checksum(const struct panfrost_device *dev, const struct panfros
}
static void
panfrost_resource_setup(struct panfrost_device *dev, struct panfrost_resource *pres,
size_t *bo_size, uint64_t modifier)
panfrost_resource_setup(struct panfrost_device *dev,
struct panfrost_resource *pres,
uint64_t modifier, enum pipe_format fmt)
{
pres->image.layout.modifier = (modifier != DRM_FORMAT_MOD_INVALID) ? modifier :
panfrost_best_modifier(dev, pres);
pres->image.layout.crc_mode = panfrost_should_checksum(dev, pres) ?
PAN_IMAGE_CRC_INBAND : PAN_IMAGE_CRC_NONE;
uint64_t chosen_mod = modifier != DRM_FORMAT_MOD_INVALID ?
modifier : panfrost_best_modifier(dev, pres, fmt);
enum pan_image_crc_mode crc_mode =
panfrost_should_checksum(dev, pres) ?
PAN_IMAGE_CRC_INBAND : PAN_IMAGE_CRC_NONE;
enum mali_texture_dimension dim =
panfrost_translate_texture_dimension(pres->base.target);
/* We can only switch tiled->linear if the resource isn't already
* linear and if we control the modifier */
pres->modifier_constant = !((pres->image.layout.modifier != DRM_FORMAT_MOD_LINEAR)
&& (modifier == DRM_FORMAT_MOD_INVALID));
pres->modifier_constant =
!(chosen_mod != DRM_FORMAT_MOD_LINEAR &&
modifier == DRM_FORMAT_MOD_INVALID);
/* Z32_S8X24 variants are actually stored in 2 planes (one per
* component), we have to adjust the format on the first plane.
*/
if (pres->image.layout.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
pres->image.layout.format = PIPE_FORMAT_Z32_FLOAT;
if (fmt == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
fmt = PIPE_FORMAT_Z32_FLOAT;
panfrost_setup_layout(dev, pres, bo_size);
ASSERTED bool valid =
pan_image_layout_init(dev, &pres->image.layout,
chosen_mod, fmt, dim,
pres->base.width0,
pres->base.height0,
pres->base.depth0,
pres->base.array_size,
MAX2(pres->base.nr_samples, 1),
pres->base.last_level + 1,
crc_mode, NULL);
assert(valid);
}
static void
@@ -743,19 +586,17 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
struct panfrost_resource *so = rzalloc(screen, struct panfrost_resource);
so->base = *template;
so->base.screen = screen;
so->image.layout.format = template->format;
so->image.layout.dim = panfrost_translate_texture_dimension(template->target);
pipe_reference_init(&so->base.reference, 1);
util_range_init(&so->valid_buffer_range);
size_t bo_size;
panfrost_resource_setup(dev, so, &bo_size, modifier);
panfrost_resource_setup(dev, so, modifier, template->format);
/* We create a BO immediately but don't bother mapping, since we don't
* care to map e.g. FBOs which the CPU probably won't touch */
so->image.data.bo = panfrost_bo_create(dev, bo_size, PAN_BO_DELAY_MMAP);
so->image.data.bo =
panfrost_bo_create(dev, so->image.layout.data_size, PAN_BO_DELAY_MMAP);
if (drm_is_afbc(so->image.layout.modifier))
panfrost_resource_init_afbc_headers(so);
@@ -1145,7 +986,8 @@ pan_resource_modifier_convert(struct panfrost_context *ctx,
rsrc->image.data.bo = tmp_rsrc->image.data.bo;
panfrost_bo_reference(rsrc->image.data.bo);
panfrost_resource_setup(pan_device(ctx->base.screen), rsrc, NULL, modifier);
panfrost_resource_setup(pan_device(ctx->base.screen), rsrc, modifier,
blit.dst.format);
pipe_resource_reference(&tmp_prsrc, NULL);
}
@@ -1207,7 +1049,8 @@ panfrost_ptr_unmap(struct pipe_context *pctx,
if (prsrc->image.crc.bo)
panfrost_bo_unreference(prsrc->image.crc.bo);
panfrost_resource_setup(dev, prsrc, NULL, DRM_FORMAT_MOD_LINEAR);
panfrost_resource_setup(dev, prsrc, DRM_FORMAT_MOD_LINEAR,
prsrc->image.layout.format);
prsrc->image.data.bo = pan_resource(trans->staging.rsrc)->image.data.bo;
panfrost_bo_reference(prsrc->image.data.bo);
@@ -1231,12 +1074,12 @@ panfrost_ptr_unmap(struct pipe_context *pctx,
assert(transfer->box.depth == 1);
if (panfrost_should_linear_convert(prsrc, transfer)) {
size_t bo_size;
panfrost_resource_setup(dev, prsrc, &bo_size, DRM_FORMAT_MOD_LINEAR);
if (bo_size > bo->size) {
panfrost_resource_setup(dev, prsrc, DRM_FORMAT_MOD_LINEAR,
prsrc->image.layout.format);
if (prsrc->image.layout.data_size > bo->size) {
panfrost_bo_unreference(bo);
bo = prsrc->image.data.bo = panfrost_bo_create(dev, bo_size, 0);
bo = prsrc->image.data.bo =
panfrost_bo_create(dev, prsrc->image.layout.data_size, 0);
assert(bo);
}