mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 09:38:07 +02:00
panfrost: add support for image2DMSArray on bifrost
On bifrost we only can use 3 coordinates for images, but image2DMSArray needs 4 (x, y, sample#, and array index). We work around this by making the image nr_samples times higher than the original image, using the Y coordinate to address the sample plane. This limits the maximum image height (to 4K pixels instead of 64K pixels in the 16 sample case) but at least allows us to use the images. Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30521>
This commit is contained in:
parent
3173b2c9b7
commit
9e04c0a818
2 changed files with 67 additions and 26 deletions
|
|
@ -1850,29 +1850,34 @@ emit_image_bufs(struct panfrost_batch *batch, enum pipe_shader_type shader,
|
|||
|
||||
pan_pack(bufs + (i * 2) + 1, ATTRIBUTE_BUFFER_CONTINUATION_3D, cfg) {
|
||||
unsigned level = image->u.tex.level;
|
||||
unsigned r_dim;
|
||||
unsigned samples = rsrc->image.layout.nr_samples;
|
||||
|
||||
if (is_3d) {
|
||||
r_dim = u_minify(rsrc->base.depth0, level);
|
||||
} else if (is_msaa) {
|
||||
r_dim = u_minify(image->resource->nr_samples, level);
|
||||
} else {
|
||||
r_dim = image->u.tex.last_layer - image->u.tex.first_layer + 1;
|
||||
}
|
||||
cfg.s_dimension = u_minify(rsrc->base.width0, level);
|
||||
cfg.t_dimension = u_minify(rsrc->base.height0, level);
|
||||
cfg.r_dimension = r_dim;
|
||||
cfg.r_dimension = is_3d ? u_minify(rsrc->image.layout.depth, level)
|
||||
: (image->u.tex.last_layer - image->u.tex.first_layer + 1);
|
||||
|
||||
cfg.row_stride = rsrc->image.layout.slices[level].row_stride;
|
||||
|
||||
if (is_msaa) {
|
||||
unsigned samples = rsrc->base.nr_samples;
|
||||
cfg.slice_stride =
|
||||
panfrost_get_layer_stride(&rsrc->image.layout, level) / samples;
|
||||
} else if (rsrc->base.target != PIPE_TEXTURE_2D) {
|
||||
if (cfg.r_dimension > 1) {
|
||||
cfg.slice_stride =
|
||||
panfrost_get_layer_stride(&rsrc->image.layout, level);
|
||||
}
|
||||
|
||||
if (is_msaa) {
|
||||
if (cfg.r_dimension == 1) {
|
||||
/* regular multisampled images get the sample index in
|
||||
the R dimension */
|
||||
cfg.r_dimension = samples;
|
||||
cfg.slice_stride =
|
||||
panfrost_get_layer_stride(&rsrc->image.layout, level) / samples;
|
||||
} else {
|
||||
/* multisampled image arrays are emulated by making the
|
||||
image "samples" times higher than the original image,
|
||||
and fixing up the T coordinate by the sample number
|
||||
to address the correct sample (on bifrost) */
|
||||
cfg.t_dimension *= samples;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,16 @@ static bool
|
|||
nir_lower_image_ms(nir_builder *b, nir_intrinsic_instr *intr,
|
||||
UNUSED void *data)
|
||||
{
|
||||
bool img_deref = false;
|
||||
|
||||
switch (intr->intrinsic) {
|
||||
case nir_intrinsic_image_load:
|
||||
case nir_intrinsic_image_deref_load:
|
||||
case nir_intrinsic_image_store:
|
||||
case nir_intrinsic_image_deref_store:
|
||||
img_deref = true;
|
||||
break;
|
||||
case nir_intrinsic_image_texel_address:
|
||||
case nir_intrinsic_image_load:
|
||||
case nir_intrinsic_image_store:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
|
@ -49,17 +53,49 @@ nir_lower_image_ms(nir_builder *b, nir_intrinsic_instr *intr,
|
|||
b->cursor = nir_before_instr(&intr->instr);
|
||||
|
||||
nir_def *coord = intr->src[1].ssa;
|
||||
nir_def *index = intr->src[2].ssa;
|
||||
nir_def *sample = nir_channel(b, intr->src[2].ssa, 0);
|
||||
|
||||
if (nir_intrinsic_image_array(intr)) {
|
||||
/* Unlike textures, images only embed a single LOD, hence the zero. */
|
||||
nir_def *lod = nir_imm_int(b, 0);
|
||||
nir_def *img_size =
|
||||
img_deref ? nir_image_deref_size(b, 3, 32, intr->src[0].ssa, lod) :
|
||||
nir_image_size(b, 3, 32, intr->src[0].ssa, lod,
|
||||
.image_array = true, .image_dim = GLSL_SAMPLER_DIM_MS);
|
||||
nir_def *img_height = nir_channel(b, img_size, 1);
|
||||
nir_def *y_coord = nir_channel(b, coord, 1);
|
||||
nir_def *z_coord = nir_channel(b, coord, 2);
|
||||
|
||||
/* With image2DMSArray, the Z coord is already used to index the array. We
|
||||
* assume sample planes are adjacent and patch the Y coordinate to address
|
||||
* the right sample plane. This means our image height is effectively
|
||||
* limited to 4k though.
|
||||
*
|
||||
* Note that we don't trust image intrinsic is_array information because
|
||||
* arrays of size one are allowed, and we only get to know the actual
|
||||
* image size at bind time.
|
||||
*/
|
||||
nir_def *is_array = nir_ugt_imm(b, nir_channel(b, img_size, 2), 1);
|
||||
|
||||
y_coord = nir_bcsel(
|
||||
b, is_array,
|
||||
nir_iadd(b, nir_imul(b, img_height, sample), y_coord), y_coord);
|
||||
z_coord = nir_bcsel(b, is_array, z_coord, sample);
|
||||
coord = nir_vec4(b, nir_channel(b, coord, 0), y_coord, z_coord,
|
||||
nir_channel(b, coord, 3));
|
||||
|
||||
nir_src_rewrite(&intr->src[1], coord);
|
||||
} else {
|
||||
/* image2DMS is treated by panfrost as if it were a 3D image, so
|
||||
* the sample index is in src[2]. We need to put this into the coordinates
|
||||
* in the Z component.
|
||||
*/
|
||||
nir_src_rewrite(&intr->src[1],
|
||||
nir_vector_insert_imm(b, coord, sample, 2));
|
||||
}
|
||||
|
||||
/* image2DMS is treated by panfrost as if it were a 3D image, so
|
||||
* the sample index is in src[2]. We need to put this into the coordinates
|
||||
* in the Z component
|
||||
*/
|
||||
nir_src_rewrite(&intr->src[1],
|
||||
nir_vector_insert_imm(b, coord,
|
||||
nir_channel(b, index, 0),
|
||||
2) );
|
||||
nir_intrinsic_set_image_dim(intr, GLSL_SAMPLER_DIM_3D);
|
||||
nir_intrinsic_set_image_array(intr, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue