Mesa (main): pan/bi: Emit Valhall texture instructions

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 7 14:34:59 UTC 2022


Module: Mesa
Branch: main
Commit: ae79f6765a371ca3d6f612bdf607f29ae35101c7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ae79f6765a371ca3d6f612bdf607f29ae35101c7

Author: Alyssa Rosenzweig <alyssa at collabora.com>
Date:   Wed Mar 23 12:05:43 2022 -0400

pan/bi: Emit Valhall texture instructions

Valhall uses an updated version fo the TEXC path. To avoid disrupting the
existing Bifrost code, add a new Valhall-specific texture path that generates
the new-style texture instructions.

Signed-off-by: Alyssa Rosenzweig <alyssa at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15793>

---

 src/panfrost/bifrost/bifrost_compile.c | 280 +++++++++++++++++++++++++++++++--
 1 file changed, 267 insertions(+), 13 deletions(-)

diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c
index 89a51faa85e..9942ff6567b 100644
--- a/src/panfrost/bifrost/bifrost_compile.c
+++ b/src/panfrost/bifrost/bifrost_compile.c
@@ -2568,6 +2568,31 @@ bifrost_tex_format(enum glsl_sampler_dim dim)
         }
 }
 
+static enum bi_dimension
+valhall_tex_dimension(enum glsl_sampler_dim dim)
+{
+        switch (dim) {
+        case GLSL_SAMPLER_DIM_1D:
+        case GLSL_SAMPLER_DIM_BUF:
+                return BI_DIMENSION_1D;
+
+        case GLSL_SAMPLER_DIM_2D:
+        case GLSL_SAMPLER_DIM_MS:
+        case GLSL_SAMPLER_DIM_EXTERNAL:
+        case GLSL_SAMPLER_DIM_RECT:
+                return BI_DIMENSION_2D;
+
+        case GLSL_SAMPLER_DIM_3D:
+                return BI_DIMENSION_3D;
+
+        case GLSL_SAMPLER_DIM_CUBE:
+                return BI_DIMENSION_CUBE;
+
+        default:
+                unreachable("Unknown sampler dim type");
+        }
+}
+
 static enum bifrost_texture_format_full
 bi_texture_format(nir_alu_type T, enum bi_clamp clamp)
 {
@@ -2686,22 +2711,81 @@ bi_emit_texc_offset_ms_index(bi_builder *b, nir_tex_instr *instr)
         return dest;
 }
 
