panfrost: Use modifier instead of layout throughout

Instead of converting back and forth we should stick with fourcc codes
as the canonical layout definition. Furthermore modifiers allow all the
variants of AFBC to be encoded canonically, whereas the previous enum
does not (info about YTR is encoded out of band, for instance).

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tested-by: Icecream95 <ixn@keemail.me>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6159>
This commit is contained in:
Alyssa Rosenzweig 2020-07-22 10:23:50 -04:00
parent 6fed69cde2
commit 965537df2a
11 changed files with 97 additions and 77 deletions

View File

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

View File

@ -944,7 +944,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
}
so->texture_bo = prsrc->bo->gpu;
so->layout = prsrc->layout;
so->modifier = prsrc->modifier;
unsigned char user_swizzle[4] = {
so->base.swizzle_r,
@ -989,7 +989,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
so->base.u.tex.first_layer,
so->base.u.tex.last_layer,
texture->nr_samples,
type, prsrc->layout);
type, prsrc->modifier);
so->bo = panfrost_bo_create(device, size, 0);
@ -999,7 +999,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
texture->width0, texture->height0,
depth, array_size,
format,
type, prsrc->layout,
type, prsrc->modifier,
so->base.u.tex.first_level,
so->base.u.tex.last_level,
so->base.u.tex.first_layer,
@ -1017,7 +1017,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
so->base.u.tex.first_layer,
so->base.u.tex.last_layer,
texture->nr_samples,
type, prsrc->layout);
type, prsrc->modifier);
size += sizeof(struct mali_texture_descriptor);
so->bo = panfrost_bo_create(device, size, 0);
@ -1027,7 +1027,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
texture->width0, texture->height0,
depth, array_size,
format,
type, prsrc->layout,
type, prsrc->modifier,
so->base.u.tex.first_level,
so->base.u.tex.last_level,
so->base.u.tex.first_layer,

View File

@ -274,7 +274,7 @@ struct panfrost_sampler_view {
struct panfrost_bo *bo;
struct bifrost_texture_descriptor *bifrost_descriptor;
mali_ptr texture_bo;
enum mali_texture_layout layout;
uint64_t modifier;
};
static inline struct panfrost_context *

View File

