asahi: Lower 1D to 2D
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Sat, 18 Mar 2023 20:42:35 +0000 (16:42 -0400)
committerMarge Bot <emma+marge@anholt.net>
Fri, 7 Apr 2023 03:23:03 +0000 (03:23 +0000)
Khronos APIs require that we support mipmapping even for 1D textures. However,
it isn't clear if this is supported in the hardware, and how it would work even
if it is. But 1D textures are pretty useless, so we just lower 1D textures to 2D
textures instead of worrying about that.

Fixes piles of Piglits relating to 1D textures.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22353>

src/asahi/compiler/agx_nir_lower_texture.c
src/gallium/drivers/asahi/agx_pipe.c
src/gallium/drivers/asahi/agx_state.c

index b849d8d..5894ae0 100644 (file)
@@ -104,6 +104,10 @@ agx_txs(nir_builder *b, nir_tex_instr *tex)
    nir_ssa_def *height = nir_iadd_imm(b, height_m1, 1);
    nir_ssa_def *depth = nir_iadd_imm(b, depth_m1, 1);
 
+   /* 1D Arrays have their second component as the layer count */
+   if (tex->sampler_dim == GLSL_SAMPLER_DIM_1D && tex->is_array)
+      height = depth;
+
    /* How we finish depends on the size of the result */
    unsigned nr_comps = nir_dest_num_components(tex->dest);
    assert(nr_comps <= 3);
@@ -264,6 +268,43 @@ lower_regular_texture(nir_builder *b, nir_instr *instr, UNUSED void *data)
    nir_ssa_def *coord = steal_tex_src(tex, nir_tex_src_coord);
    nir_ssa_def *ms_idx = steal_tex_src(tex, nir_tex_src_ms_index);
 
+   /* It's unclear if mipmapped 1D textures work in the hardware. For now, we
+    * always lower to 2D.
+    */
+   if (tex->sampler_dim == GLSL_SAMPLER_DIM_1D) {
+      /* Add a zero Y component to the coordinate */
+      if (tex->is_array) {
+         assert(coord->num_components == 2);
+         coord = nir_vec3(b, nir_channel(b, coord, 0),
+                          nir_imm_intN_t(b, 0, coord->bit_size),
+                          nir_channel(b, coord, 1));
+      } else {
+         assert(coord->num_components == 1);
+         coord = nir_vec2(b, coord, nir_imm_intN_t(b, 0, coord->bit_size));
+      }
+
+      /* Add a zero Y component to other sources */
+      nir_tex_src_type other_srcs[] = {
+         nir_tex_src_ddx,
+         nir_tex_src_ddy,
+         nir_tex_src_offset,
+      };
+
+      for (unsigned i = 0; i < ARRAY_SIZE(other_srcs); ++i) {
+         nir_ssa_def *src = steal_tex_src(tex, other_srcs[i]);
+
+         if (!src)
+            continue;
+
+         assert(src->num_components == 1);
+         src = nir_vec2(b, src, nir_imm_intN_t(b, 0, src->bit_size));
+         nir_tex_instr_add_src(tex, other_srcs[i], nir_src_for_ssa(src));
+      }
+
+      tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
+      tex->coord_components++;
+   }
+
    /* The layer is always the last component of the NIR coordinate, split it off
     * because we'll need to swizzle.
     */
index 5635be6..3822b3d 100644 (file)
@@ -282,6 +282,7 @@ agx_linear_allowed(const struct agx_resource *pres)
    /* 1D is always linear */
    case PIPE_BUFFER:
    case PIPE_TEXTURE_1D:
+   case PIPE_TEXTURE_1D_ARRAY:
 
    /* Linear textures require specifying their strides explicitly, which only
     * works for 2D textures. Rectangle textures are a special case of 2D.
@@ -307,8 +308,8 @@ agx_twiddled_allowed(const struct agx_resource *pres)
        (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_LINEAR))
       return false;
 
-   /* Buffers must be linear, and it does not make sense to twiddle 1D */
-   if (pres->base.target == PIPE_BUFFER || pres->base.target == PIPE_TEXTURE_1D)
+   /* Buffers must be linear */
+   if (pres->base.target == PIPE_BUFFER)
       return false;
 
    /* Anything else may be twiddled */
index 3df99d5..a44336c 100644 (file)
@@ -27,6 +27,7 @@
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_state.h"
+#include "util/compiler.h"
 #include "util/format_srgb.h"
 #include "util/half_float.h"
 #include "util/u_inlines.h"
@@ -606,23 +607,20 @@ agx_translate_tex_dim(enum pipe_texture_target dim, unsigned samples)
 
    switch (dim) {
    case PIPE_BUFFER:
+   case PIPE_TEXTURE_1D:
       /* Lowered to 2D */
       assert(samples == 1);
       return AGX_TEXTURE_DIMENSION_2D;
 
-   case PIPE_TEXTURE_1D:
-      assert(samples == 1);
-      return AGX_TEXTURE_DIMENSION_1D;
-
-   case PIPE_TEXTURE_1D_ARRAY:
-      assert(samples == 1);
-      return AGX_TEXTURE_DIMENSION_1D_ARRAY;
-
    case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_2D:
       return samples > 1 ? AGX_TEXTURE_DIMENSION_2D_MULTISAMPLED
                          : AGX_TEXTURE_DIMENSION_2D;
 
+   case PIPE_TEXTURE_1D_ARRAY:
+      assert(samples == 1);
+      /* Lowered to 2D */
+      FALLTHROUGH;
    case PIPE_TEXTURE_2D_ARRAY:
       return samples > 1 ? AGX_TEXTURE_DIMENSION_2D_ARRAY_MULTISAMPLED
                          : AGX_TEXTURE_DIMENSION_2D_ARRAY;