+/*
+ * Valhall specifies specifies texel offsets, multisample indices, and (for
+ * fetches) LOD together as a u8vec4 <offset.xyz, LOD>, where the third
+ * component is either offset.z or multisample index depending on context. Build
+ * this register.
+ */
+static bi_index
+bi_emit_valhall_offsets(bi_builder *b, nir_tex_instr *instr)
+{
+        bi_index dest = bi_zero();
+
+        int offs_idx = nir_tex_instr_src_index(instr, nir_tex_src_offset);
+        int ms_idx = nir_tex_instr_src_index(instr, nir_tex_src_ms_index);
+        int lod_idx = nir_tex_instr_src_index(instr, nir_tex_src_lod);
+
+        /* Components 0-2: offsets */
+        if (offs_idx >= 0 &&
+            (!nir_src_is_const(instr->src[offs_idx].src) ||
+             nir_src_as_uint(instr->src[offs_idx].src) != 0)) {
+                unsigned nr = nir_src_num_components(instr->src[offs_idx].src);
+                bi_index idx = bi_src_index(&instr->src[offs_idx].src);
+
+                /* No multisample index with 3D */
+                assert((nr <= 2) || (ms_idx < 0));
+
+                dest = bi_mkvec_v4i8(b,
+                                (nr > 0) ? bi_byte(bi_word(idx, 0), 0) : bi_imm_u8(0),
+                                (nr > 1) ? bi_byte(bi_word(idx, 1), 0) : bi_imm_u8(0),
+                                (nr > 2) ? bi_byte(bi_word(idx, 2), 0) : bi_imm_u8(0),
+                                bi_imm_u8(0));
+        }
+
+        /* Component 2: multisample index */
+        if (ms_idx >= 0 &&
+            (!nir_src_is_const(instr->src[ms_idx].src) ||
+             nir_src_as_uint(instr->src[ms_idx].src) != 0)) {
+                dest = bi_mkvec_v2i16(b, dest,
+                                bi_src_index(&instr->src[ms_idx].src));
+        }
+
+        /* Component 3: 8-bit LOD */
+        if (lod_idx >= 0 &&
+            (!nir_src_is_const(instr->src[lod_idx].src) ||
+             nir_src_as_uint(instr->src[lod_idx].src) != 0) &&
+            nir_tex_instr_src_type(instr, lod_idx) != nir_type_float) {
+                dest = bi_lshift_or_i32(b,
+                                bi_src_index(&instr->src[lod_idx].src), dest,
+                                bi_imm_u8(24));
+        }
+
+        return dest;
+}
+
 static void
 bi_emit_cube_coord(bi_builder *b, bi_index coord,
                     bi_index *face, bi_index *s, bi_index *t)
 {
         /* Compute max { |x|, |y|, |z| } */
-        bi_instr *cubeface = bi_cubeface_to(b, bi_temp(b->shader),
-                        bi_temp(b->shader), coord,
-                        bi_word(coord, 1), bi_word(coord, 2));
+        bi_index maxxyz = bi_temp(b->shader);
+        *face = bi_temp(b->shader);
 
-        /* Select coordinates */
+        bi_index cx = coord, cy = bi_word(coord, 1), cz = bi_word(coord, 2);
 
-        bi_index ssel = bi_cube_ssel(b, bi_word(coord, 2), coord,
-                        cubeface->dest[1]);
+        /* Use a pseudo op on Bifrost due to tuple restrictions */
+        if (b->shader->arch <= 8) {
+                bi_cubeface_to(b, maxxyz, *face, cx, cy, cz);
+        } else {
+                bi_cubeface1_to(b, maxxyz, cx, cy, cz);
+                bi_cubeface2_v9_to(b, *face, cx, cy, cz);
+        }
 
+        /* Select coordinates */
+        bi_index ssel = bi_cube_ssel(b, bi_word(coord, 2), coord, *face);
         bi_index tsel = bi_cube_tsel(b, bi_word(coord, 1), bi_word(coord, 2),
-                        cubeface->dest[1]);
+                        *face);
 
         /* The OpenGL ES specification requires us to transform an input vector
          * (x, y, z) to the coordinate, given the selected S/T:
@@ -2716,8 +2800,7 @@ bi_emit_cube_coord(bi_builder *b, bi_index coord,
          *
          * Take the reciprocal of max{x, y, z}
          */