@ -845,7 +845,7 @@ panfrost_load_surface(struct panfrost_batch *batch, struct pipe_surface *surf, u
.depth0 = rsrc->base.depth0,
.format = format,
.type = type,
.layout = rsrc->layout,
.modifier = rsrc->modifier,
.array_size = rsrc->base.array_size,
.first_level = level,
.last_level = level,

View File

@ -227,9 +227,9 @@ panfrost_mfbd_set_cbuf(
else
rt->format.msaa = MALI_MSAA_SINGLE;
/* Now, we set the layout specific pieces */
/* Now, we set the modifier specific pieces */
if (rsrc->layout == MALI_TEXTURE_LINEAR) {
if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) {
if (is_bifrost) {
rt->format.unk4 = 0x1;
} else {
@ -239,7 +239,7 @@ panfrost_mfbd_set_cbuf(
rt->framebuffer = base;
rt->framebuffer_stride = stride / 16;
rt->layer_stride = layer_stride;
} else if (rsrc->layout == MALI_TEXTURE_TILED) {
} else if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
if (is_bifrost) {
rt->format.unk3 |= 0x8;
} else {
@ -249,7 +249,7 @@ panfrost_mfbd_set_cbuf(
rt->framebuffer = base;
rt->framebuffer_stride = stride;
rt->layer_stride = layer_stride;
} else if (rsrc->layout == MALI_TEXTURE_AFBC) {
} else if (drm_is_afbc(rsrc->modifier)) {
rt->format.block = MALI_BLOCK_AFBC;
unsigned header_size = rsrc->slices[level].header_size;
@ -260,18 +260,14 @@ panfrost_mfbd_set_cbuf(
rt->afbc.stride = 0;
rt->afbc.flags = MALI_AFBC_FLAGS;
unsigned components = util_format_get_nr_components(surf->format);
/* The "lossless colorspace transform" is lossy for R and RG formats */
if (components >= 3)
rt->afbc.flags |= MALI_AFBC_YTR;
if (rsrc->modifier & AFBC_FORMAT_MOD_YTR)
rt->afbc.flags |= MALI_AFBC_YTR;
/* TODO: The blob sets this to something nonzero, but it's not
* clear what/how to calculate/if it matters */
rt->framebuffer_stride = 0;
} else {
fprintf(stderr, "Invalid render layout (cbuf)");
assert(0);
unreachable("Invalid mod");
}
}
@ -296,7 +292,7 @@ panfrost_mfbd_set_zsbuf(
mali_ptr base = panfrost_get_texture_address(rsrc, level, first_layer, 0);
if (rsrc->layout == MALI_TEXTURE_AFBC) {
if (drm_is_afbc(rsrc->modifier)) {
/* The only Z/S format we can compress is Z24S8 or variants
* thereof (handled by the gallium frontend) */
assert(panfrost_is_z24s8_variant(surf->format));
@ -315,7 +311,9 @@ panfrost_mfbd_set_zsbuf(
fbx->ds_afbc.flags = MALI_AFBC_FLAGS;
fbx->ds_afbc.padding = 0x1000;
} else if (rsrc->layout == MALI_TEXTURE_LINEAR || rsrc->layout == MALI_TEXTURE_TILED) {
} else {
assert(rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED || rsrc->modifier == DRM_FORMAT_MOD_LINEAR);
/* TODO: Z32F(S8) support, which is always linear */
int stride = rsrc->slices[level].stride;
@ -328,7 +326,7 @@ panfrost_mfbd_set_zsbuf(
fbx->ds_linear.depth = base;
if (rsrc->layout == MALI_TEXTURE_LINEAR) {
if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) {
fbx->zs_block = MALI_BLOCK_LINEAR;
fbx->ds_linear.depth_stride = stride / 16;
fbx->ds_linear.depth_layer_stride = layer_stride;
@ -365,9 +363,6 @@ panfrost_mfbd_set_zsbuf(
fbx->ds_linear.stencil_stride = stencil_slice.stride;
fbx->ds_linear.stencil_layer_stride = stencil_layer_stride;
}
} else {
assert(0);
}
}

View File

@ -75,7 +75,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
rsc->bo = panfrost_bo_import(dev, whandle->handle);
rsc->internal_format = templat->format;
rsc->layout = MALI_TEXTURE_LINEAR;
rsc->modifier = DRM_FORMAT_MOD_LINEAR;
rsc->slices[0].stride = whandle->stride;
rsc->slices[0].offset = whandle->offset;
rsc->slices[0].initialized = true;
@ -234,7 +234,7 @@ panfrost_create_scanout_res(struct pipe_screen *screen,
return res;
}
/* Setup the mip tree given a particular layout, possibly with checksumming */
/* Setup the mip tree given a particular modifier, possibly with checksumming */
static void
panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size)
@ -265,8 +265,9 @@ panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size)
bool renderable = res->bind &
(PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL) &&
res->target != PIPE_BUFFER;
bool afbc = pres->layout == MALI_TEXTURE_AFBC;
bool tiled = pres->layout == MALI_TEXTURE_TILED;
bool afbc = drm_is_afbc(pres->modifier);
bool tiled = pres->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
bool linear = pres->modifier == DRM_FORMAT_MOD_LINEAR;
bool should_align = renderable || tiled;
/* We don't know how to specify a 2D stride for 3D textures */
@ -307,7 +308,7 @@ panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size)
stride /= 4;
/* ..but cache-line align it for performance */
if (can_align_stride && pres->layout == MALI_TEXTURE_LINEAR)
if (can_align_stride && linear)
stride = ALIGN_POT(stride, 64);
slice->stride = stride;
@ -410,10 +411,12 @@ panfrost_resource_create_bo(struct panfrost_device *dev, struct panfrost_resourc
pres->checksummed = can_checksum && should_checksum;
/* Set the layout appropriately */
/* Set the modifier appropriately */
assert(!(must_tile && !can_tile)); /* must_tile => can_tile */
pres->layout = ((can_tile && should_tile) || must_tile) ? MALI_TEXTURE_TILED : MALI_TEXTURE_LINEAR;
pres->layout_constant = must_tile || !can_tile;
pres->modifier = ((can_tile && should_tile) || must_tile) ?
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED :
DRM_FORMAT_MOD_LINEAR;
pres->modifier_constant = must_tile || !can_tile;
size_t bo_size;
@ -647,7 +650,7 @@ panfrost_transfer_map(struct pipe_context *pctx,
}
}
if (rsrc->layout != MALI_TEXTURE_LINEAR) {
if (rsrc->modifier != DRM_FORMAT_MOD_LINEAR) {
/* Non-linear resources need to be indirectly mapped */
if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
@ -659,9 +662,9 @@ panfrost_transfer_map(struct pipe_context *pctx,
assert(box->depth == 1);
if ((usage & PIPE_TRANSFER_READ) && rsrc->slices[level].initialized) {
if (rsrc->layout == MALI_TEXTURE_AFBC) {
if (drm_is_afbc(rsrc->modifier)) {
unreachable("Unimplemented: reads from AFBC");
} else if (rsrc->layout == MALI_TEXTURE_TILED) {
} else if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
panfrost_load_tiled_image(
transfer->map,
bo->cpu + rsrc->slices[level].offset,
@ -721,32 +724,32 @@ panfrost_transfer_unmap(struct pipe_context *pctx,
struct panfrost_bo *bo = prsrc->bo;
if (transfer->usage & PIPE_TRANSFER_WRITE) {
if (prsrc->layout == MALI_TEXTURE_AFBC) {
if (drm_is_afbc(prsrc->modifier)) {
unreachable("Unimplemented: writes to AFBC\n");
} else if (prsrc->layout == MALI_TEXTURE_TILED) {
} else if (prsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
assert(transfer->box.depth == 1);
/* Do we overwrite the entire resource? If so,
* we don't need an intermediate blit so it's a
* good time to switch the layout. */
* good time to switch the modifier. */
bool discards_content = prsrc->base.last_level == 0
&& transfer->box.width == prsrc->base.width0
&& transfer->box.height == prsrc->base.height0
&& transfer->box.x == 0
&& transfer->box.y == 0
&& !prsrc->layout_constant;
&& !prsrc->modifier_constant;
/* It also serves as a good heuristic for
* streaming textures (e.g. in video players),
* but we could do better */
if (discards_content)
++prsrc->layout_updates;
++prsrc->modifier_updates;
if (prsrc->layout_updates >= LAYOUT_CONVERT_THRESHOLD)
if (prsrc->modifier_updates >= LAYOUT_CONVERT_THRESHOLD)
{
prsrc->layout = MALI_TEXTURE_LINEAR;
prsrc->modifier = DRM_FORMAT_MOD_LINEAR;
util_copy_rect(
bo->cpu + prsrc->slices[0].offset,

View File

@ -58,17 +58,17 @@ struct panfrost_resource {
/* Distance from tree to tree */
unsigned cubemap_stride;
/* Internal layout (tiled?) */
enum mali_texture_layout layout;
/* DRM fourcc code: linear, 16x16 u-interleaved, AFBC */
uint64_t modifier;
/* Whether the layout can be changed */
bool layout_constant;
/* Whether the modifier can be changed */
bool modifier_constant;
/* Is transaciton elimination enabled? */
bool checksummed;
/* Used to decide when to convert to another layout */
uint16_t layout_updates;
/* Used to decide when to convert to another modifier */
uint16_t modifier_updates;
enum pipe_format internal_format;

View File

@ -141,13 +141,13 @@ panfrost_sfbd_set_cbuf(
fb->framebuffer = base;
fb->stride = stride;
if (rsrc->layout == MALI_TEXTURE_LINEAR)
if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR)
fb->format.block = MALI_BLOCK_LINEAR;
else if (rsrc->layout == MALI_TEXTURE_TILED) {
else if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
fb->format.block = MALI_BLOCK_TILED;
fb->stride *= 16;
} else {
fprintf(stderr, "Invalid render layout\n");
fprintf(stderr, "Invalid render modifier\n");
assert(0);
}
}
@ -163,8 +163,8 @@ panfrost_sfbd_set_zsbuf(
unsigned level = surf->u.tex.level;
assert(surf->u.tex.first_layer == 0);
if (rsrc->layout != MALI_TEXTURE_TILED)
unreachable("Invalid render layout.");
if (rsrc->modifier != DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
unreachable("Invalid render modifier.");
fb->depth_buffer = rsrc->bo->gpu + rsrc->slices[level].offset;
fb->depth_stride = rsrc->slices[level].stride;

View File

@ -299,7 +299,7 @@ panfrost_load_midg(
image->width0, image->height0,
MAX2(image->nr_samples, 1), 1,
image->format, MALI_TEX_2D,
image->layout,
image->modifier,
image->first_level, image->last_level,
0, 0,
image->nr_samples,

View File

@ -43,6 +43,21 @@
* to us here.
*/
/* Map modifiers to mali_texture_layout for packing in a texture descriptor */
static enum mali_texture_layout
panfrost_modifier_to_layout(uint64_t modifier)
{
if (drm_is_afbc(modifier))
return MALI_TEXTURE_AFBC;
else if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
return MALI_TEXTURE_TILED;
else if (modifier == DRM_FORMAT_MOD_LINEAR)
return MALI_TEXTURE_LINEAR;
else
unreachable("Invalid modifer");
}
/* Check if we need to set a custom stride by computing the "expected"
* stride and comparing it to what the user actually wants. Only applies
* to linear textures, since tiled/compressed textures have strict
@ -90,10 +105,10 @@ panfrost_astc_stretch(unsigned dim)
static unsigned
panfrost_compression_tag(
const struct util_format_description *desc,
enum mali_format format, enum mali_texture_layout layout)
enum mali_format format, uint64_t modifier)
{
if (layout == MALI_TEXTURE_AFBC)
return desc->nr_channels >= 3;
if (drm_is_afbc(modifier))
return (modifier & AFBC_FORMAT_MOD_YTR) ? 1 : 0;
else if (format == MALI_ASTC_2D_LDR || format == MALI_ASTC_2D_HDR)
return (panfrost_astc_stretch(desc->block.height) << 3) |
panfrost_astc_stretch(desc->block.width);
@ -157,10 +172,10 @@ panfrost_estimate_texture_payload_size(
unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer,
unsigned nr_samples,
enum mali_texture_type type, enum mali_texture_layout layout)
enum mali_texture_type type, uint64_t modifier)
{
/* Assume worst case */
unsigned manual_stride = (layout == MALI_TEXTURE_LINEAR);
unsigned manual_stride = (modifier == DRM_FORMAT_MOD_LINEAR);
unsigned elements = panfrost_texture_num_elements(
first_level, last_level,
@ -178,12 +193,12 @@ panfrost_estimate_texture_payload_size(
*/
static unsigned
panfrost_nonlinear_stride(enum mali_texture_layout layout,
panfrost_nonlinear_stride(uint64_t modifier,
unsigned bytes_per_pixel,
unsigned width,
unsigned height)
{
if (layout == MALI_TEXTURE_TILED) {
if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
return (height <= 16) ? 0 : (16 * bytes_per_pixel * ALIGN_POT(width, 16));
} else {
unreachable("TODO: AFBC on Bifrost");
@ -196,7 +211,7 @@ panfrost_emit_texture_payload(
const struct util_format_description *desc,
enum mali_format mali_format,
enum mali_texture_type type,
enum mali_texture_layout layout,
uint64_t modifier,
unsigned width, unsigned height,
unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer,
@ -206,7 +221,7 @@ panfrost_emit_texture_payload(
mali_ptr base,
struct panfrost_slice *slices)
{
base |= panfrost_compression_tag(desc, mali_format, layout);
base |= panfrost_compression_tag(desc, mali_format, modifier);
/* Inject the addresses in, interleaving array indices, mip levels,
* cube faces, and strides in that order */
@ -231,9 +246,9 @@ panfrost_emit_texture_payload(
cube_stride, l, w * face_mult + f, s);
if (manual_stride) {
payload[idx++] = (layout == MALI_TEXTURE_LINEAR) ?
payload[idx++] = (modifier == DRM_FORMAT_MOD_LINEAR) ?
slices[l].stride :
panfrost_nonlinear_stride(layout,
panfrost_nonlinear_stride(modifier,
MAX2(desc->block.bits / 8, 1),
u_minify(width, l),
u_minify(height, l));
@ -264,7 +279,7 @@ panfrost_new_texture(
uint16_t depth, uint16_t array_size,
enum pipe_format format,
enum mali_texture_type type,
enum mali_texture_layout layout,
uint64_t modifier,
unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer,
unsigned nr_samples,
@ -281,7 +296,7 @@ panfrost_new_texture(
enum mali_format mali_format = panfrost_pipe_format_table[desc->format].hw;
assert(mali_format);
bool manual_stride = (layout == MALI_TEXTURE_LINEAR)
bool manual_stride = (modifier == DRM_FORMAT_MOD_LINEAR)
&& panfrost_needs_explicit_stride(slices, width,
first_level, last_level, bytes_per_pixel);
@ -299,7 +314,7 @@ panfrost_new_texture(
.format = mali_format,
.srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB),
.type = type,
.layout = layout,
.layout = panfrost_modifier_to_layout(modifier),
.manual_stride = manual_stride,
.unknown2 = 1,
},
@ -315,7 +330,7 @@ panfrost_new_texture(
desc,
mali_format,
type,
layout,
modifier,
width, height,
first_level, last_level,
first_layer, last_layer,
@ -333,7 +348,7 @@ panfrost_new_texture_bifrost(
uint16_t depth, uint16_t array_size,
enum pipe_format format,
enum mali_texture_type type,
enum mali_texture_layout layout,
uint64_t modifier,
unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer,
unsigned nr_samples,
@ -354,7 +369,7 @@ panfrost_new_texture_bifrost(
desc,
mali_format,
type,
layout,
modifier,
width, height,
first_level, last_level,
first_layer, last_layer,
@ -372,7 +387,7 @@ panfrost_new_texture_bifrost(
descriptor->width = MALI_POSITIVE(u_minify(width, first_level));
descriptor->height = MALI_POSITIVE(u_minify(height, first_level));
descriptor->swizzle = swizzle;
descriptor->layout = layout;
descriptor->layout = panfrost_modifier_to_layout(modifier),
descriptor->levels = last_level - first_level;
descriptor->unk1 = 0x0;
descriptor->levels_unk = 0;

View File

@ -29,6 +29,7 @@
#define __PAN_TEXTURE_H
#include <stdbool.h>
#include "drm-uapi/drm_fourcc.h"
#include "util/format/u_format.h"
#include "compiler/shader_enums.h"
#include "panfrost-job.h"
@ -64,7 +65,7 @@ struct pan_image {
struct panfrost_bo *bo;
struct panfrost_slice *slices;
unsigned cubemap_stride;
enum mali_texture_layout layout;
uint64_t modifier;
};
unsigned
@ -88,7 +89,7 @@ panfrost_estimate_texture_payload_size(
unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer,
unsigned nr_samples,
enum mali_texture_type type, enum mali_texture_layout layout);
enum mali_texture_type type, uint64_t modifier);
void
panfrost_new_texture(
@ -97,7 +98,7 @@ panfrost_new_texture(
uint16_t depth, uint16_t array_size,
enum pipe_format format,
enum mali_texture_type type,
enum mali_texture_layout layout,
uint64_t modifier,
unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer,
unsigned nr_samples,
@ -113,7 +114,7 @@ panfrost_new_texture_bifrost(
uint16_t depth, uint16_t array_size,
enum pipe_format format,
enum mali_texture_type type,
enum mali_texture_layout layout,
uint64_t modifier,
unsigned first_level, unsigned last_level,
unsigned first_layer, unsigned last_layer,
unsigned nr_samples,
@ -195,4 +196,10 @@ panfrost_load_midg(
struct pan_image *image,
unsigned loc);
/* DRM modifier helper */
#define drm_is_afbc(mod) \
((mod >> 52) == (DRM_FORMAT_MOD_ARM_TYPE_AFBC | \
(DRM_FORMAT_MOD_VENDOR_ARM << 4)))
#endif