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:

committed by
Marge Bot

parent
051d62cf04
commit
9d0ad7fd2e
@@ -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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user