-
-        bi_index rcp = bi_frcp_f32(b, cubeface->dest[0]);
+        bi_index rcp = bi_frcp_f32(b, maxxyz);
 
         /* Calculate 0.5 * (1.0 / max{x, y, z}) */
         bi_index fma1 = bi_fma_f32(b, rcp, bi_imm_f32(0.5f), bi_negzero(),
@@ -2734,9 +2817,6 @@ bi_emit_cube_coord(bi_builder *b, bi_index coord,
 
         S->clamp = BI_CLAMP_CLAMP_0_1;
         T->clamp = BI_CLAMP_CLAMP_0_1;
-
-        /* Face index at bit[29:31], matching the cube map descriptor */
-        *face = cubeface->dest[1];
 }
 
 /* Emits a cube map descriptor, returning lower 32-bits and putting upper
@@ -3013,6 +3093,178 @@ bi_emit_texc(bi_builder *b, nir_tex_instr *instr)
         }
 }
 
+/* Staging registers required by texturing in the order they appear (Valhall) */
+
+enum valhall_tex_sreg {
+        VALHALL_TEX_SREG_X_COORD = 0,
+        VALHALL_TEX_SREG_Y_COORD = 1,
+        VALHALL_TEX_SREG_Z_COORD = 2,
+        VALHALL_TEX_SREG_Y_DELTAS = 3,
+        VALHALL_TEX_SREG_ARRAY = 4,
+        VALHALL_TEX_SREG_SHADOW = 5,
+        VALHALL_TEX_SREG_OFFSETMS = 6,
+        VALHALL_TEX_SREG_LOD = 7,
+        VALHALL_TEX_SREG_GRDESC = 8,
+        VALHALL_TEX_SREG_COUNT,
+};
+
+static void
+bi_emit_tex_valhall(bi_builder *b, nir_tex_instr *instr)
+{
+        bool explicit_offset = false;
+        enum bi_va_lod_mode lod_mode = BI_VA_LOD_MODE_COMPUTED_LOD;
+
+        bool has_lod_mode =
+                (instr->op == nir_texop_tex) ||
+                (instr->op == nir_texop_txl) ||
+                (instr->op == nir_texop_txb);
+
+        /* 32-bit indices to be allocated as consecutive staging registers */
+        bi_index sregs[VALHALL_TEX_SREG_COUNT] = { };
+
+        bi_index sampler = bi_imm_u32(instr->sampler_index);
+        bi_index texture = bi_imm_u32(instr->texture_index);
+        uint32_t tables = (PAN_TABLE_SAMPLER << 11) | (PAN_TABLE_TEXTURE << 27);
+
+        for (unsigned i = 0; i < instr->num_srcs; ++i) {
+                bi_index index = bi_src_index(&instr->src[i].src);
+                unsigned sz = nir_src_bit_size(instr->src[i].src);
+                unsigned components = nir_src_num_components(instr->src[i].src);
+
+                switch (instr->src[i].src_type) {
+                case nir_tex_src_coord:
+                        if (instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE) {
+                                sregs[VALHALL_TEX_SREG_X_COORD] =
+                                        bi_emit_texc_cube_coord(b, index,
+                                                &sregs[VALHALL_TEX_SREG_Y_COORD]);
+			} else {
+                                assert(components >= 1 && components <= 3);
+
+                                /* Copy XY (for 2D+) or XX (for 1D) */
+                                sregs[VALHALL_TEX_SREG_X_COORD] = index;
+
+                                if (components >= 2)
+                                        sregs[VALHALL_TEX_SREG_Y_COORD] = bi_word(index, 1);
+
+                                if (components == 3 && !instr->is_array) {
+                                        sregs[VALHALL_TEX_SREG_Z_COORD] =
+                                                bi_word(index, 2);
+                                }
+                        }
+
+                        if (instr->is_array) {
+                                sregs[VALHALL_TEX_SREG_ARRAY] =
+                                        bi_word(index, components - 1);
+                        }
+
+                        break;
+
+                case nir_tex_src_lod:
+                        if (nir_src_is_const(instr->src[i].src) &&
+                            nir_src_as_uint(instr->src[i].src) == 0) {
+                                lod_mode = BI_VA_LOD_MODE_ZERO_LOD;
+                        } else if (has_lod_mode) {
+                                lod_mode = BI_VA_LOD_MODE_EXPLICIT;
+
+                                assert(sz == 16 || sz == 32);
+                                sregs[VALHALL_TEX_SREG_LOD] =
+                                        bi_emit_texc_lod_88(b, index, sz == 16);
+                        }
+                        break;
+
+                case nir_tex_src_bias:
+                        /* Upper 16-bits interpreted as a clamp, leave zero */
+                        assert(sz == 16 || sz == 32);
+                        sregs[VALHALL_TEX_SREG_LOD] =
+                                bi_emit_texc_lod_88(b, index, sz == 16);
+
+                        lod_mode = BI_VA_LOD_MODE_COMPUTED_BIAS;
+                        break;
+                case nir_tex_src_ms_index:
+                case nir_tex_src_offset:
+                        /* Handled below */
+                        break;
+
+                case nir_tex_src_comparator:
+                        sregs[VALHALL_TEX_SREG_SHADOW] = index;
+                        break;
+
+                case nir_tex_src_texture_offset:
+                        assert(instr->texture_index == 0);
+                        texture = index;
+                        break;
+
+                case nir_tex_src_sampler_offset:
+                        assert(instr->sampler_index == 0);
+                        sampler = index;
+                        break;
+
+                default:
+                        unreachable("Unhandled src type in tex emit");
+                }
+        }
+
+        /* Generate packed offset + ms index + LOD register. These default to
+         * zero so we only need to encode if these features are actually in use.
+         */
+        bi_index offsets = bi_emit_valhall_offsets(b, instr);
+
+        if (!bi_is_equiv(offsets, bi_zero())) {
+                sregs[VALHALL_TEX_SREG_OFFSETMS] = offsets;
+                explicit_offset = true;
+        }
+
+        /* Allocate staging registers contiguously by compacting the array. */
+        unsigned sr_count = 0;
+
+        for (unsigned i = 0; i < ARRAY_SIZE(sregs); ++i) {
+                if (!bi_is_null(sregs[i]))
+                        sregs[sr_count++] = sregs[i];
+        }
+
+        bi_index idx = sr_count ? bi_temp(b->shader) : bi_null();
+
+        if (sr_count)
+                bi_make_vec_to(b, idx, sregs, NULL, sr_count, 32);
+
+        bi_index image_src = bi_imm_u32(tables);
+        image_src = bi_lshift_or_i32(b, sampler, image_src, bi_imm_u8(0));
+        image_src = bi_lshift_or_i32(b, texture, image_src, bi_imm_u8(16));
+
+        bi_index rsrc = bi_temp_reg(b->shader);
+        bi_index words[] = { image_src, bi_zero() };
+        bi_make_vec_to(b, rsrc, words, NULL, 2, 32);
+        bi_index rsrc_hi = bi_word(rsrc, 1);
+
+        unsigned mask = BI_WRITE_MASK_RGBA;
+        enum bi_register_format regfmt = bi_reg_fmt_for_nir(instr->dest_type);
+        enum bi_dimension dim = valhall_tex_dimension(instr->sampler_dim);
+        bi_index dest = bi_dest_index(&instr->dest);
+
+        switch (instr->op) {
+        case nir_texop_tex:
+        case nir_texop_txl:
+        case nir_texop_txb:
+                bi_tex_single_to(b, dest, idx, rsrc, rsrc_hi, instr->is_array,
+                                 dim, regfmt, instr->is_shadow, explicit_offset,
+                                 lod_mode, mask, sr_count);
+                break;
+        case nir_texop_txf:
+        case nir_texop_txf_ms:
+                bi_tex_fetch_to(b, dest, idx, rsrc, rsrc_hi, instr->is_array,
+                                 dim, regfmt, explicit_offset, mask, sr_count);
+                break;
+        case nir_texop_tg4:
+                bi_tex_gather_to(b, dest, idx, rsrc, rsrc_hi, instr->is_array,
+                                 dim, instr->component, false, regfmt,
+                                 instr->is_shadow, explicit_offset, mask,
+                                 sr_count);
+                break;
+        default:
+                unreachable("Unhandled Valhall texture op");
+        }
+}
+
 /* Simple textures ops correspond to NIR tex or txl with LOD = 0 on 2D/cube
  * textures with sufficiently small immediate indices. Anything else
  * needs a complete texture op. */
@@ -3109,7 +3361,9 @@ bi_emit_tex(bi_builder *b, nir_tex_instr *instr)
                 unreachable("Invalid texture operation");
         }
 
-        if (bi_is_simple_tex(instr))
+        if (b->shader->arch >= 9)
+                bi_emit_tex_valhall(b, instr);
+        else if (bi_is_simple_tex(instr))
                 bi_emit_texs(b, instr);
         else
                 bi_emit_texc(b, instr);



More information about the mesa-commit mailing list