diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index a62c3dd29d7..4f2b42a7a8c 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -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 }; diff --git a/src/gallium/drivers/panfrost/pan_csf.c b/src/gallium/drivers/panfrost/pan_csf.c index b6a60a4d8e0..53a1838b7ee 100644 --- a/src/gallium/drivers/panfrost/pan_csf.c +++ b/src/gallium/drivers/panfrost/pan_csf.c @@ -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); diff --git a/src/gallium/drivers/panfrost/pan_fb_preload.c b/src/gallium/drivers/panfrost/pan_fb_preload.c index c054b589d98..ef0d27c0142 100644 --- a/src/gallium/drivers/panfrost/pan_fb_preload.c +++ b/src/gallium/drivers/panfrost/pan_fb_preload.c @@ -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 diff --git a/src/gallium/drivers/panfrost/pan_helpers.c b/src/gallium/drivers/panfrost/pan_helpers.c index fe0f714078d..6139216b3cf 100644 --- a/src/gallium/drivers/panfrost/pan_helpers.c +++ b/src/gallium/drivers/panfrost/pan_helpers.c @@ -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; diff --git a/src/gallium/drivers/panfrost/pan_jm.c b/src/gallium/drivers/panfrost/pan_jm.c index 70f3f3c0857..4f29d2da56a 100644 --- a/src/gallium/drivers/panfrost/pan_jm.c +++ b/src/gallium/drivers/panfrost/pan_jm.c @@ -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; } diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index da3e4d55f2a..c7ec977d571 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -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; diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index f05530d5a4d..06820c411cf 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -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; } } diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h index 1f02427e698..295fe0afc5f 100644 --- a/src/gallium/drivers/panfrost/pan_resource.h +++ b/src/gallium/drivers/panfrost/pan_resource.h @@ -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); diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index ac3d685a47f..82de261d2fe 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -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) diff --git a/src/panfrost/lib/pan_afbc.h b/src/panfrost/lib/pan_afbc.h index d406f592e8b..0eb79241e28 100644 --- a/src/panfrost/lib/pan_afbc.h +++ b/src/panfrost/lib/pan_afbc.h @@ -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: diff --git a/src/panfrost/lib/pan_desc.c b/src/panfrost/lib/pan_desc.c index 0bc6edd9193..e173fa06804 100644 --- a/src/panfrost/lib/pan_desc.c +++ b/src/panfrost/lib/pan_desc.c @@ -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); diff --git a/src/panfrost/lib/pan_image.h b/src/panfrost/lib/pan_image.h index c519bc42459..c3b8764db96 100644 --- a/src/panfrost/lib/pan_image.h +++ b/src/panfrost/lib/pan_image.h @@ -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); } } diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index f6f572b8dde..f4d16b661c0 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -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)); diff --git a/src/panfrost/lib/pan_layout.h b/src/panfrost/lib/pan_layout.h index c47ad838e99..d649d7dd4f0 100644 --- a/src/panfrost/lib/pan_layout.h +++ b/src/panfrost/lib/pan_layout.h @@ -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); diff --git a/src/panfrost/lib/pan_texture.c b/src/panfrost/lib/pan_texture.c index d6f2773dc09..94d096d9aaa 100644 --- a/src/panfrost/lib/pan_texture.c +++ b/src/panfrost/lib/pan_texture.c @@ -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)); diff --git a/src/panfrost/lib/tests/test-layout.cpp b/src/panfrost/lib/tests/test-layout.cpp index 289d9ccafe5..b2789619892 100644 --- a/src/panfrost/lib/tests/test-layout.cpp +++ b/src/panfrost/lib/tests/test-layout.cpp @@ -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) \ @@ -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) \ << ",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++) { diff --git a/src/panfrost/vulkan/panvk_image.c b/src/panfrost/vulkan/panvk_image.c index 55fefdc4f35..6a2a1058407 100644 --- a/src/panfrost/vulkan/panvk_image.c +++ b/src/panfrost/vulkan/panvk_image.c @@ -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; } } } diff --git a/src/panfrost/vulkan/panvk_image.h b/src/panfrost/vulkan/panvk_image.h index b8fc5c2fed7..aec46007c56 100644 --- a/src/panfrost/vulkan/panvk_image.h +++ b/src/panfrost/vulkan/panvk_image.h @@ -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, diff --git a/src/panfrost/vulkan/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/panvk_vX_cmd_draw.c index fd29c6fa7ca..e9aa52ec31c 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c @@ -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 = diff --git a/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c b/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c index be0e341522f..3c1124594c3 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c @@ -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 diff --git a/src/panfrost/vulkan/panvk_vX_image_view.c b/src/panfrost/vulkan/panvk_vX_image_view.c index a5e0782a1d3..c53473de227 100644 --- a/src/panfrost/vulkan/panvk_vX_image_view.c +++ b/src/panfrost/vulkan/panvk_vX_image_view.c @@ -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