mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 16:08:04 +02:00
asahi: use 2D descriptors for cubes
fixes arb_shader_image_load_store-invalid case imageLoad/address bounds test/imageCube/rgba32f this is also better codegen since it avoids the wacko division by 6. although it creates a div by 6 in imageSize, that's better because that one is much more likely to hoist to the preamble. probably should've done this from the start. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26614>
This commit is contained in:
parent
86c4a72767
commit
b74d2dcd57
3 changed files with 50 additions and 31 deletions
|
|
@ -17,6 +17,7 @@
|
|||
#include "agx_nir.h"
|
||||
#include "nir.h"
|
||||
#include "nir_intrinsics.h"
|
||||
#include "nir_intrinsics_indices.h"
|
||||
|
||||
/* Alignment for shader programs. I'm not sure what the optimal value is. */
|
||||
#define AGX_CODE_ALIGN 0x100
|
||||
|
|
@ -912,8 +913,20 @@ agx_emit_image_load(agx_builder *b, agx_index dst, nir_intrinsic_instr *intr)
|
|||
agx_extract_nir_src(b, intr->src[1], 3),
|
||||
};
|
||||
|
||||
/* Get the image dimension. Cubes are lowered to 2D, since they are logically
|
||||
* equivalent for imageLoad, but out-of-bounds behaviour for cubes on G13
|
||||
* is wrong according to Piglit's arb_shader_image_load_store-invalid.
|
||||
*
|
||||
* This requires a matching transform in the driver.
|
||||
*/
|
||||
enum glsl_sampler_dim dim = nir_intrinsic_image_dim(intr);
|
||||
bool is_array = nir_intrinsic_image_array(intr);
|
||||
|
||||
if (dim == GLSL_SAMPLER_DIM_CUBE) {
|
||||
dim = GLSL_SAMPLER_DIM_2D;
|
||||
is_array = true;
|
||||
}
|
||||
|
||||
bool is_ms = dim == GLSL_SAMPLER_DIM_MS;
|
||||
unsigned coord_comps = glsl_get_sampler_dim_coordinate_components(dim);
|
||||
if (is_array && is_ms) {
|
||||
|
|
@ -951,8 +964,16 @@ agx_emit_image_load(agx_builder *b, agx_index dst, nir_intrinsic_instr *intr)
|
|||
static agx_instr *
|
||||
agx_emit_image_store(agx_builder *b, nir_intrinsic_instr *instr)
|
||||
{
|
||||
/* See remarks in agx_emit_image_load */
|
||||
enum glsl_sampler_dim glsl_dim = nir_intrinsic_image_dim(instr);
|
||||
enum agx_dim dim = agx_tex_dim(glsl_dim, nir_intrinsic_image_array(instr));
|
||||
bool is_array = nir_intrinsic_image_array(instr);
|
||||
|
||||
if (glsl_dim == GLSL_SAMPLER_DIM_CUBE) {
|
||||
glsl_dim = GLSL_SAMPLER_DIM_2D;
|
||||
is_array = true;
|
||||
}
|
||||
|
||||
enum agx_dim dim = agx_tex_dim(glsl_dim, is_array);
|
||||
assert(glsl_dim != GLSL_SAMPLER_DIM_MS && "needs to be lowered");
|
||||
|
||||
agx_index base, index;
|
||||
|
|
@ -973,7 +994,7 @@ agx_emit_image_store(agx_builder *b, nir_intrinsic_instr *instr)
|
|||
assert(lod.size == AGX_SIZE_16);
|
||||
|
||||
int coord_components = glsl_get_sampler_dim_coordinate_components(glsl_dim);
|
||||
if (nir_intrinsic_image_array(instr))
|
||||
if (is_array)
|
||||
coord_components++;
|
||||
|
||||
agx_index coord_comps[4] = {};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "agx_compiler.h"
|
||||
#include "agx_internal_formats.h"
|
||||
#include "agx_nir.h"
|
||||
#include "glsl_types.h"
|
||||
#include "libagx_shaders.h"
|
||||
#include "nir_builder_opcodes.h"
|
||||
#include "nir_intrinsics.h"
|
||||
|
|
@ -359,7 +360,15 @@ txs_for_image(nir_builder *b, nir_intrinsic_instr *intr,
|
|||
|
||||
nir_def_init(&tex->instr, &tex->def, num_components, bit_size);
|
||||
nir_builder_instr_insert(b, &tex->instr);
|
||||
return &tex->def;
|
||||
nir_def *res = &tex->def;
|
||||
|
||||
/* Cube images are implemented as 2D arrays, so we need to divide here. */
|
||||
if (tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE && res->num_components > 2) {
|
||||
nir_def *divided = nir_udiv_imm(b, nir_channel(b, res, 2), 6);
|
||||
res = nir_vector_insert_imm(b, res, divided, 2);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
|
|
@ -431,25 +440,6 @@ lower_1d_image(nir_builder *b, nir_intrinsic_instr *intr)
|
|||
nir_intrinsic_set_image_dim(intr, GLSL_SAMPLER_DIM_2D);
|
||||
}
|
||||
|
||||
/*
|
||||
* AGX needs the face and the layer specified separately. This matches how NIR
|
||||
* texture instructions work, but not how NIR image intrinsics work. Here we
|
||||
* lower by dividing the combined layer-face into separate components which the
|
||||
* compiler can consume.
|
||||
*/
|
||||
static void
|
||||
lower_cube_array_image(nir_builder *b, nir_intrinsic_instr *intr)
|
||||
{
|
||||
nir_def *x = nir_channel(b, intr->src[1].ssa, 0);
|
||||
nir_def *y = nir_channel(b, intr->src[1].ssa, 1);
|
||||
nir_def *z = nir_channel(b, intr->src[1].ssa, 2);
|
||||
|
||||
nir_def *face = nir_umod_imm(b, z, 6);
|
||||
nir_def *layer = nir_udiv_imm(b, z, 6);
|
||||
|
||||
nir_src_rewrite(&intr->src[1], nir_vec4(b, x, y, face, layer));
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_images(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data)
|
||||
{
|
||||
|
|
@ -472,12 +462,6 @@ lower_images(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data)
|
|||
lower_buffer_image(b, intr);
|
||||
return true;
|
||||
|
||||
case GLSL_SAMPLER_DIM_CUBE:
|
||||
if (nir_intrinsic_image_array(intr))
|
||||
lower_cube_array_image(b, intr);
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -639,6 +639,12 @@ agx_translate_sample_count(unsigned samples)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
target_is_cube(enum pipe_texture_target target)
|
||||
{
|
||||
return target == PIPE_TEXTURE_CUBE || target == PIPE_TEXTURE_CUBE_ARRAY;
|
||||
}
|
||||
|
||||
static void
|
||||
agx_pack_texture(void *out, struct agx_resource *rsrc,
|
||||
enum pipe_format format /* override */,
|
||||
|
|
@ -737,8 +743,7 @@ agx_pack_texture(void *out, struct agx_resource *rsrc,
|
|||
unsigned layers =
|
||||
state->u.tex.last_layer - state->u.tex.first_layer + 1;
|
||||
|
||||
if ((state->target == PIPE_TEXTURE_CUBE) ||
|
||||
(state->target == PIPE_TEXTURE_CUBE_ARRAY))
|
||||
if (target_is_cube(state->target))
|
||||
layers /= 6;
|
||||
|
||||
if (rsrc->layout.tiling == AIL_TILING_LINEAR &&
|
||||
|
|
@ -1206,8 +1211,10 @@ agx_batch_upload_pbe(struct agx_batch *batch, struct agx_pbe_packed *out,
|
|||
|
||||
/* To reduce shader variants, spilled layered render targets are accessed as
|
||||
* 2D Arrays regardless of the actual target, so force in that case.
|
||||
*
|
||||
* Likewise, cubes are accessed as arrays for consistency with NIR.
|
||||
*/
|
||||
if (arrays_as_2d && target_is_array(target))
|
||||
if ((arrays_as_2d && target_is_array(target)) || target_is_cube(target))
|
||||
target = PIPE_TEXTURE_2D_ARRAY;
|
||||
|
||||
unsigned level = is_buffer ? 0 : view->u.tex.level;
|
||||
|
|
@ -2502,6 +2509,13 @@ agx_upload_textures(struct agx_batch *batch, struct agx_compiled_shader *cs,
|
|||
agx_batch_track_image(batch, view);
|
||||
|
||||
struct pipe_sampler_view sampler_view = util_image_to_sampler_view(view);
|
||||
|
||||
/* For the texture descriptor, lower cubes to 2D arrays. This matches the
|
||||
* transform done in the compiler.
|
||||
*/
|
||||
if (target_is_cube(sampler_view.target))
|
||||
sampler_view.target = PIPE_TEXTURE_2D_ARRAY;
|
||||
|
||||
agx_pack_texture(texture, agx_resource(view->resource), view->format,
|
||||
&sampler_view, true);
|
||||
agx_batch_upload_pbe(batch, pbe, view, false, false);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue