pan/image: Teach pan_image/layout about planar images

The way things are done at the moment, the pan_layout logic has no way
of knowing which plane is targeted, which either forces the user of
pan_image_layout_init() to patch the layout after the calculation based
on the YUV format.

These changes unblock unittests on YUV formats.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Tested-by: Eric R. Smith <eric.smith@collabora.com>
Reviewed-by: Eric R. Smith <eric.smith@collabora.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35015>
This commit is contained in:
Boris Brezillon 2025-05-05 19:54:26 +02:00 committed by Marge Bot
parent ceb79e399e
commit 4d9a4e8228
21 changed files with 586 additions and 372 deletions

View file

@ -942,7 +942,7 @@ panfrost_emit_vertex_buffers(struct panfrost_batch *batch)
panfrost_batch_read_rsrc(batch, rsrc, PIPE_SHADER_VERTEX);
pan_pack(buffers + i, BUFFER, cfg) {
cfg.address = rsrc->image.data.base + vb.buffer_offset;
cfg.address = rsrc->plane.base + vb.buffer_offset;
cfg.size = prsrc->width0 - vb.buffer_offset;
}
@ -1019,7 +1019,7 @@ panfrost_map_constant_buffer_gpu(struct panfrost_batch *batch,
/* Alignment gauranteed by
* pipe_caps.constant_buffer_offset_alignment */
return rsrc->image.data.base + cb->buffer_offset;
return rsrc->plane.base + cb->buffer_offset;
} else if (cb->user_buffer) {
return pan_pool_upload_aligned(&batch->pool.base,
cb->user_buffer + cb->buffer_offset,
@ -1325,7 +1325,7 @@ panfrost_upload_sysvals(struct panfrost_batch *batch, void *ptr_cpu,
panfrost_batch_write_rsrc(batch, rsrc, PIPE_SHADER_VERTEX);
uniforms[i].du[0] = rsrc->image.data.base + offset;
uniforms[i].du[0] = rsrc->plane.base + offset;
break;
}
@ -1695,8 +1695,8 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
is_shadow = true;
}
so->texture_bo = prsrc->image.data.base;
so->texture_size = prsrc->image.layout.data_size_B;
so->texture_bo = prsrc->plane.base;
so->texture_size = prsrc->plane.layout.data_size_B;
so->modifier = prsrc->modifier;
/* MSAA only supported for 2D textures */
@ -1715,7 +1715,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
.width_el =
MIN2(so->base.u.buf.size / util_format_get_blocksize(format),
PAN_MAX_TEXEL_BUFFER_ELEMENTS),
.base = prsrc->image.data.base + so->base.u.buf.offset,
.base = prsrc->plane.base + so->base.u.buf.offset,
};
if (desc->layout == UTIL_FORMAT_LAYOUT_ASTC) {
@ -1779,7 +1779,6 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
so->base.swizzle_b,
so->base.swizzle_a,
},
.planes = {NULL},
};
#if PAN_ARCH >= 7
@ -1844,8 +1843,8 @@ panfrost_update_sampler_view(struct panfrost_sampler_view *view,
struct pipe_context *pctx)
{
struct panfrost_resource *rsrc = pan_resource(view->base.texture);
if (view->texture_bo != rsrc->image.data.base ||
view->texture_size != rsrc->image.layout.data_size_B ||
if (view->texture_bo != rsrc->plane.base ||
view->texture_size != rsrc->plane.layout.data_size_B ||
view->modifier != rsrc->modifier) {
panfrost_bo_unreference(view->state.bo);
panfrost_create_sampler_view_bo(view, pctx, &rsrc->base);
@ -2047,7 +2046,7 @@ emit_image_bufs(struct panfrost_batch *batch, enum pipe_shader_type shader,
unsigned offset =
is_buffer ? image->u.buf.offset
: pan_image_surface_offset(
&rsrc->image.layout, image->u.tex.level,
&rsrc->plane.layout, image->u.tex.level,
(is_3d || is_msaa) ? 0 : image->u.tex.first_layer,
(is_3d || is_msaa) ? image->u.tex.first_layer : 0);
@ -2055,10 +2054,10 @@ emit_image_bufs(struct panfrost_batch *batch, enum pipe_shader_type shader,
pan_pack(bufs + (i * 2), ATTRIBUTE_BUFFER, cfg) {
cfg.type = pan_modifier_to_attr_type(rsrc->image.props.modifier);
cfg.pointer = rsrc->image.data.base + offset;
cfg.pointer = rsrc->plane.base + offset;
cfg.stride = util_format_get_blocksize(image->format);
cfg.size =
pan_image_mip_level_size(&rsrc->image.props, &rsrc->image.layout,
pan_image_mip_level_size(&rsrc->image.props, &rsrc->plane.layout,
is_buffer ? 0 : image->u.tex.level);
}
@ -2084,16 +2083,16 @@ emit_image_bufs(struct panfrost_batch *batch, enum pipe_shader_type shader,
is_3d ? u_minify(rsrc->image.props.extent_px.depth, level)
: (image->u.tex.last_layer - image->u.tex.first_layer + 1);
cfg.row_stride = rsrc->image.layout.slices[level].row_stride_B;
cfg.row_stride = rsrc->plane.layout.slices[level].row_stride_B;
if (cfg.r_dimension > 1) {
cfg.slice_stride = pan_image_surface_stride(
&rsrc->image.props, &rsrc->image.layout, level);
&rsrc->image.props, &rsrc->plane.layout, level);
}
if (is_msaa) {
if (cfg.r_dimension == 1) {
unsigned slice_stride = pan_image_surface_stride(
&rsrc->image.props, &rsrc->image.layout, level);
&rsrc->image.props, &rsrc->plane.layout, level);
/* regular multisampled images get the sample index in
the R dimension */
@ -2218,7 +2217,7 @@ panfrost_emit_vertex_data(struct panfrost_batch *batch, uint64_t *buffers)
panfrost_batch_read_rsrc(batch, rsrc, PIPE_SHADER_VERTEX);
/* Mask off lower bits, see offset fixup below */
uint64_t raw_addr = rsrc->image.data.base + buf->buffer_offset;
uint64_t raw_addr = rsrc->plane.base + buf->buffer_offset;
uint64_t addr = raw_addr & ~63;
/* Since we advanced the base pointer, we shrink the buffer
@ -3399,7 +3398,7 @@ panfrost_draw_indirect(struct pipe_context *pipe,
struct panfrost_resource *index_buffer =
pan_resource(info->index.resource);
panfrost_batch_read_rsrc(batch, index_buffer, PIPE_SHADER_VERTEX);
batch->indices = index_buffer->image.data.base;
batch->indices = index_buffer->plane.base;
}
panfrost_update_state_3d(batch);
@ -3598,9 +3597,9 @@ panfrost_afbc_size(struct panfrost_batch *batch, struct panfrost_resource *src,
{
MESA_TRACE_FUNC();
struct pan_image_slice_layout *slice = &src->image.layout.slices[level];
struct pan_image_slice_layout *slice = &src->plane.layout.slices[level];
struct panfrost_afbc_size_info consts = {
.src = src->image.data.base + slice->offset_B,
.src = src->plane.base + slice->offset_B,
.metadata = metadata->ptr.gpu + offset,
};
@ -3619,9 +3618,9 @@ panfrost_afbc_pack(struct panfrost_batch *batch, struct panfrost_resource *src,
{
MESA_TRACE_FUNC();
struct pan_image_slice_layout *src_slice = &src->image.layout.slices[level];
struct pan_image_slice_layout *src_slice = &src->plane.layout.slices[level];
struct panfrost_afbc_pack_info consts = {
.src = src->image.data.base + src_slice->offset_B,
.src = src->plane.base + src_slice->offset_B,
.dst = dst->ptr.gpu + dst_slice->offset_B,
.metadata = metadata->ptr.gpu + metadata_offset_B,
.header_size = dst_slice->afbc.header_size_B,
@ -3651,9 +3650,9 @@ panfrost_mtk_detile_compute(struct panfrost_context *ctx, struct pipe_blit_info
unsigned width = info->src.box.width;
unsigned height = info->src.box.height;
unsigned src_stride =
pan_resource(y_src)->image.layout.slices[0].row_stride_B;
pan_resource(y_src)->plane.layout.slices[0].row_stride_B;
unsigned dst_stride =
pan_resource(y_dst)->image.layout.slices[0].row_stride_B;
pan_resource(y_dst)->plane.layout.slices[0].row_stride_B;
/* 4 images: y_src, uv_src, y_dst, uv_dst */
struct pipe_image_view image[4] = { 0 };

View file

@ -935,7 +935,7 @@ GENX(csf_launch_grid)(struct panfrost_batch *batch,
struct cs_index address = cs_reg64(b, 64);
cs_move64_to(
b, address,
pan_resource(info->indirect)->image.data.base + info->indirect_offset);
pan_resource(info->indirect)->plane.base + info->indirect_offset);
struct cs_index grid_xyz = cs_sr_reg_tuple(b, COMPUTE, JOB_SIZE_X, 3);
cs_load_to(b, grid_xyz, address, BITFIELD_MASK(3), 0);
@ -1138,7 +1138,7 @@ csf_emit_draw_state(struct panfrost_batch *batch,
if (ctx->occlusion_query && ctx->active_queries) {
struct panfrost_resource *rsrc = pan_resource(ctx->occlusion_query->rsrc);
cs_move64_to(b, cs_sr_reg64(b, IDVS, OQ), rsrc->image.data.base);
cs_move64_to(b, cs_sr_reg64(b, IDVS, OQ), rsrc->plane.base);
panfrost_batch_write_rsrc(ctx->batch, rsrc, PIPE_SHADER_FRAGMENT);
}
@ -1378,7 +1378,7 @@ GENX(csf_launch_draw_indirect)(struct panfrost_batch *batch,
struct cs_index counter = cs_reg32(b, 66);
cs_move64_to(
b, address,
pan_resource(indirect->buffer)->image.data.base + indirect->offset);
pan_resource(indirect->buffer)->plane.base + indirect->offset);
cs_move32_to(b, counter, indirect->draw_count);
cs_while(b, MALI_CS_CONDITION_GREATER, counter) {
@ -1638,7 +1638,7 @@ GENX(csf_emit_write_timestamp)(struct panfrost_batch *batch,
struct cs_builder *b = batch->csf.cs.builder;
struct cs_index address = cs_reg64(b, 40);
cs_move64_to(b, address, dst->image.data.base + offset);
cs_move64_to(b, address, dst->plane.base + offset);
cs_store_state(b, address, 0, MALI_CS_STATE_TIMESTAMP, cs_now());
panfrost_batch_write_rsrc(batch, dst, PIPE_SHADER_VERTEX);

View file

@ -1226,8 +1226,8 @@ pan_preload_emit_pre_frame_dcd(struct pan_fb_preload_cache *cache,
always_write);
if (zs) {
enum pipe_format fmt = fb->zs.view.zs
? fb->zs.view.zs->planes[0]->props.format
: fb->zs.view.s->planes[0]->props.format;
? fb->zs.view.zs->planes[0].image->props.format
: fb->zs.view.s->planes[0].image->props.format;
/* On some GPUs (e.g. G31), we must use SHADER_MODE_ALWAYS rather than
* SHADER_MODE_INTERSECT for full screen operations. Since the full
* screen rectangle will always intersect, this won't affect

View file

@ -105,7 +105,7 @@ panfrost_get_index_buffer(struct panfrost_batch *batch,
if (!info->has_user_indices) {
/* Only resources can be directly mapped */
panfrost_batch_read_rsrc(batch, rsrc, PIPE_SHADER_VERTEX);
return rsrc->image.data.base + offset;
return rsrc->plane.base + offset;
} else {
/* Otherwise, we need to upload to transient memory */
const uint8_t *ibuf8 = (const uint8_t *)info->index.user;

View file

@ -380,7 +380,7 @@ GENX(jm_launch_grid)(struct panfrost_batch *batch,
struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
struct pan_indirect_dispatch_info indirect = {
.job = t.gpu,
.indirect_dim = pan_resource(info->indirect)->image.data.base +
.indirect_dim = pan_resource(info->indirect)->plane.base +
info->indirect_offset,
.num_wg_sysval =
{
@ -545,7 +545,7 @@ jm_emit_tiler_draw(struct mali_draw_packed *out, struct panfrost_batch *batch,
struct panfrost_resource *rsrc =
pan_resource(ctx->occlusion_query->rsrc);
cfg.occlusion = rsrc->image.data.base;
cfg.occlusion = rsrc->plane.base;
panfrost_batch_write_rsrc(ctx->batch, rsrc, PIPE_SHADER_FRAGMENT);
}
@ -1027,7 +1027,7 @@ GENX(jm_emit_write_timestamp)(struct panfrost_batch *batch,
struct pan_ptr job = pan_pool_alloc_desc(&batch->pool.base, WRITE_VALUE_JOB);
pan_section_pack(job.cpu, WRITE_VALUE_JOB, PAYLOAD, cfg) {
cfg.address = dst->image.data.base + offset;
cfg.address = dst->plane.base + offset;
cfg.type = MALI_WRITE_VALUE_TYPE_SYSTEM_TIMESTAMP;
}

View file

@ -564,7 +564,10 @@ panfrost_batch_to_fb_info(const struct panfrost_batch *batch,
zs->last_level = zs->first_level = surf->level;
zs->first_layer = surf->first_layer;
zs->last_layer = surf->last_layer;
zs->planes[0] = &z_rsrc->image;
zs->planes[0] = (struct pan_image_plane_ref){
.image = &z_rsrc->image,
.plane_idx = 0,
};
zs->nr_samples = surf->nr_samples ?: MAX2(surf->texture->nr_samples, 1);
memcpy(zs->swizzle, id_swz, sizeof(zs->swizzle));
fb->zs.view.zs = zs;
@ -581,7 +584,10 @@ panfrost_batch_to_fb_info(const struct panfrost_batch *batch,
s->last_level = s->first_level = surf->level;
s->first_layer = surf->first_layer;
s->last_layer = surf->last_layer;
s->planes[0] = &s_rsrc->image;
s->planes[0] = (struct pan_image_plane_ref){
.image = &s_rsrc->image,
.plane_idx = 0,
};
s->nr_samples = surf->nr_samples ?: MAX2(surf->texture->nr_samples, 1);
memcpy(s->swizzle, id_swz, sizeof(s->swizzle));
fb->zs.view.s = s;

View file

@ -104,6 +104,34 @@ panfrost_clear_render_target(struct pipe_context *pipe,
height);
}
static void
panfrost_resource_init_image(struct panfrost_resource *rsc,
const struct pan_image_props *iprops,
unsigned plane_idx)
{
if (util_format_get_num_planes(iprops->format) == 1) {
rsc->image.props = *iprops;
rsc->image.planes[0] = &rsc->plane;
return;
}
/* The resource props will be initialized when we hit the first plane. */
if (plane_idx > 0)
return;
rsc->image.props = *iprops;
for (struct panfrost_resource *plane = rsc;
plane && plane_idx < ARRAY_SIZE(rsc->image.planes);
plane = pan_resource(plane->base.next))
rsc->image.planes[plane_idx++] = &plane->plane;
assert(plane_idx == util_format_get_num_planes(iprops->format));
for (struct panfrost_resource *plane = pan_resource(rsc->base.next);
plane; plane = pan_resource(plane->base.next))
plane->image = rsc->image;
}
static struct pipe_resource *
panfrost_resource_from_handle(struct pipe_screen *pscreen,
const struct pipe_resource *templat,
@ -138,30 +166,43 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
};
rsc->modifier = mod;
rsc->image.props = (struct pan_image_props){
bool h_subsamp =
util_format_get_plane_width(templat->format, whandle->plane, 2) == 1;
bool v_subsamp =
util_format_get_plane_height(templat->format, whandle->plane, 2) == 1;
struct pan_image_props iprops = {
/* pan_layout doesn't know about MTK modifiers, so make it
* linear before calling pan_image_layout_init(). */
.modifier = panfrost_is_emulated_mod(mod) ? DRM_FORMAT_MOD_LINEAR : mod,
.format = templat->format,
.dim = dim,
.extent_px = {
.width = prsc->width0,
.height = prsc->height0,
/* pan_layout_init() wants the property of the full image, not the
* plane, but pipe_resource encodes the properties of the plane.
* We need to adjust the width/height according to the subsampling
* properties. */
.width = prsc->width0 * (h_subsamp ? 2 : 1),
.height = prsc->height0 * (v_subsamp ? 2 : 1),
.depth = prsc->depth0,
},
.array_size = prsc->array_size,
.nr_samples = MAX2(prsc->nr_samples, 1),
.nr_slices = 1,
};
unsigned format_plane =
util_format_get_num_planes(iprops.format) > 1 ? whandle->plane : 0;
bool valid = pan_image_layout_init(dev->arch, &rsc->image.props,
&explicit_layout, &rsc->image.layout);
bool valid = pan_image_layout_init(dev->arch, &iprops, format_plane,
&explicit_layout, &rsc->plane.layout);
if (!valid) {
FREE(rsc);
return NULL;
}
panfrost_resource_init_image(rsc, &iprops, whandle->plane);
rsc->bo = panfrost_bo_import(dev, whandle->handle);
/* Sometimes an import can fail e.g. on an invalid buffer fd, out of
* memory space to mmap it etc.
@ -171,7 +212,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
return NULL;
}
rsc->image.data.base = rsc->bo->ptr.gpu;
rsc->plane.base = rsc->bo->ptr.gpu;
rsc->modifier_constant = true;
BITSET_SET(rsc->valid.data, 0);
@ -192,15 +233,13 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
struct winsys_handle *handle, unsigned usage)
{
struct panfrost_device *dev = pan_device(pscreen);
struct panfrost_resource *rsrc;
struct panfrost_resource *rsrc = pan_resource(pt);
struct renderonly_scanout *scanout;
struct pipe_resource *plane_res =
util_resource_at_index(pt, handle->plane);
if (!plane_res)
if (handle->plane >= ARRAY_SIZE(rsrc->image.planes) ||
!rsrc->image.planes[handle->plane])
return false;
rsrc = pan_resource(plane_res);
scanout = rsrc->scanout;
handle->modifier = rsrc->modifier;
@ -223,7 +262,8 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
}
struct pan_image_wsi_layout wsi_layout = pan_image_layout_get_wsi_layout(
&rsrc->image.props, &rsrc->image.layout, 0);
&rsrc->image.props, handle->plane,
&rsrc->image.planes[handle->plane]->layout, 0);
handle->stride = wsi_layout.row_pitch_B;
handle->offset = wsi_layout.offset_B;
@ -238,18 +278,17 @@ panfrost_resource_get_param(struct pipe_screen *pscreen,
enum pipe_resource_param param, unsigned usage,
uint64_t *value)
{
struct pipe_resource *plane_res = util_resource_at_index(prsc, plane);
struct panfrost_resource *rsrc = pan_resource(plane_res);
struct panfrost_resource *rsrc = pan_resource(prsc);
switch (param) {
case PIPE_RESOURCE_PARAM_STRIDE:
*value = pan_image_layout_get_wsi_layout(&rsrc->image.props,
&rsrc->image.layout, level)
*value = pan_image_layout_get_wsi_layout(&rsrc->image.props, plane,
&rsrc->plane.layout, level)
.row_pitch_B;
return true;
case PIPE_RESOURCE_PARAM_OFFSET:
*value = pan_image_layout_get_wsi_layout(&rsrc->image.props,
&rsrc->image.layout, level)
*value = pan_image_layout_get_wsi_layout(&rsrc->image.props, plane,
&rsrc->plane.layout, level)
.offset_B;
return true;
case PIPE_RESOURCE_PARAM_MODIFIER:
@ -555,7 +594,7 @@ panfrost_should_checksum(const struct panfrost_device *dev,
static void
panfrost_resource_setup(struct pipe_screen *screen,
struct panfrost_resource *pres, uint64_t modifier,
enum pipe_format fmt)
enum pipe_format fmt, unsigned plane_idx)
{
struct panfrost_device *dev = pan_device(screen);
uint64_t chosen_mod = modifier != DRM_FORMAT_MOD_INVALID
@ -576,14 +615,21 @@ panfrost_resource_setup(struct pipe_screen *screen,
fmt = PIPE_FORMAT_Z32_FLOAT;
pres->modifier = chosen_mod;
pres->image.props = (struct pan_image_props){
bool h_subsamp = util_format_get_plane_width(fmt, plane_idx, 2) == 1;
bool v_subsamp = util_format_get_plane_height(fmt, plane_idx, 2) == 1;
struct pan_image_props iprops = {
.modifier = panfrost_is_emulated_mod(chosen_mod) ? DRM_FORMAT_MOD_LINEAR
: chosen_mod,
.format = fmt,
.dim = dim,
.extent_px = {
.width = pres->base.width0,
.height = pres->base.height0,
/* pan_layout_init() wants the property of the full image, not the
* plane, but pipe_resource encodes the properties of the plane.
* We need to adjust the width/height according to the subsampling
* properties. */
.width = pres->base.width0 * (h_subsamp ? 2 : 1),
.height = pres->base.height0 * (v_subsamp ? 2 : 1),
.depth = pres->base.depth0,
},
.array_size = pres->base.array_size,
@ -596,9 +642,11 @@ panfrost_resource_setup(struct pipe_screen *screen,
* want the real bitrate and not DEFAULT */
pres->base.compression_rate = pan_afrc_get_rate(fmt, chosen_mod);
ASSERTED bool valid = pan_image_layout_init(dev->arch, &pres->image.props,
NULL, &pres->image.layout);
ASSERTED bool valid = pan_image_layout_init(dev->arch, &iprops, plane_idx,
NULL, &pres->plane.layout);
assert(valid);
panfrost_resource_init_image(pres, &iprops, plane_idx);
}
static int
@ -611,11 +659,11 @@ panfrost_resource_init_afbc_headers(struct panfrost_resource *pres)
for (unsigned i = 0; i < pres->base.array_size; ++i) {
for (unsigned l = 0; l <= pres->base.last_level; ++l) {
struct pan_image_slice_layout *slice = &pres->image.layout.slices[l];
struct pan_image_slice_layout *slice = &pres->plane.layout.slices[l];
for (unsigned s = 0; s < nr_samples; ++s) {
void *ptr = pres->bo->ptr.cpu +
(i * pres->image.layout.array_stride_B) +
(i * pres->plane.layout.array_stride_B) +
slice->offset_B + (s * slice->afbc.surface_stride_B);
/* Zero-ed AFBC headers seem to encode a plain
@ -729,7 +777,8 @@ panfrost_can_create_resource(struct pipe_screen *screen,
struct panfrost_resource tmp;
tmp.base = *template;
panfrost_resource_setup(screen, &tmp, DRM_FORMAT_MOD_INVALID, template->format);
panfrost_resource_setup(screen, &tmp, DRM_FORMAT_MOD_INVALID,
template->format, 0);
uint64_t system_memory;
if (!os_get_total_physical_memory(&system_memory))
@ -738,13 +787,13 @@ panfrost_can_create_resource(struct pipe_screen *screen,
/* Limit maximum texture size to a quarter of the system memory, to avoid
* allocating huge textures on systems with little memory.
*/
return tmp.image.layout.data_size_B <= system_memory / 4;
return tmp.plane.layout.data_size_B <= system_memory / 4;
}
struct pipe_resource *
static struct pipe_resource *
panfrost_resource_create_with_modifier(struct pipe_screen *screen,
const struct pipe_resource *template,
uint64_t modifier)
uint64_t modifier, unsigned plane_idx)
{
MESA_TRACE_FUNC();
@ -777,7 +826,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
so->modifier_constant = true;
}
panfrost_resource_setup(screen, so, modifier, template->format);
panfrost_resource_setup(screen, so, modifier, template->format, plane_idx);
/* Guess a label based on the bind */
unsigned bind = template->bind;
@ -799,7 +848,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
if (dev->ro && (template->bind & PIPE_BIND_SCANOUT)) {
struct winsys_handle handle;
struct pan_image_block_size blocksize =
pan_image_renderblock_size_el(modifier, template->format);
pan_image_renderblock_size_el(modifier, template->format, plane_idx);
/* Block-based texture formats are only used for texture
* compression (not framebuffer compression!), which doesn't
@ -826,7 +875,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
unsigned width = ALIGN_POT(template->width0, blocksize.width);
unsigned stride = ALIGN_POT(template->width0, blocksize.width) *
util_format_get_blocksize(template->format);
unsigned size = so->image.layout.data_size_B;
unsigned size = so->plane.layout.data_size_B;
unsigned effective_rows = DIV_ROUND_UP(size, stride);
struct pipe_resource scanout_tmpl = {
@ -855,7 +904,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
return NULL;
}
so->image.data.base = so->bo->ptr.gpu;
so->plane.base = so->bo->ptr.gpu;
} else {
/* 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 */
@ -866,14 +915,14 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
flags |= PAN_BO_SHAREABLE;
so->bo =
panfrost_bo_create(dev, so->image.layout.data_size_B, flags, label);
panfrost_bo_create(dev, so->plane.layout.data_size_B, flags, label);
if (!so->bo) {
FREE(so);
return NULL;
}
so->image.data.base = so->bo->ptr.gpu;
so->plane.base = so->bo->ptr.gpu;
so->constant_stencil = true;
}
@ -900,7 +949,7 @@ panfrost_resource_create(struct pipe_screen *screen,
const struct pipe_resource *template)
{
return panfrost_resource_create_with_modifier(screen, template,
DRM_FORMAT_MOD_INVALID);
DRM_FORMAT_MOD_INVALID, 0);
}
/* If no modifier is specified, we'll choose. Otherwise, the order of
@ -917,14 +966,14 @@ panfrost_resource_create_with_modifiers(struct pipe_screen *screen,
for (unsigned i = 0; i < ARRAY_SIZE(native_mods); ++i) {
if (drm_find_modifier(native_mods[i], modifiers, count)) {
return panfrost_resource_create_with_modifier(screen, template,
native_mods[i]);
native_mods[i], 0);
}
}
for (unsigned i = 0; i < ARRAY_SIZE(emulated_mods); ++i) {
if (drm_find_modifier(emulated_mods[i], modifiers, count)) {
return panfrost_resource_create_with_modifier(screen, template,
emulated_mods[i]);
emulated_mods[i], 0);
}
}
@ -1052,20 +1101,20 @@ panfrost_load_tiled_images(struct panfrost_transfer *transfer,
struct panfrost_bo *bo = rsrc->bo;
unsigned stride =
pan_image_surface_stride(&rsrc->image.props, &rsrc->image.layout, level);
pan_image_surface_stride(&rsrc->image.props, &rsrc->plane.layout, level);
/* Otherwise, load each layer separately, required to load from 3D and
* array textures.
*/
for (unsigned z = 0; z < ptrans->box.depth; ++z) {
void *dst = transfer->map + (ptrans->layer_stride * z);
uint8_t *map = bo->ptr.cpu + rsrc->image.layout.slices[level].offset_B +
uint8_t *map = bo->ptr.cpu + rsrc->plane.layout.slices[level].offset_B +
(z + ptrans->box.z) * stride;
pan_load_tiled_image(dst, map, ptrans->box.x, ptrans->box.y,
ptrans->box.width, ptrans->box.height,
ptrans->stride,
rsrc->image.layout.slices[level].row_stride_B,
rsrc->plane.layout.slices[level].row_stride_B,
rsrc->image.props.format);
}
}
@ -1176,7 +1225,7 @@ pan_dump_resource(struct panfrost_context *ctx, struct panfrost_resource *rsc)
debug_dump_image(buffer, rsc->base.format, 0 /* UNUSED */, rsc->base.width0,
rsc->base.height0,
linear->image.layout.slices[0].row_stride_B,
linear->plane.layout.slices[0].row_stride_B,
linear->bo->ptr.cpu);
} else {
mesa_loge("failed to mmap, not dumping resource");
@ -1206,19 +1255,19 @@ panfrost_store_tiled_images(struct panfrost_transfer *transfer,
struct pipe_transfer *ptrans = &transfer->base;
unsigned level = ptrans->level;
unsigned stride =
pan_image_surface_stride(&rsrc->image.props, &rsrc->image.layout, level);
pan_image_surface_stride(&rsrc->image.props, &rsrc->plane.layout, level);
/* Otherwise, store each layer separately, required to store to 3D and
* array textures.
*/
for (unsigned z = 0; z < ptrans->box.depth; ++z) {
void *src = transfer->map + (ptrans->layer_stride * z);
uint8_t *map = bo->ptr.cpu + rsrc->image.layout.slices[level].offset_B +
uint8_t *map = bo->ptr.cpu + rsrc->plane.layout.slices[level].offset_B +
(z + ptrans->box.z) * stride;
pan_store_tiled_image(map, src, ptrans->box.x, ptrans->box.y,
ptrans->box.width, ptrans->box.height,
rsrc->image.layout.slices[level].row_stride_B,
rsrc->plane.layout.slices[level].row_stride_B,
ptrans->stride, rsrc->image.props.format);
}
}
@ -1287,9 +1336,9 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
/* Staging resources have one LOD: level 0. Query the strides
* on this LOD.
*/
transfer->base.stride = staging->image.layout.slices[0].row_stride_B;
transfer->base.stride = staging->plane.layout.slices[0].row_stride_B;
transfer->base.layer_stride = pan_image_surface_stride(
&staging->image.props, &staging->image.layout, 0);
&staging->image.props, &staging->plane.layout, 0);
transfer->staging.rsrc = &staging->base;
@ -1404,7 +1453,7 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
*/
panfrost_bo_unreference(rsrc->bo);
rsrc->bo = newbo;
rsrc->image.data.base = newbo->ptr.gpu;
rsrc->plane.base = newbo->ptr.gpu;
if (!copy_resource && drm_is_afbc(rsrc->modifier)) {
if (panfrost_resource_init_afbc_headers(rsrc))
@ -1463,9 +1512,9 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
if ((usage & dpw) == dpw && rsrc->index_cache)
return NULL;
transfer->base.stride = rsrc->image.layout.slices[level].row_stride_B;
transfer->base.stride = rsrc->plane.layout.slices[level].row_stride_B;
transfer->base.layer_stride = pan_image_surface_stride(
&rsrc->image.props, &rsrc->image.layout, level);
&rsrc->image.props, &rsrc->plane.layout, level);
/* By mapping direct-write, we're implicitly already
* initialized (maybe), so be conservative */
@ -1477,9 +1526,9 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
transfer->base.box.x, transfer->base.box.width);
}
return bo->ptr.cpu + rsrc->image.layout.slices[level].offset_B +
return bo->ptr.cpu + rsrc->plane.layout.slices[level].offset_B +
box->z * transfer->base.layer_stride +
box_blocks.y * rsrc->image.layout.slices[level].row_stride_B +
box_blocks.y * rsrc->plane.layout.slices[level].row_stride_B +
box_blocks.x * bytes_per_block;
}
}
@ -1495,43 +1544,26 @@ pan_resource_modifier_convert(struct panfrost_context *ctx,
assert(!rsrc->modifier_constant || copy_resource);
struct pipe_resource template = rsrc->base;
struct pipe_resource *tmp_prsrc;
struct pipe_resource *next_tmp_prsrc = NULL;
struct panfrost_resource *next_tmp_rsrc = NULL;
if (template.next) {
struct pipe_resource second_template = *template.next;
bool fix_stride;
assert(drm_is_mtk_tiled(rsrc->modifier));
/* fix up the stride */
switch (rsrc->base.format) {
case PIPE_FORMAT_R8_G8B8_420_UNORM:
case PIPE_FORMAT_R8_G8B8_422_UNORM:
case PIPE_FORMAT_R10_G10B10_420_UNORM:
case PIPE_FORMAT_R10_G10B10_422_UNORM:
fix_stride = true;
break;
default:
fix_stride = false;
break;
}
template.next = NULL;
if (fix_stride) {
second_template.width0 *= 2; /* temporarily adjust size for subsampling */
}
next_tmp_prsrc = panfrost_resource_create_with_modifier(
ctx->base.screen, &second_template, modifier);
next_tmp_rsrc = pan_resource(next_tmp_prsrc);
if (fix_stride) {
next_tmp_rsrc->base.width0 /= 2;
next_tmp_rsrc->image.props.extent_px.width /= 2;
}
}
tmp_prsrc = panfrost_resource_create_with_modifier(
ctx->base.screen, &template, modifier);
struct panfrost_resource *tmp_rsrc = pan_resource(tmp_prsrc);
if (next_tmp_prsrc) {
tmp_prsrc->next = next_tmp_prsrc;
struct pipe_resource templates[MAX_IMAGE_PLANES] = {0};
unsigned plane_count;
templates[0] = rsrc->base;
for (plane_count = 1;
templates[plane_count - 1].next && plane_count < ARRAY_SIZE(templates);
plane_count++)
templates[plane_count] = *(templates[plane_count - 1].next);
struct panfrost_resource *tmp_rsrc = NULL;
for (int i = plane_count - 1; i >= 0; i--) {
if (tmp_rsrc)
templates[i].next = &tmp_rsrc->base;
struct pipe_resource *new_prsrc =
panfrost_resource_create_with_modifier(ctx->base.screen, &templates[i],
modifier, i);
tmp_rsrc = pan_resource(new_prsrc);
}
if (need_shadow && rsrc->shadow_image) {
@ -1577,21 +1609,24 @@ pan_resource_modifier_convert(struct panfrost_context *ctx,
if (need_shadow) {
panfrost_resource_setup(ctx->base.screen, tmp_rsrc,
modifier, tmp_rsrc->base.format);
modifier, tmp_rsrc->base.format, 0);
rsrc->shadow_image = tmp_rsrc;
} else {
panfrost_bo_unreference(rsrc->bo);
rsrc->bo = tmp_rsrc->bo;
rsrc->image.data.base = rsrc->bo->ptr.gpu;
rsrc->plane.base = rsrc->bo->ptr.gpu;
panfrost_bo_reference(rsrc->bo);
panfrost_resource_setup(ctx->base.screen, rsrc, modifier,
tmp_rsrc->base.format);
tmp_rsrc->base.format, 0);
/* panfrost_resource_setup will force the modifier to stay constant when
* called with a specific modifier. We don't want that here, we want to
* be able to convert back to another modifier if needed */
rsrc->modifier_constant = false;
struct pipe_resource *tmp_prsrc = &tmp_rsrc->base;
pipe_resource_reference(&tmp_prsrc, NULL);
perf_debug(ctx, "resource_modifier_convert required due to: %s", reason);
}
@ -1618,8 +1653,8 @@ pan_legalize_format(struct panfrost_context *ctx,
return;
if (drm_is_afbc(rsrc->modifier)) {
compatible = (pan_afbc_format(dev->arch, old_format) ==
pan_afbc_format(dev->arch, new_format));
compatible = (pan_afbc_format(dev->arch, old_format, 0) ==
pan_afbc_format(dev->arch, new_format, 0));
} else if (drm_is_afrc(rsrc->modifier)) {
struct pan_afrc_format_info old_info =
pan_afrc_get_format_info(old_format);
@ -1698,7 +1733,7 @@ panfrost_get_afbc_superblock_sizes(struct panfrost_context *ctx,
unsigned metadata_size = 0;
for (int level = first_level; level <= last_level; ++level) {
struct pan_image_slice_layout *slice = &rsrc->image.layout.slices[level];
struct pan_image_slice_layout *slice = &rsrc->plane.layout.slices[level];
unsigned sz = slice->afbc.nr_sblocks * sizeof(struct pan_afbc_block_info);
out_offsets[level - first_level] = metadata_size;
metadata_size += sz;
@ -1761,7 +1796,7 @@ panfrost_pack_afbc(struct panfrost_context *ctx,
for (unsigned level = 0; level <= last_level; ++level) {
struct pan_image_slice_layout *src_slice =
&prsrc->image.layout.slices[level];
&prsrc->plane.layout.slices[level];
struct pan_image_slice_layout *dst_slice = &slice_infos[level];
unsigned src_stride =
pan_afbc_stride_blocks(src_modifier, src_slice->row_stride_B);
@ -1857,10 +1892,10 @@ panfrost_pack_afbc(struct panfrost_context *ctx,
struct pan_image_slice_layout *slice = &slice_infos[level];
screen->vtbl.afbc_pack(batch, prsrc, dst, slice, metadata_bo,
metadata_offsets[level], level);
prsrc->image.layout.slices[level] = *slice;
prsrc->plane.layout.slices[level] = *slice;
}
prsrc->image.layout.array_stride_B = new_size;
prsrc->image.layout.data_size_B = new_size;
prsrc->plane.layout.array_stride_B = new_size;
prsrc->plane.layout.data_size_B = new_size;
panfrost_flush_batches_accessing_rsrc(ctx, prsrc, "AFBC compaction flush");
@ -1869,7 +1904,7 @@ panfrost_pack_afbc(struct panfrost_context *ctx,
prsrc->modifier = dst_modifier;
panfrost_bo_unreference(prsrc->bo);
prsrc->bo = dst;
prsrc->image.data.base = dst->ptr.gpu;
prsrc->plane.base = dst->ptr.gpu;
prsrc->image.props.crc = false;
prsrc->valid.crc = false;
panfrost_bo_unreference(metadata_bo);
@ -1904,10 +1939,10 @@ panfrost_ptr_unmap(struct pipe_context *pctx, struct pipe_transfer *transfer)
panfrost_bo_unreference(prsrc->bo);
panfrost_resource_setup(screen, prsrc, DRM_FORMAT_MOD_LINEAR,
prsrc->image.props.format);
prsrc->image.props.format, 0);
prsrc->bo = pan_resource(trans->staging.rsrc)->bo;
prsrc->image.data.base = prsrc->bo->ptr.gpu;
prsrc->plane.base = prsrc->bo->ptr.gpu;
panfrost_bo_reference(prsrc->bo);
} else {
bool discard = panfrost_can_discard(&prsrc->base, &transfer->box,
@ -1940,17 +1975,17 @@ panfrost_ptr_unmap(struct pipe_context *pctx, struct pipe_transfer *transfer)
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
if (panfrost_should_linear_convert(ctx, prsrc, transfer)) {
panfrost_resource_setup(screen, prsrc, DRM_FORMAT_MOD_LINEAR,
prsrc->image.props.format);
prsrc->image.props.format, 0);
/* converting the resource from tiled to linear and back
* shouldn't increase memory usage...
*/
assert(prsrc->image.layout.data_size_B <= panfrost_bo_size(bo));
assert(prsrc->plane.layout.data_size_B <= panfrost_bo_size(bo));
util_copy_rect(
bo->ptr.cpu + prsrc->image.layout.slices[0].offset_B,
bo->ptr.cpu + prsrc->plane.layout.slices[0].offset_B,
prsrc->base.format,
prsrc->image.layout.slices[0].row_stride_B, 0, 0,
prsrc->plane.layout.slices[0].row_stride_B, 0, 0,
transfer->box.width, transfer->box.height, trans->map,
transfer->stride, 0, 0);
} else {
@ -2031,10 +2066,24 @@ panfrost_set_image_view_planes(struct pan_image_view *iview,
struct pipe_resource *texture)
{
struct panfrost_resource *prsrc_plane = (struct panfrost_resource *)texture;
unsigned view_nplanes = util_format_get_num_planes(iview->format);
struct pan_image_plane_ref pref = {
.image = &prsrc_plane->image,
.plane_idx = pan_resource_plane_index(prsrc_plane),
};
for (int i = 0; i < MAX_IMAGE_PLANES && prsrc_plane; i++) {
iview->planes[i] = &prsrc_plane->image;
prsrc_plane = (struct panfrost_resource *)prsrc_plane->base.next;
if (view_nplanes > 1) {
assert(pref.plane_idx == 0);
assert(view_nplanes == util_format_get_num_planes(prsrc_plane->image.props.format));
for (int i = 0; i < view_nplanes; i++) {
iview->planes[i] = pref;
pref.plane_idx++;
prsrc_plane = (struct panfrost_resource *)prsrc_plane->base.next;
}
} else {
assert(pref.plane_idx <
util_format_get_num_planes(prsrc_plane->image.props.format));
iview->planes[0] = pref;
}
}

View file

@ -60,6 +60,7 @@ struct panfrost_resource {
/* Description of the resource layout */
struct pan_image image;
struct pan_image_plane plane;
/* In case of emulated modifiers, the image.props.modifier won't match this
* modifier. */
@ -98,6 +99,18 @@ pan_resource(struct pipe_resource *p)
return (struct panfrost_resource *)p;
}
static inline unsigned
pan_resource_plane_index(const struct panfrost_resource *rsc)
{
for (unsigned i = 0; i < ARRAY_SIZE(rsc->image.planes); i++) {
if (rsc->image.planes[i] == &rsc->plane)
return i;
}
assert(!"Invalid image props");
return 0;
}
struct panfrost_transfer {
struct pipe_transfer base;
void *map;
@ -184,11 +197,6 @@ panfrost_translate_texture_dimension(enum pipe_texture_target t)
}
}
struct pipe_resource *
panfrost_resource_create_with_modifier(struct pipe_screen *screen,
const struct pipe_resource *template,
uint64_t modifier);
bool panfrost_should_pack_afbc(struct panfrost_device *dev,
const struct panfrost_resource *rsrc);

View file

@ -286,7 +286,7 @@ panfrost_walk_dmabuf_modifiers(struct pipe_screen *screen,
continue;
if ((native_mods[i] & AFBC_FORMAT_MOD_SPLIT) &&
!pan_afbc_can_split(dev->arch, format, native_mods[i]))
!pan_afbc_can_split(dev->arch, format, native_mods[i], 0))
continue;
if ((native_mods[i] & AFBC_FORMAT_MOD_YTR) && !ytr)

View file

@ -299,8 +299,11 @@ pan_afbc_unswizzled_format(unsigned arch, enum pipe_format format)
* cannot be compressed. */
static inline enum pan_afbc_mode
pan_afbc_format(unsigned arch, enum pipe_format format)
pan_afbc_format(unsigned arch, enum pipe_format format, unsigned plane_idx)
{
/* Revisit when adding YUV support. */
assert(plane_idx == 0);
/* sRGB does not change the pixel format itself, only the
* interpretation. The interpretation is handled by conversion hardware
* independent to the compression hardware, so we can compress sRGB
@ -351,7 +354,14 @@ pan_afbc_format(unsigned arch, enum pipe_format format)
static inline bool
pan_format_supports_afbc(unsigned arch, enum pipe_format format)
{
return pan_afbc_format(arch, format) != PAN_AFBC_MODE_INVALID;
unsigned plane_count = util_format_get_num_planes(format);
for (unsigned i = 0; i < plane_count; i++) {
if (pan_afbc_format(arch, format, i) == PAN_AFBC_MODE_INVALID)
return false;
}
return true;
}
/* The lossless colour transform (AFBC_FORMAT_MOD_YTR) requires RGB. */
@ -370,7 +380,8 @@ pan_afbc_can_ytr(enum pipe_format format)
}
static inline bool
pan_afbc_can_split(unsigned arch, enum pipe_format format, uint64_t modifier)
pan_afbc_can_split(unsigned arch, enum pipe_format format, uint64_t modifier,
unsigned plane_idx)
{
unsigned block_width = pan_afbc_superblock_width(modifier);
@ -380,7 +391,7 @@ pan_afbc_can_split(unsigned arch, enum pipe_format format, uint64_t modifier)
if (block_width == 16) {
return true;
} else if (block_width == 32) {
enum pan_afbc_mode mode = pan_afbc_format(arch, format);
enum pan_afbc_mode mode = pan_afbc_format(arch, format, plane_idx);
return (mode == PAN_AFBC_MODE_R8G8B8A8 ||
mode == PAN_AFBC_MODE_R10G10B10A2);
}
@ -410,7 +421,7 @@ pan_afbc_can_tile(unsigned arch)
#if PAN_ARCH >= 9
static inline enum mali_afbc_compression_mode
pan_afbc_compression_mode(enum pipe_format format)
pan_afbc_compression_mode(enum pipe_format format, unsigned plane_idx)
{
/* There's a special case for texturing the stencil part from a combined
* depth/stencil texture, handle it separately.
@ -422,7 +433,7 @@ pan_afbc_compression_mode(enum pipe_format format)
* needs to handle the subset of formats returned by
* pan_afbc_format.
*/
switch (pan_afbc_format(PAN_ARCH, format)) {
switch (pan_afbc_format(PAN_ARCH, format, plane_idx)) {
case PAN_AFBC_MODE_R8:
return MALI_AFBC_COMPRESSION_MODE_R8;
case PAN_AFBC_MODE_R8G8:

View file

@ -71,11 +71,13 @@ mali_sampling_mode(const struct pan_image_view *view)
unsigned nr_samples = pan_image_view_get_nr_samples(view);
if (nr_samples > 1) {
ASSERTED const struct pan_image *first_plane =
ASSERTED const struct pan_image_plane_ref pref =
pan_image_view_get_first_plane(view);
ASSERTED const struct pan_image_plane *plane =
pref.image->planes[pref.plane_idx];
assert(view->nr_samples == nr_samples);
assert(first_plane->layout.slices[0].surface_stride_B != 0);
assert(view->nr_samples == pref.image->props.nr_samples);
assert(plane->layout.slices[0].surface_stride_B != 0);
return MALI_MSAA_LAYERED;
}
@ -94,8 +96,8 @@ static bool
renderblock_fits_in_single_pass(const struct pan_image_view *view,
unsigned tile_size)
{
const struct pan_image *first_plane = pan_image_view_get_first_plane(view);
uint64_t mod = first_plane->props.modifier;
const struct pan_image_plane_ref pref = pan_image_view_get_first_plane(view);
uint64_t mod = pref.image->props.modifier;
if (!drm_is_afbc(mod))
return tile_size >= 16 * 16;
@ -212,7 +214,9 @@ pan_prepare_s(const struct pan_fb_info *fb, unsigned layer_idx,
if (!s)
return;
const struct pan_image *image = pan_image_view_get_s_plane(s);
const struct pan_image_plane_ref pref = pan_image_view_get_s_plane(s);
const struct pan_image *image = pref.image;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
unsigned level = s->first_level;
ext->s_msaa = mali_sampling_mode(s);
@ -224,10 +228,10 @@ pan_prepare_s(const struct pan_fb_info *fb, unsigned layer_idx,
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||
image->props.modifier == DRM_FORMAT_MOD_LINEAR);
ext->s_writeback_base = surf.data;
ext->s_writeback_row_stride = image->layout.slices[level].row_stride_B;
ext->s_writeback_row_stride = plane->layout.slices[level].row_stride_B;
ext->s_writeback_surface_stride =
(pan_image_view_get_nr_samples(s) > 1)
? image->layout.slices[level].surface_stride_B
? plane->layout.slices[level].surface_stride_B
: 0;
ext->s_block_format = mod_to_block_fmt(image->props.modifier);
ext->s_write_format = translate_s_format(s->format);
@ -242,15 +246,16 @@ pan_prepare_zs(const struct pan_fb_info *fb, unsigned layer_idx,
if (!zs)
return;
const struct pan_image *image = pan_image_view_get_zs_plane(zs);
const struct pan_image_plane_ref pref = pan_image_view_get_zs_plane(zs);
const struct pan_image *image = pref.image;
unsigned level = zs->first_level;
ext->zs_msaa = mali_sampling_mode(zs);
struct pan_image_surface surf;
pan_iview_get_surface(zs, 0, layer_idx, 0, &surf);
UNUSED const struct pan_image_slice_layout *slice =
&image->layout.slices[level];
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
const struct pan_image_slice_layout *slice = &plane->layout.slices[level];
if (drm_is_afbc(image->props.modifier)) {
#if PAN_ARCH >= 9
@ -282,11 +287,9 @@ pan_prepare_zs(const struct pan_fb_info *fb, unsigned layer_idx,
/* TODO: Z32F(S8) support, which is always linear */
ext->zs_writeback_base = surf.data;
ext->zs_writeback_row_stride = image->layout.slices[level].row_stride_B;
ext->zs_writeback_row_stride = slice->row_stride_B;
ext->zs_writeback_surface_stride =
(pan_image_view_get_nr_samples(zs) > 1)
? image->layout.slices[level].surface_stride_B
: 0;
(pan_image_view_get_nr_samples(zs) > 1) ? slice->surface_stride_B : 0;
}
ext->zs_block_format = mod_to_block_fmt(image->props.modifier);
@ -305,11 +308,13 @@ pan_prepare_crc(const struct pan_fb_info *fb, int rt_crc,
assert(rt_crc < fb->rt_count);
const struct pan_image_view *rt = fb->rts[rt_crc].view;
const struct pan_image *image = pan_image_view_get_color_plane(rt);
const struct pan_image_plane_ref pref = pan_image_view_get_color_plane(rt);
const struct pan_image *image = pref.image;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
const struct pan_image_slice_layout *slice =
&image->layout.slices[rt->first_level];
&plane->layout.slices[rt->first_level];
ext->crc_base = image->data.base + slice->crc.offset_B;
ext->crc_base = plane->base + slice->crc.offset_B;
ext->crc_row_stride = slice->crc.stride_B;
#if PAN_ARCH >= 7
@ -527,7 +532,8 @@ pan_rt_init_format(const struct pan_image_view *rt,
}
#if PAN_ARCH >= 10
const struct pan_image *image = pan_image_view_get_color_plane(rt);
const struct pan_image_plane_ref pref = pan_image_view_get_color_plane(rt);
const struct pan_image *image = pref.image;
if (drm_is_afrc(image->props.modifier))
cfg->afrc.writeback_format = writeback_format;
@ -551,8 +557,9 @@ pan_prepare_rt(const struct pan_fb_info *fb, unsigned layer_idx,
#if PAN_ARCH >= 6
bool force_clean_writes = fb->rts[rt_idx].clear;
if (fb->rts[rt_idx].view) {
const struct pan_image *img =
const struct pan_image_plane_ref pref =
pan_image_view_get_color_plane(fb->rts[rt_idx].view);
const struct pan_image *img = pref.image;
force_clean_writes |= pan_force_clean_write_on(img, fb->tile_size);
}
cfg->clean_pixel_write_enable = force_clean_writes;
@ -578,28 +585,29 @@ pan_prepare_rt(const struct pan_fb_info *fb, unsigned layer_idx,
return;
}
const struct pan_image *image = pan_image_view_get_color_plane(rt);
struct pan_image_plane_ref pref = pan_image_view_get_color_plane(rt);
const struct pan_image *image = pref.image;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
if (!drm_is_afrc(image->props.modifier))
cfg->write_enable = true;
cfg->dithering_enable = true;
const struct pan_image *first_plane = pan_image_view_get_first_plane(rt);
unsigned level = rt->first_level;
ASSERTED unsigned layer_count = rt->dim == MALI_TEXTURE_DIMENSION_3D
? first_plane->props.extent_px.depth
? image->props.extent_px.depth
: rt->last_layer - rt->first_layer + 1;
assert(rt->last_level == rt->first_level);
assert(layer_idx < layer_count);
int row_stride_B = image->layout.slices[level].row_stride_B;
int row_stride_B = plane->layout.slices[level].row_stride_B;
/* Only set layer_stride for layered MSAA rendering */
unsigned layer_stride_B = (pan_image_view_get_nr_samples(rt) > 1)
? image->layout.slices[level].surface_stride_B
? plane->layout.slices[level].surface_stride_B
: 0;
cfg->writeback_msaa = mali_sampling_mode(rt);
@ -622,10 +630,10 @@ pan_prepare_rt(const struct pan_fb_info *fb, unsigned layer_idx,
cfg->afbc.body_offset = surf.afbc.body - surf.afbc.header;
assert(surf.afbc.body >= surf.afbc.header);
cfg->afbc.compression_mode = pan_afbc_compression_mode(rt->format);
cfg->afbc.compression_mode = pan_afbc_compression_mode(rt->format, 0);
cfg->afbc.row_stride = row_stride_B;
#else
const struct pan_image_slice_layout *slice = &image->layout.slices[level];
const struct pan_image_slice_layout *slice = &plane->layout.slices[level];
#if PAN_ARCH >= 6
cfg->afbc.row_stride =
@ -806,20 +814,21 @@ pan_force_clean_write(const struct pan_fb_info *fb, unsigned tile_size)
if (!fb->rts[i].view || fb->rts[i].discard)
continue;
const struct pan_image *img =
const struct pan_image_plane_ref pref =
pan_image_view_get_color_plane(fb->rts[i].view);
const struct pan_image *img = pref.image;
if (pan_force_clean_write_on(img, tile_size))
return true;
}
if (fb->zs.view.zs && !fb->zs.discard.z &&
pan_force_clean_write_on(pan_image_view_get_zs_plane(fb->zs.view.zs),
tile_size))
pan_force_clean_write_on(
pan_image_view_get_zs_plane(fb->zs.view.zs).image, tile_size))
return true;
if (fb->zs.view.s && !fb->zs.discard.s &&
pan_force_clean_write_on(pan_image_view_get_s_plane(fb->zs.view.s),
pan_force_clean_write_on(pan_image_view_get_s_plane(fb->zs.view.s).image,
tile_size))
return true;
@ -923,7 +932,7 @@ GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx,
#if PAN_ARCH >= 6
clean_tile_write |= pan_force_clean_write_on(
pan_image_view_get_color_plane(fb->rts[crc_rt].view),
pan_image_view_get_color_plane(fb->rts[crc_rt].view).image,
fb->tile_size);
#endif
@ -1054,7 +1063,10 @@ GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx,
if (fb->rt_count && fb->rts[0].view) {
const struct pan_image_view *rt = fb->rts[0].view;
const struct pan_image *image = pan_image_view_get_color_plane(rt);
const struct pan_image_plane_ref pref =
pan_image_view_get_color_plane(rt);
const struct pan_image *image = pref.image;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
const struct util_format_description *desc =
util_format_description(rt->format);
@ -1086,7 +1098,7 @@ GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx,
cfg.color_write_enable = !fb->rts[0].discard;
cfg.color_writeback.base = surf.data;
cfg.color_writeback.row_stride =
image->layout.slices[level].row_stride_B;
plane->layout.slices[level].row_stride_B;
cfg.color_block_format = mod_to_block_fmt(image->props.modifier);
assert(cfg.color_block_format == MALI_BLOCK_FORMAT_LINEAR ||
@ -1095,16 +1107,19 @@ GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx,
if (pan_image_view_has_crc(rt)) {
const struct pan_image_slice_layout *slice =
&image->layout.slices[level];
&plane->layout.slices[level];
cfg.crc_buffer.row_stride = slice->crc.stride_B;
cfg.crc_buffer.base = image->data.base + slice->crc.offset_B;
cfg.crc_buffer.base = plane->base + slice->crc.offset_B;
}
}
if (fb->zs.view.zs) {
const struct pan_image_view *zs = fb->zs.view.zs;
const struct pan_image *image = pan_image_view_get_zs_plane(zs);
const struct pan_image_plane_ref pref =
pan_image_view_get_zs_plane(zs);
const struct pan_image *image = pref.image;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
unsigned level = zs->first_level;
struct pan_image_surface surf;
@ -1112,7 +1127,7 @@ GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx,
cfg.zs_write_enable = !fb->zs.discard.z;
cfg.zs_writeback.base = surf.data;
cfg.zs_writeback.row_stride = image->layout.slices[level].row_stride_B;
cfg.zs_writeback.row_stride = plane->layout.slices[level].row_stride_B;
cfg.zs_block_format = mod_to_block_fmt(image->props.modifier);
assert(cfg.zs_block_format == MALI_BLOCK_FORMAT_LINEAR ||
cfg.zs_block_format == MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED);

View file

@ -21,14 +21,19 @@
extern "C" {
#endif
struct pan_image_mem {
struct pan_image_plane {
struct pan_image_layout layout;
uint64_t base;
};
struct pan_image {
struct pan_image_mem data;
struct pan_image_props props;
struct pan_image_layout layout;
struct pan_image_plane *planes[MAX_IMAGE_PLANES];
};
struct pan_image_plane_ref {
struct pan_image *image;
uint32_t plane_idx;
};
struct pan_image_surface {
@ -52,7 +57,7 @@ struct pan_image_view {
unsigned char swizzle[4];
/* planes 1 and 2 are NULL for single plane formats */
const struct pan_image *planes[MAX_IMAGE_PLANES];
struct pan_image_plane_ref planes[MAX_IMAGE_PLANES];
/* If EXT_multisampled_render_to_texture is used, this may be
* greater than image->layout.nr_samples. */
@ -64,11 +69,11 @@ struct pan_image_view {
} astc;
};
static inline const struct pan_image *
static inline struct pan_image_plane_ref
pan_image_view_get_plane(const struct pan_image_view *iview, uint32_t idx)
{
if (idx >= ARRAY_SIZE(iview->planes))
return NULL;
return (struct pan_image_plane_ref){0};
return iview->planes[idx];
}
@ -79,7 +84,7 @@ pan_image_view_get_plane_mask(const struct pan_image_view *iview)
unsigned mask = 0;
for (unsigned i = 0; i < ARRAY_SIZE(iview->planes); i++) {
if (iview->planes[i])
if (iview->planes[i].image)
mask |= BITFIELD_BIT(i);
}
@ -95,7 +100,7 @@ pan_image_view_get_first_plane_idx(const struct pan_image_view *iview)
return ffs(mask) - 1;
}
static inline const struct pan_image *
static inline struct pan_image_plane_ref
pan_image_view_get_first_plane(const struct pan_image_view *iview)
{
unsigned first_plane_idx = pan_image_view_get_first_plane_idx(iview);
@ -105,34 +110,34 @@ pan_image_view_get_first_plane(const struct pan_image_view *iview)
static inline uint32_t
pan_image_view_get_nr_samples(const struct pan_image_view *iview)
{
const struct pan_image *image = pan_image_view_get_first_plane(iview);
const struct pan_image_plane_ref pref = pan_image_view_get_first_plane(iview);
if (!image)
if (!pref.image)
return 0;
return image->props.nr_samples;
return pref.image->props.nr_samples;
}
static inline const struct pan_image *
static inline const struct pan_image_plane_ref
pan_image_view_get_color_plane(const struct pan_image_view *iview)
{
/* We only support rendering to plane 0 */
assert(pan_image_view_get_plane(iview, 1) == NULL);
assert(pan_image_view_get_plane(iview, 1).image == NULL);
return pan_image_view_get_plane(iview, 0);
}
static inline bool
pan_image_view_has_crc(const struct pan_image_view *iview)
{
const struct pan_image *image = pan_image_view_get_color_plane(iview);
const struct pan_image_plane_ref p = pan_image_view_get_color_plane(iview);
if (!image)
if (!p.image)
return false;
return image->props.crc;
return p.image->props.crc;
}
static inline const struct pan_image *
static inline struct pan_image_plane_ref
pan_image_view_get_s_plane(const struct pan_image_view *iview)
{
ASSERTED const struct util_format_description *fdesc =
@ -143,15 +148,16 @@ pan_image_view_get_s_plane(const struct pan_image_view *iview)
* plane 1. Combined depth/stencil only has one plane, so depth
* will be on plane 0 in either case.
*/
const struct pan_image *plane = iview->planes[1] ?: iview->planes[0];
const struct pan_image_plane_ref pref =
iview->planes[1].image ? iview->planes[1] : iview->planes[0];
assert(plane);
fdesc = util_format_description(plane->props.format);
assert(pref.image);
fdesc = util_format_description(pref.image->props.format);
assert(util_format_has_stencil(fdesc));
return plane;
return pref;
}
static inline const struct pan_image *
static inline struct pan_image_plane_ref
pan_image_view_get_zs_plane(const struct pan_image_view *iview)
{
assert(util_format_is_depth_or_stencil(iview->format));
@ -172,9 +178,10 @@ pan_iview_get_surface(const struct pan_image_view *iview, unsigned level,
* plane 1. Combined depth/stencil only has one plane, so depth
* will be on plane 0 in either case.
*/
const struct pan_image *image = util_format_has_stencil(fdesc)
? pan_image_view_get_s_plane(iview)
: pan_image_view_get_plane(iview, 0);
const struct pan_image_plane_ref pref =
util_format_has_stencil(fdesc) ? pan_image_view_get_s_plane(iview)
: pan_image_view_get_plane(iview, 0);
const struct pan_image *image = pref.image;
level += iview->first_level;
assert(level < image->props.nr_slices);
@ -182,8 +189,9 @@ pan_iview_get_surface(const struct pan_image_view *iview, unsigned level,
layer += iview->first_layer;
bool is_3d = image->props.dim == MALI_TEXTURE_DIMENSION_3D;
const struct pan_image_slice_layout *slice = &image->layout.slices[level];
uint64_t base = image->data.base;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
const struct pan_image_slice_layout *slice = &plane->layout.slices[level];
uint64_t base = plane->base;
memset(surf, 0, sizeof(*surf));
@ -201,14 +209,14 @@ pan_iview_get_surface(const struct pan_image_view *iview, unsigned level,
} else {
assert(layer < image->props.array_size);
surf->afbc.header =
base + pan_image_surface_offset(&image->layout, level, layer, 0);
base + pan_image_surface_offset(&plane->layout, level, layer, 0);
surf->afbc.body = surf->afbc.header + slice->afbc.header_size_B;
}
} else {
unsigned array_idx = is_3d ? 0 : layer;
unsigned surface_idx = is_3d ? layer : sample;
surf->data = base + pan_image_surface_offset(&image->layout, level,
surf->data = base + pan_image_surface_offset(&plane->layout, level,
array_idx, surface_idx);
}
}

View file

@ -39,10 +39,16 @@
static inline struct pan_image_block_size
pan_u_interleaved_tile_size_el(enum pipe_format format)
{
if (util_format_is_compressed(format))
if (util_format_is_compressed(format)) {
return (struct pan_image_block_size){4, 4};
else
return (struct pan_image_block_size){16, 16};
} else {
assert(16 % util_format_get_blockwidth(format) == 0);
assert(16 % util_format_get_blockheight(format) == 0);
return (struct pan_image_block_size){
.width = 16 / util_format_get_blockwidth(format),
.height = 16 / util_format_get_blockheight(format),
};
}
}
/*
@ -51,16 +57,31 @@ pan_u_interleaved_tile_size_el(enum pipe_format format)
* paging tile size. For linear textures, this is trivially 1x1.
*/
struct pan_image_block_size
pan_image_block_size_el(uint64_t modifier, enum pipe_format format)
pan_image_block_size_el(uint64_t modifier, enum pipe_format format,
unsigned plane_idx)
{
if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
return pan_u_interleaved_tile_size_el(format);
else if (drm_is_afbc(modifier))
return pan_afbc_superblock_size(modifier);
else if (drm_is_afrc(modifier))
} else if (drm_is_afbc(modifier)) {
struct pan_image_block_size sb_size_px =
pan_afbc_superblock_size(modifier);
assert(sb_size_px.width % util_format_get_blockwidth(format) == 0);
assert(sb_size_px.height % util_format_get_blockheight(format) == 0);
return (struct pan_image_block_size){
.width = sb_size_px.width / util_format_get_blockwidth(format),
.height = sb_size_px.height / util_format_get_blockheight(format),
};
} else if (drm_is_afrc(modifier)) {
assert(util_format_get_blockwidth(format) == 1 &&
util_format_get_blockheight(format) == 1);
return pan_afrc_tile_size(format, modifier);
else
} else {
assert(util_format_is_compressed(format) ||
util_format_get_blockheight(format) == 1);
return (struct pan_image_block_size){1, 1};
}
}
/* For non-AFBC and non-wide AFBC, the render block size matches
@ -68,12 +89,21 @@ pan_image_block_size_el(uint64_t modifier, enum pipe_format format)
* to be 16 pixels high.
*/
struct pan_image_block_size
pan_image_renderblock_size_el(uint64_t modifier, enum pipe_format format)
pan_image_renderblock_size_el(uint64_t modifier, enum pipe_format format,
unsigned plane_idx)
{
if (!drm_is_afbc(modifier))
return pan_image_block_size_el(modifier, format);
return pan_image_block_size_el(modifier, format, plane_idx);
return pan_afbc_renderblock_size(modifier);
struct pan_image_block_size rb_size_px = pan_afbc_renderblock_size(modifier);
assert(rb_size_px.width % util_format_get_blockwidth(format) == 0);
assert(rb_size_px.height % util_format_get_blockheight(format) == 0);
return (struct pan_image_block_size){
.width = rb_size_px.width / util_format_get_blockwidth(format),
.height = rb_size_px.height / util_format_get_blockheight(format),
};
}
static unsigned
@ -150,28 +180,55 @@ pan_image_surface_stride(const struct pan_image_props *props,
return layout->slices[level].surface_stride_B;
}
static unsigned
get_plane_blocksize(enum pipe_format format, unsigned plane_idx)
{
switch (format) {
case PIPE_FORMAT_R8G8_R8B8_UNORM:
case PIPE_FORMAT_G8R8_B8R8_UNORM:
case PIPE_FORMAT_R8B8_R8G8_UNORM:
case PIPE_FORMAT_B8R8_G8R8_UNORM:
return 2;
case PIPE_FORMAT_R8_G8B8_420_UNORM:
case PIPE_FORMAT_R8_B8G8_420_UNORM:
case PIPE_FORMAT_R8_G8B8_422_UNORM:
case PIPE_FORMAT_R8_B8G8_422_UNORM:
return plane_idx ? 2 : 1;
case PIPE_FORMAT_R10_G10B10_420_UNORM:
case PIPE_FORMAT_R10_G10B10_422_UNORM:
return plane_idx ? 10 : 5;
case PIPE_FORMAT_R8_G8_B8_420_UNORM:
case PIPE_FORMAT_R8_B8_G8_420_UNORM:
return 1;
default:
assert(util_format_get_num_planes(format) == 1);
return util_format_get_blocksize(format);
}
}
struct pan_image_wsi_layout
pan_image_layout_get_wsi_layout(const struct pan_image_props *props,
unsigned plane_idx,
const struct pan_image_layout *layout,
unsigned level)
{
unsigned row_stride_B = layout->slices[level].row_stride_B;
struct pan_image_block_size block_size_el =
pan_image_renderblock_size_el(props->modifier, props->format);
pan_image_renderblock_size_el(props->modifier, props->format, plane_idx);
if (drm_is_afbc(props->modifier)) {
struct pan_image_block_size afbc_tile_extent_px =
pan_afbc_superblock_size(props->modifier);
struct pan_image_block_size afbc_tile_extent_el =
pan_image_block_size_el(props->modifier, props->format, plane_idx);
unsigned afbc_tile_payload_size_B =
afbc_tile_extent_px.width * afbc_tile_extent_px.height *
util_format_get_blocksize(props->format);
afbc_tile_extent_el.width * afbc_tile_extent_el.height *
get_plane_blocksize(props->format, plane_idx);
unsigned afbc_tile_row_payload_size_B =
pan_afbc_stride_blocks(props->modifier, row_stride_B) *
afbc_tile_payload_size_B;
return (struct pan_image_wsi_layout){
.offset_B = layout->slices[level].offset_B,
.row_pitch_B = afbc_tile_row_payload_size_B /
afbc_tile_extent_px.height,
pan_afbc_superblock_height(props->modifier),
};
} else if (drm_is_afrc(props->modifier)) {
struct pan_image_block_size tile_size_px =
@ -191,6 +248,7 @@ pan_image_layout_get_wsi_layout(const struct pan_image_props *props,
static bool
wsi_row_pitch_to_row_stride(unsigned arch, const struct pan_image_props *props,
unsigned plane_idx,
const struct pan_image_wsi_layout *wsi_layout,
unsigned *row_stride_B)
{
@ -200,15 +258,20 @@ wsi_row_pitch_to_row_stride(unsigned arch, const struct pan_image_props *props,
uint64_t modifier = props->modifier;
if (drm_is_afbc(modifier)) {
/* We assume single pixel blocks in AFBC. */
assert(util_format_get_blockwidth(format) == 1 &&
util_format_get_blockheight(format) == 1);
struct pan_image_block_size afbc_tile_extent_px =
pan_afbc_renderblock_size(modifier);
unsigned afbc_tile_payload_size_B = afbc_tile_extent_px.width *
afbc_tile_extent_px.height *
util_format_get_blocksize(format);
pan_afbc_superblock_size(modifier);
/* YUV packed formats can have a block extent bigger than one pixel,
* but the block extent must be a multiple of the tile extent. */
assert(
!(afbc_tile_extent_px.width % util_format_get_blockwidth(format)) &&
!(afbc_tile_extent_px.height % util_format_get_blockheight(format)));
unsigned pixels_per_blk = util_format_get_blockwidth(format) *
util_format_get_blockheight(format);
unsigned pixels_per_tile = afbc_tile_extent_px.width *
afbc_tile_extent_px.height;
unsigned blks_per_tile = pixels_per_tile / pixels_per_blk;
unsigned afbc_tile_payload_size_B =
blks_per_tile * get_plane_blocksize(format, plane_idx);
unsigned afbc_tile_payload_row_stride_B =
wsi_row_pitch_B * afbc_tile_extent_px.height;
@ -244,16 +307,26 @@ wsi_row_pitch_to_row_stride(unsigned arch, const struct pan_image_props *props,
width_px = (*row_stride_B / afrc_blk_size_B) * tile_size_px.width;
} else {
struct pan_image_block_size block_size_el =
pan_image_renderblock_size_el(modifier, format);
unsigned tile_size_B = block_size_el.width * block_size_el.height *
util_format_get_blocksize(format);
pan_image_renderblock_size_el(modifier, format, plane_idx);
/* The row_stride_B -> width_px conversion is assuming a 1x1 pixel
* block size for non-compressed formats. Revisit when adding support
* for block-based YUV. */
assert(util_format_is_compressed(format) ||
(util_format_get_blockwidth(format) == 1 &&
util_format_get_blockheight(format) == 1));
if (!util_format_is_compressed(format)) {
/* Block-based YUV needs special care, because the U-tile extent
* is in pixels, not blocks in that case. */
if (block_size_el.width * block_size_el.height > 1) {
assert(block_size_el.width % util_format_get_blockwidth(format) ==
0);
block_size_el.width /= util_format_get_blockwidth(format);
assert(block_size_el.height % util_format_get_blockheight(format) ==
0);
block_size_el.height /= util_format_get_blockheight(format);
} else {
block_size_el.width = util_format_get_blockwidth(format);
assert(util_format_get_blockheight(format) == 1);
}
}
unsigned tile_size_B = block_size_el.width * block_size_el.height *
get_plane_blocksize(format, plane_idx);
row_align_mask =
linear_or_tiled_row_align_req(arch, format, modifier) - 1;
@ -273,7 +346,9 @@ wsi_row_pitch_to_row_stride(unsigned arch, const struct pan_image_props *props,
return false;
}
if (width_px < props->extent_px.width) {
unsigned min_width_px =
util_format_get_plane_width(format, plane_idx, props->extent_px.width);
if (width_px < min_width_px) {
mesa_loge("WSI pitch too small");
return false;
}
@ -295,6 +370,7 @@ pan_image_surface_offset(const struct pan_image_layout *layout, unsigned level,
bool
pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
unsigned plane_idx,
const struct pan_image_wsi_layout *wsi_layout,
struct pan_image_layout *layout)
{
@ -307,6 +383,9 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
props->nr_slices > 1 || props->crc))
return false;
if (plane_idx >= util_format_get_num_planes(props->format))
return false;
bool afbc = drm_is_afbc(props->modifier);
bool afrc = drm_is_afrc(props->modifier);
int align_req_B =
@ -320,14 +399,15 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
/* Mandate alignment */
if (wsi_layout) {
if (!wsi_row_pitch_to_row_stride(arch, props, wsi_layout,
if (!wsi_row_pitch_to_row_stride(arch, props, plane_idx, wsi_layout,
&wsi_row_stride_B))
return false;
offset_B = wsi_layout->offset_B;
}
unsigned fmt_blocksize_B = util_format_get_blocksize(props->format);
unsigned fmt_blocksize_B =
get_plane_blocksize(props->format, plane_idx);
/* MSAA is implemented as a 3D texture with z corresponding to the
* sample #, horrifyingly enough */
@ -338,12 +418,16 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
bool is_3d = props->dim == MALI_TEXTURE_DIMENSION_3D;
struct pan_image_block_size renderblk_size_el =
pan_image_renderblock_size_el(props->modifier, props->format);
pan_image_renderblock_size_el(props->modifier, props->format, plane_idx);
struct pan_image_block_size block_size_el =
pan_image_block_size_el(props->modifier, props->format);
pan_image_block_size_el(props->modifier, props->format, plane_idx);
unsigned width_px = props->extent_px.width;
unsigned height_px = props->extent_px.height;
unsigned width_px = util_format_get_plane_width(props->format, plane_idx,
props->extent_px.width);
unsigned height_px = util_format_get_plane_height(props->format, plane_idx,
props->extent_px.height);
unsigned blk_width_px = util_format_get_blockwidth(props->format);
unsigned blk_height_px = util_format_get_blockheight(props->format);
unsigned depth_px = props->extent_px.depth;
unsigned align_w_el = renderblk_size_el.width;
@ -358,10 +442,12 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
for (unsigned l = 0; l < props->nr_slices; ++l) {
struct pan_image_slice_layout *slice = &layout->slices[l];
unsigned effective_width_el = ALIGN_POT(
util_format_get_nblocksx(props->format, width_px), align_w_el);
unsigned effective_height_el = ALIGN_POT(
util_format_get_nblocksy(props->format, height_px), align_h_el);
unsigned effective_width_el =
ALIGN_POT(DIV_ROUND_UP(width_px, blk_width_px), align_w_el);
unsigned effective_height_el =
ALIGN_POT(DIV_ROUND_UP(height_px, blk_height_px), align_h_el);
unsigned effective_width_px = effective_width_el * blk_width_px;
unsigned effective_height_px = effective_height_el * blk_height_px;
unsigned row_stride_B;
/* Align levels to cache-line as a performance improvement for
@ -374,7 +460,7 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
if (afrc) {
row_stride_B = pan_afrc_row_stride(props->format, props->modifier,
effective_width_el);
effective_width_px);
} else {
row_stride_B =
fmt_blocksize_B * effective_width_el * block_size_el.height;
@ -403,7 +489,7 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
/* Compute AFBC sizes if necessary */
if (afbc) {
slice->row_stride_B =
pan_afbc_row_stride(props->modifier, effective_width_el);
pan_afbc_row_stride(props->modifier, effective_width_px);
/* Explicit stride should be rejected by wsi_row_pitch_to_row_stride()
* if it's too small. */
@ -417,7 +503,7 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
slice->afbc.stride_sb =
pan_afbc_stride_blocks(props->modifier, slice->row_stride_B);
slice->afbc.nr_sblocks = slice->afbc.stride_sb *
(effective_height_el / block_size_el.height);
(effective_height_px / block_size_el.height);
slice->afbc.header_size_B =
ALIGN_POT(slice->afbc.nr_sblocks * AFBC_HEADER_BYTES_PER_TILE,
pan_afbc_body_align(arch, props->modifier));

View file

@ -121,10 +121,12 @@ pan_image_slice_align(uint64_t modifier)
}
struct pan_image_block_size pan_image_block_size_el(uint64_t modifier,
enum pipe_format format);
enum pipe_format format,
unsigned plane_idx);
struct pan_image_block_size
pan_image_renderblock_size_el(uint64_t modifier, enum pipe_format format);
pan_image_renderblock_size_el(uint64_t modifier, enum pipe_format format,
unsigned plane_idx);
unsigned pan_image_surface_stride(const struct pan_image_props *props,
const struct pan_image_layout *layout,
@ -149,11 +151,13 @@ pan_image_mip_level_size(const struct pan_image_props *props,
}
bool pan_image_layout_init(unsigned arch, const struct pan_image_props *props,
unsigned plane_idx,
const struct pan_image_wsi_layout *wsi_layout,
struct pan_image_layout *layout);
struct pan_image_wsi_layout
pan_image_layout_get_wsi_layout(const struct pan_image_props *props,
unsigned plane_idx,
const struct pan_image_layout *layout,
unsigned level);

View file

@ -165,7 +165,7 @@ GENX(pan_texture_estimate_payload_size)(const struct pan_image_view *iview)
element_size = pan_size(PLANE);
/* 2-plane and 3-plane YUV use two plane descriptors. */
if (pan_format_is_yuv(iview->format) && iview->planes[1] != NULL)
if (pan_format_is_yuv(iview->format) && iview->planes[1].image != NULL)
element_size *= 2;
#elif PAN_ARCH == 7
if (pan_format_is_yuv(iview->format))
@ -227,28 +227,30 @@ struct pan_image_section_info {
static struct pan_image_section_info
get_image_section_info(const struct pan_image_view *iview,
const struct pan_image *plane, unsigned level,
const struct pan_image_plane_ref pref, unsigned level,
unsigned index, unsigned sample)
{
const struct util_format_description *desc =
util_format_description(iview->format);
uint64_t base = plane->data.base;
const struct pan_image *image = pref.image;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
uint64_t base = plane->base;
struct pan_image_section_info info = {0};
/* v4 does not support compression */
assert(PAN_ARCH >= 5 || !drm_is_afbc(plane->props.modifier));
assert(PAN_ARCH >= 5 || !drm_is_afbc(image->props.modifier));
assert(PAN_ARCH >= 5 || desc->layout != UTIL_FORMAT_LAYOUT_ASTC);
/* pan_compression_tag() wants the dimension of the resource, not the
* one of the image view (those might differ).
*/
unsigned tag =
pan_compression_tag(desc, plane->props.dim, plane->props.modifier);
pan_compression_tag(desc, image->props.dim, image->props.modifier);
info.pointer =
pan_get_surface_pointer(&plane->props, &plane->layout, iview->dim,
pan_get_surface_pointer(&image->props, &plane->layout, iview->dim,
base | tag, level, index, sample);
pan_get_surface_strides(&plane->props, &plane->layout, level,
pan_get_surface_strides(&image->props, &plane->layout, level,
&info.row_stride, &info.surface_stride);
return info;
@ -475,12 +477,14 @@ pan_emit_iview_plane(const struct pan_image_view *iview,
{
const struct util_format_description *desc =
util_format_description(iview->format);
const struct pan_image *plane =
const struct pan_image_plane_ref pref =
util_format_has_stencil(desc)
? pan_image_view_get_s_plane(iview)
: pan_image_view_get_plane(iview, plane_index);
const struct pan_image *image = pref.image;
const struct pan_image_plane *plane = image->planes[pref.plane_idx];
const struct pan_image_layout *layout = &plane->layout;
const struct pan_image_props *props = &plane->props;
const struct pan_image_props *props = &image->props;
int32_t row_stride = sections[plane_index].row_stride;
int32_t surface_stride = sections[plane_index].surface_stride;
uint64_t pointer = sections[plane_index].pointer;
@ -553,7 +557,8 @@ pan_emit_iview_plane(const struct pan_image_view *iview,
cfg.afbc.split_block = (props->modifier & AFBC_FORMAT_MOD_SPLIT);
cfg.afbc.tiled_header = (props->modifier & AFBC_FORMAT_MOD_TILED);
cfg.afbc.prefetch = true;
cfg.afbc.compression_mode = pan_afbc_compression_mode(iview->format);
cfg.afbc.compression_mode =
pan_afbc_compression_mode(iview->format, 0);
cfg.afbc.header_stride = layout->slices[level].afbc.header_size_B;
} else if (afrc) {
#if PAN_ARCH >= 10
@ -593,13 +598,14 @@ pan_emit_iview_surface(const struct pan_image_view *iview, unsigned level,
unsigned plane_count = 0;
for (int i = 0; i < MAX_IMAGE_PLANES; i++) {
const struct pan_image *plane = pan_image_view_get_plane(iview, i);
const struct pan_image_plane_ref pref =
pan_image_view_get_plane(iview, i);
if (!plane)
if (!pref.image)
break;
sections[i] =
get_image_section_info(iview, plane, level, index, sample);
get_image_section_info(iview, pref, level, index, sample);
plane_count++;
}
@ -631,13 +637,13 @@ pan_emit_iview_surface(const struct pan_image_view *iview, unsigned level,
* plane 1. Combined depth/stencil only has one plane, so depth
* will be on plane 0 in either case.
*/
const struct pan_image *plane = util_format_has_stencil(fdesc)
? pan_image_view_get_s_plane(iview)
: pan_image_view_get_plane(iview, 0);
assert(plane != NULL);
const struct pan_image_plane_ref pref =
util_format_has_stencil(fdesc) ? pan_image_view_get_s_plane(iview)
: pan_image_view_get_plane(iview, 0);
assert(pref.image != NULL);
struct pan_image_section_info section[1] = {
get_image_section_info(iview, plane, level, index, sample),
get_image_section_info(iview, pref, level, index, sample),
};
#if PAN_ARCH >= 9
@ -782,7 +788,7 @@ pan_texture_get_array_size(const struct pan_image_view *iview)
/* Multiplanar YUV textures require 2 surface descriptors. */
if (pan_format_is_yuv(iview->format) && PAN_ARCH >= 9 &&
pan_image_view_get_plane(iview, 1) != NULL)
pan_image_view_get_plane(iview, 1).image != NULL)
array_size *= 2;
return array_size;
@ -831,8 +837,8 @@ GENX(pan_sampled_texture_emit)(const struct pan_image_view *iview,
{
const struct util_format_description *desc =
util_format_description(iview->format);
const struct pan_image *first_plane = pan_image_view_get_first_plane(iview);
const struct pan_image_props *props = &first_plane->props;
const struct pan_image_plane_ref first_plane = pan_image_view_get_first_plane(iview);
const struct pan_image_props *props = &first_plane.image->props;
uint32_t mali_format = GENX(pan_format_from_pipe_format)(iview->format)->hw;
if (desc->layout == UTIL_FORMAT_LAYOUT_ASTC && iview->astc.narrow &&
@ -886,8 +892,9 @@ GENX(pan_storage_texture_emit)(const struct pan_image_view *iview,
{
const struct util_format_description *desc =
util_format_description(iview->format);
const struct pan_image *first_plane = pan_image_view_get_first_plane(iview);
const struct pan_image_props *props = &first_plane->props;
const struct pan_image_plane_ref first_plane =
pan_image_view_get_first_plane(iview);
const struct pan_image_props *props = &first_plane.image->props;
/* AFBC and AFRC cannot be used in storage operations. */
assert(!drm_is_afbc(props->modifier));

View file

@ -37,7 +37,7 @@ TEST(BlockSize, Linear)
for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) {
struct pan_image_block_size blk =
pan_image_block_size_el(DRM_FORMAT_MOD_LINEAR, format[i]);
pan_image_block_size_el(DRM_FORMAT_MOD_LINEAR, format[i], 0);
EXPECT_EQ(blk.width, 1);
EXPECT_EQ(blk.height, 1);
@ -53,7 +53,7 @@ TEST(BlockSize, UInterleavedRegular)
for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) {
struct pan_image_block_size blk = pan_image_block_size_el(
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, format[i]);
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, format[i], 0);
EXPECT_EQ(blk.width, 16);
EXPECT_EQ(blk.height, 16);
@ -66,7 +66,7 @@ TEST(BlockSize, UInterleavedBlockCompressed)
for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) {
struct pan_image_block_size blk = pan_image_block_size_el(
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, format[i]);
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, format[i], 0);
EXPECT_EQ(blk.width, 4);
EXPECT_EQ(blk.height, 4);
@ -84,7 +84,7 @@ TEST(BlockSize, AFBCFormatInvariant16x16)
for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) {
struct pan_image_block_size blk =
pan_image_block_size_el(modifier, format[i]);
pan_image_block_size_el(modifier, format[i], 0);
EXPECT_EQ(blk.width, 16);
EXPECT_EQ(blk.height, 16);
@ -102,7 +102,7 @@ TEST(BlockSize, AFBCFormatInvariant32x8)
for (unsigned i = 0; i < ARRAY_SIZE(format); ++i) {
struct pan_image_block_size blk =
pan_image_block_size_el(modifier, format[i]);
pan_image_block_size_el(modifier, format[i], 0);
EXPECT_EQ(blk.width, 32);
EXPECT_EQ(blk.height, 8);
@ -244,7 +244,7 @@ TEST(Layout, ImplicitLayoutInterleavedETC2)
unsigned offsets[9] = {0, 8192, 10240, 10752, 10880,
11008, 11136, 11264, 11392};
ASSERT_TRUE(pan_image_layout_init(0, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(0, &p, 0, NULL, &l));
for (unsigned i = 0; i < 8; ++i) {
unsigned size = (offsets[i + 1] - offsets[i]);
@ -273,7 +273,7 @@ TEST(Layout, ImplicitLayoutInterleavedASTC5x5)
};
struct pan_image_layout l = {};
ASSERT_TRUE(pan_image_layout_init(0, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(0, &p, 0, NULL, &l));
/* The image is 50x50 pixels, with 5x5 blocks. So it is a 10x10 grid of ASTC
* blocks. 4x4 tiles of ASTC blocks are u-interleaved, so we have to round up
@ -303,7 +303,7 @@ TEST(Layout, ImplicitLayoutLinearASTC5x5)
};
struct pan_image_layout l = {};
ASSERT_TRUE(pan_image_layout_init(0, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(0, &p, 0, NULL, &l));
/* The image is 50x50 pixels, with 5x5 blocks. So it is a 10x10 grid of ASTC
* blocks. Each ASTC block is 16 bytes, so the row stride is 160 bytes,
@ -336,7 +336,7 @@ TEST(AFBCLayout, Linear3D)
};
struct pan_image_layout l = {};
ASSERT_TRUE(pan_image_layout_init(0, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(0, &p, 0, NULL, &l));
/* AFBC Surface stride is bytes between consecutive surface headers, which is
* the header size since this is a 3D texture. At superblock size 16x16, the
@ -380,7 +380,7 @@ TEST(AFBCLayout, Tiled16x16)
};
struct pan_image_layout l = {};
ASSERT_TRUE(pan_image_layout_init(0, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(0, &p, 0, NULL, &l));
/* The image is 917x417. Superblocks are 16x16, so there are 58x27
* superblocks. Superblocks are grouped into 8x8 tiles, so there are 8x4
@ -421,7 +421,7 @@ TEST(AFBCLayout, Linear16x16Minimal)
};
struct pan_image_layout l = {};
ASSERT_TRUE(pan_image_layout_init(0, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(0, &p, 0, NULL, &l));
/* Image is 1x1 to test for correct alignment everywhere. */
EXPECT_EQ(l.slices[0].offset_B, 0);
@ -451,7 +451,7 @@ TEST(AFBCLayout, Linear16x16Minimalv6)
};
struct pan_image_layout l = {};
ASSERT_TRUE(pan_image_layout_init(6, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(6, &p, 0, NULL, &l));
/* Image is 1x1 to test for correct alignment everywhere. */
EXPECT_EQ(l.slices[0].offset_B, 0);
@ -482,7 +482,7 @@ TEST(AFBCLayout, Tiled16x16Minimal)
};
struct pan_image_layout l = {};
ASSERT_TRUE(pan_image_layout_init(0, &p, NULL, &l));
ASSERT_TRUE(pan_image_layout_init(0, &p, 0, NULL, &l));
/* Image is 1x1 to test for correct alignment everywhere. */
EXPECT_EQ(l.slices[0].offset_B, 0);
@ -504,8 +504,8 @@ static unsigned archs[] = {4, 5, 6, 7, 9, 12, 13};
#define EXPECT_IMPORT_SUCCESS(__arch, __iprops, __plane, __wsi_layout, \
__out_layout, __test_desc) \
do { \
bool __result = \
pan_image_layout_init(__arch, __iprops, __wsi_layout, __out_layout); \
bool __result = pan_image_layout_init(__arch, __iprops, __plane, \
__wsi_layout, __out_layout); \
EXPECT_TRUE(__result) \
<< __test_desc \
<< " for <format=" << util_format_name((__iprops)->format) \
@ -517,7 +517,7 @@ static unsigned archs[] = {4, 5, 6, 7, 9, 12, 13};
break; \
\
struct pan_image_wsi_layout __export_wsi_layout = \
pan_image_layout_get_wsi_layout(&iprops, &layout, 0); \
pan_image_layout_get_wsi_layout(&iprops, __plane, &layout, 0); \
EXPECT_TRUE(__export_wsi_layout.row_pitch_B == \
(__wsi_layout)->row_pitch_B && \
__export_wsi_layout.offset_B == (__wsi_layout)->offset_B) \
@ -529,8 +529,8 @@ static unsigned archs[] = {4, 5, 6, 7, 9, 12, 13};
#define EXPECT_IMPORT_FAIL(__arch, __iprops, __plane, __wsi_layout, \
__out_layout, __test_desc) \
EXPECT_FALSE( \
pan_image_layout_init(__arch, __iprops, __wsi_layout, __out_layout)) \
EXPECT_FALSE(pan_image_layout_init(__arch, __iprops, __plane, __wsi_layout, \
__out_layout)) \
<< __test_desc \
<< " for <format=" << util_format_name((__iprops)->format) \
<< ",plane=" << __plane << ",mod=" << std::hex << (__iprops)->modifier \
@ -541,7 +541,7 @@ format_can_do_mod(unsigned arch, enum pipe_format format, unsigned plane_idx,
uint64_t modifier)
{
if (drm_is_afbc(modifier)) {
return pan_afbc_format(arch, format) != PAN_AFBC_MODE_INVALID;
return pan_afbc_format(arch, format, plane_idx) != PAN_AFBC_MODE_INVALID;
} else if (drm_is_afrc(modifier)) {
return arch >= 10 && pan_format_supports_afrc(format);
} else {
@ -752,12 +752,6 @@ TEST(WSI, Import)
.crc = false,
};
/* YUV import is broken. Will be fixed once we make
* pan_image_layout a per-plane thing and pass the
* plane index to pan_image_layout_init(). */
if (pan_format_is_yuv(iprops.format))
continue;
bool supported = true;
for (unsigned p = 0; p < util_format_get_num_planes(iprops.format);
p++) {

View file

@ -245,25 +245,28 @@ panvk_image_init_layouts(struct panvk_image *image,
};
}
image->planes[plane].props = (struct pan_image_props){
.modifier = image->vk.drm_format_mod,
.format = vk_format_to_pipe_format(format),
.dim = panvk_image_type_to_mali_tex_dim(image->vk.image_type),
.extent_px = {
.width = vk_format_get_plane_width(image->vk.format, plane,
image->vk.extent.width),
.height = vk_format_get_plane_height(image->vk.format, plane,
image->vk.extent.height),
.depth = image->vk.extent.depth,
image->planes[plane].image = (struct pan_image){
.props = {
.modifier = image->vk.drm_format_mod,
.format = vk_format_to_pipe_format(format),
.dim = panvk_image_type_to_mali_tex_dim(image->vk.image_type),
.extent_px = {
.width = vk_format_get_plane_width(image->vk.format, plane,
image->vk.extent.width),
.height = vk_format_get_plane_height(image->vk.format, plane,
image->vk.extent.height),
.depth = image->vk.extent.depth,
},
.array_size = image->vk.array_layers,
.nr_samples = image->vk.samples,
.nr_slices = image->vk.mip_levels,
},
.array_size = image->vk.array_layers,
.nr_samples = image->vk.samples,
.nr_slices = image->vk.mip_levels,
.planes = {&image->planes[plane].plane},
};
pan_image_layout_init(arch, &image->planes[plane].props,
pan_image_layout_init(arch, &image->planes[plane].image.props, 0,
explicit_info ? &plane_layout : NULL,
&image->planes[plane].layout);
&image->planes[plane].plane.layout);
}
}
@ -328,7 +331,7 @@ panvk_image_get_total_size(const struct panvk_image *image)
{
uint64_t size = 0;
for (uint8_t plane = 0; plane < image->plane_count; plane++)
size += image->planes[plane].layout.data_size_B;
size += image->planes[plane].plane.layout.data_size_B;
return size;
}
@ -420,20 +423,20 @@ get_image_subresource_layout(const struct panvk_image *image,
assert(plane < PANVK_MAX_PLANES);
const struct pan_image_slice_layout *slice_layout =
&image->planes[plane].layout.slices[subres->mipLevel];
&image->planes[plane].plane.layout.slices[subres->mipLevel];
uint64_t base_offset = 0;
if (!is_disjoint(image)) {
for (uint8_t plane_idx = 0; plane_idx < plane; plane_idx++)
base_offset += image->planes[plane_idx].layout.data_size_B;
base_offset += image->planes[plane_idx].plane.layout.data_size_B;
}
layout->offset =
base_offset + slice_layout->offset_B +
(subres->arrayLayer * image->planes[plane].layout.array_stride_B);
(subres->arrayLayer * image->planes[plane].plane.layout.array_stride_B);
layout->size = slice_layout->size_B;
layout->rowPitch = slice_layout->row_stride_B;
layout->arrayPitch = image->planes[plane].layout.array_stride_B;
layout->arrayPitch = image->planes[plane].plane.layout.array_stride_B;
layout->depthPitch = slice_layout->surface_stride_B;
}
@ -476,7 +479,7 @@ panvk_GetImageMemoryRequirements2(VkDevice device,
plane_info ? plane_info->planeAspect : image->vk.aspects;
uint8_t plane = panvk_plane_index(image->vk.format, aspects);
const uint64_t size =
disjoint ? image->planes[plane].layout.data_size_B :
disjoint ? image->planes[plane].plane.layout.data_size_B :
panvk_image_get_total_size(image);
pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
@ -538,27 +541,27 @@ panvk_GetDeviceImageSparseMemoryRequirements(VkDevice device,
}
static void
panvk_image_plane_bind(struct pan_image *plane, struct pan_kmod_bo *bo,
panvk_image_plane_bind(struct panvk_image_plane *plane, struct pan_kmod_bo *bo,
uint64_t base, uint64_t offset)
{
plane->data.base = base + offset;
plane->plane.base = base + offset;
/* Reset the AFBC headers */
if (drm_is_afbc(plane->props.modifier)) {
if (drm_is_afbc(plane->image.props.modifier)) {
/* Transient CPU mapping */
void *bo_base = pan_kmod_bo_mmap(bo, 0, pan_kmod_bo_size(bo),
PROT_WRITE, MAP_SHARED, NULL);
assert(bo_base != MAP_FAILED);
for (unsigned layer = 0; layer < plane->props.array_size;
for (unsigned layer = 0; layer < plane->image.props.array_size;
layer++) {
for (unsigned level = 0; level < plane->props.nr_slices;
for (unsigned level = 0; level < plane->image.props.nr_slices;
level++) {
void *header = bo_base + offset +
(layer * plane->layout.array_stride_B) +
plane->layout.slices[level].offset_B;
(layer * plane->plane.layout.array_stride_B) +
plane->plane.layout.slices[level].offset_B;
memset(header, 0,
plane->layout.slices[level].afbc.header_size_B);
plane->plane.layout.slices[level].afbc.header_size_B);
}
}
@ -587,7 +590,7 @@ panvk_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
image->bo = wsi_image->bo;
panvk_image_plane_bind(&image->planes[0], image->bo,
wsi_image->planes[0].data.base, 0);
wsi_image->planes[0].plane.base, 0);
} else {
VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
assert(mem);
@ -605,7 +608,7 @@ panvk_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
for (unsigned plane = 0; plane < image->plane_count; plane++) {
panvk_image_plane_bind(&image->planes[plane], image->bo,
mem->addr.dev, offset);
offset += image->planes[plane].layout.data_size_B;
offset += image->planes[plane].plane.layout.data_size_B;
}
}
}

View file

@ -12,13 +12,21 @@
#define PANVK_MAX_PLANES 3
/* Right now, planar YUV images are treated as N different images, hence the 1:1
* association between pan_image and pan_image_plane, but this can be optimized
* once planar YUV support is hooked up. */
struct panvk_image_plane {
struct pan_image image;
struct pan_image_plane plane;
};
struct panvk_image {
struct vk_image vk;
struct pan_kmod_bo *bo;
uint8_t plane_count;
struct pan_image planes[PANVK_MAX_PLANES];
struct panvk_image_plane planes[PANVK_MAX_PLANES];
};
VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_image, vk.base, VkImage,

View file

@ -122,8 +122,11 @@ render_state_set_z_attachment(struct panvk_cmd_buffer *cmdbuf,
if (iview->pview.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
state->render.zs_pview.format = PIPE_FORMAT_Z32_FLOAT;
state->render.zs_pview.planes[0] = &img->planes[0];
state->render.zs_pview.planes[1] = NULL;
state->render.zs_pview.planes[0] = (struct pan_image_plane_ref){
.image = &img->planes[0].image,
.plane_idx = 0,
};
state->render.zs_pview.planes[1] = (struct pan_image_plane_ref){0};
state->render.fb.nr_samples =
MAX2(state->render.fb.nr_samples,
pan_image_view_get_nr_samples(&iview->pview));
@ -184,11 +187,17 @@ render_state_set_s_attachment(struct panvk_cmd_buffer *cmdbuf,
? PIPE_FORMAT_Z24_UNORM_S8_UINT
: PIPE_FORMAT_S8_UINT;
if (img->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
state->render.s_pview.planes[0] = NULL;
state->render.s_pview.planes[1] = &img->planes[1];
state->render.s_pview.planes[0] = (struct pan_image_plane_ref){0};
state->render.s_pview.planes[1] = (struct pan_image_plane_ref){
.image = &img->planes[1].image,
.plane_idx = 0,
};
} else {
state->render.s_pview.planes[0] = &img->planes[0];
state->render.s_pview.planes[1] = NULL;
state->render.s_pview.planes[0] = (struct pan_image_plane_ref){
.image = &img->planes[0].image,
.plane_idx = 0,
};
state->render.s_pview.planes[1] = (struct pan_image_plane_ref){0};
}
state->render.fb.nr_samples =

View file

@ -488,10 +488,10 @@ cmd_emit_dcd(struct panvk_cmd_buffer *cmdbuf, struct pan_fb_info *fbinfo,
fbinfo->bifrost.pre_post.modes[dcd_idx] =
MALI_PRE_POST_FRAME_SHADER_MODE_INTERSECT;
} else {
const struct pan_image *plane =
const struct pan_image_plane_ref pref =
fbinfo->zs.view.zs ? pan_image_view_get_zs_plane(fbinfo->zs.view.zs)
: pan_image_view_get_s_plane(fbinfo->zs.view.s);
enum pipe_format fmt = plane->props.format;
enum pipe_format fmt = pref.image->props.format;
/* On some GPUs (e.g. G31), we must use SHADER_MODE_ALWAYS rather than
* SHADER_MODE_INTERSECT for full screen operations. Since the full
* screen rectangle will always intersect, this won't affect

View file

@ -241,9 +241,10 @@ prepare_attr_buf_descs(struct panvk_image_view *view)
vk_format_get_blocksize(view->vk.view_format) == 1)))
plane_idx = 1;
const struct pan_image_props *plane_props = &image->planes[plane_idx].props;
const struct pan_image_props *plane_props =
&image->planes[plane_idx].image.props;
const struct pan_image_layout *plane_layout =
&image->planes[plane_idx].layout;
&image->planes[plane_idx].plane.layout;
bool is_3d = plane_props->dim == MALI_TEXTURE_DIMENSION_3D;
unsigned offset = pan_image_surface_offset(
plane_layout, view->pview.first_level,
@ -266,7 +267,7 @@ prepare_attr_buf_descs(struct panvk_image_view *view)
cfg.type = image->vk.drm_format_mod == DRM_FORMAT_MOD_LINEAR
? MALI_ATTRIBUTE_TYPE_3D_LINEAR
: MALI_ATTRIBUTE_TYPE_3D_INTERLEAVED;
cfg.pointer = image->planes[plane_idx].data.base + offset;
cfg.pointer = image->planes[plane_idx].plane.base + offset;
cfg.stride = fmt_blksize | (hw_fmt << 10);
cfg.size = pan_image_mip_level_size(plane_props, plane_layout,
view->pview.first_level);
@ -284,11 +285,11 @@ prepare_attr_buf_descs(struct panvk_image_view *view)
? extent.depth
: (view->pview.last_layer - view->pview.first_layer + 1);
cfg.row_stride =
image->planes[plane_idx].layout.slices[level].row_stride_B;
image->planes[plane_idx].plane.layout.slices[level].row_stride_B;
if (cfg.r_dimension > 1) {
cfg.slice_stride =
pan_image_surface_stride(&image->planes[plane_idx].props,
&image->planes[plane_idx].layout, level);
cfg.slice_stride = pan_image_surface_stride(
&image->planes[plane_idx].image.props,
&image->planes[plane_idx].plane.layout, level);
}
}
}
@ -337,14 +338,20 @@ panvk_per_arch(CreateImageView)(VkDevice _device,
uint8_t view_plane = (view->vk.aspects == VK_IMAGE_ASPECT_PLANE_1_BIT ||
view->vk.aspects == VK_IMAGE_ASPECT_PLANE_2_BIT) ?
0 : image_plane;
view->pview.planes[view_plane] = &image->planes[image_plane];
view->pview.planes[view_plane] = (struct pan_image_plane_ref) {
.image = &image->planes[image_plane].image,
.plane_idx = 0,
};
}
/* Depth/stencil are viewed as color for copies. */
if (view->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT &&
image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT &&
vk_format_get_blocksize(view->vk.view_format) == 1) {
view->pview.planes[0] = &image->planes[1];
view->pview.planes[0] = (struct pan_image_plane_ref) {
.image = &image->planes[1].image,
.plane_idx = 0,
};
}
/* We need to patch the view format when the image contains both