Mesa (master): pan/mdg: Fix texture handling for 2DMS arrays

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Dec 11 09:46:41 UTC 2020


Module: Mesa
Branch: master
Commit: 727cc80fe3e19371da6cac9d7c92f99acc853ddc
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=727cc80fe3e19371da6cac9d7c92f99acc853ddc

Author: Boris Brezillon <boris.brezillon at collabora.com>
Date:   Thu Dec 10 19:46:14 2020 +0100

pan/mdg: Fix texture handling for 2DMS arrays

While at it, move the coordinate building logic to a dedicated helper
and make it generalize it to handle 1D arrays too.

Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8042>

---

 src/panfrost/midgard/midgard_compile.c | 252 +++++++++++++++++++--------------
 1 file changed, 148 insertions(+), 104 deletions(-)

diff --git a/src/panfrost/midgard/midgard_compile.c b/src/panfrost/midgard/midgard_compile.c
index e2389084863..475cc73464d 100644
--- a/src/panfrost/midgard/midgard_compile.c
+++ b/src/panfrost/midgard/midgard_compile.c
@@ -1911,6 +1911,150 @@ mdg_texture_mode(nir_tex_instr *instr)
                 return TEXTURE_NORMAL;
 }
 
+static void
+set_tex_coord(compiler_context *ctx, nir_tex_instr *instr,
+              midgard_instruction *ins)
+{
+        int coord_idx = nir_tex_instr_src_index(instr, nir_tex_src_coord);
+
+        assert(coord_idx >= 0);
+
+        int comparator_idx = nir_tex_instr_src_index(instr, nir_tex_src_comparator);
+        int ms_idx = nir_tex_instr_src_index(instr, nir_tex_src_ms_index);
+        assert(comparator_idx < 0 || ms_idx < 0);
+        int ms_or_comparator_idx = ms_idx >= 0 ? ms_idx : comparator_idx;
+
+        unsigned coords = nir_src_index(ctx, &instr->src[coord_idx].src);
+
+        emit_explicit_constant(ctx, coords, coords);
+
+        ins->src_types[1] = nir_tex_instr_src_type(instr, coord_idx) |
+                            nir_src_bit_size(instr->src[coord_idx].src);
+
+        unsigned nr_comps = instr->coord_components;
+        unsigned written_mask = 0, write_mask = 0;
+
+        /* Initialize all components to coord.x which is expected to always be
+         * present. Swizzle is updated below based on the texture dimension
+         * and extra attributes that are packed in the coordinate argument.
+         */
+        for (unsigned c = 0; c < MIR_VEC_COMPONENTS; c++)
+                ins->swizzle[1][c] = COMPONENT_X;
+
+        /* Shadow ref value is part of the coordinates if there's no comparator
+         * source, in that case it's always placed in the last component.
+         * Midgard wants the ref value in coord.z.
+         */
+        if (instr->is_shadow && comparator_idx < 0) {
+                ins->swizzle[1][COMPONENT_Z] = --nr_comps;
+                write_mask |= 1 << COMPONENT_Z;
+        }
+
+        /* The array index is the last component if there's no shadow ref value
+         * or second last if there's one. We already decremented the number of
+         * components to account for the shadow ref value above.
+         * Midgard wants the array index in coord.w.
+         */
+        if (instr->is_array) {
+                ins->swizzle[1][COMPONENT_W] = --nr_comps;
+                write_mask |= 1 << COMPONENT_W;
+        }
+
+        if (instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE) {
+                /* texelFetch is undefined on samplerCube */
+                assert(ins->op != TEXTURE_OP_TEXEL_FETCH);
+
+                ins->src[1] = make_compiler_temp_reg(ctx);
+
+                /* For cubemaps, we use a special ld/st op to select the face
+                 * and copy the xy into the texture register
+                 */
+                midgard_instruction ld = m_ld_cubemap_coords(ins->src[1], 0);
+                ld.src[1] = coords;
+                ld.src_types[1] = ins->src_types[1];
+                ld.mask = 0x3; /* xy */
+                ld.load_store.arg_1 = 0x20;
+                ld.swizzle[1][3] = COMPONENT_X;
+                emit_mir_instruction(ctx, ld);
+
+                /* We packed cube coordiates (X,Y,Z) into (X,Y), update the
+                 * written mask accordingly and decrement the number of
+                 * components
+                 */
+                nr_comps--;
+                written_mask |= 3;
+        }
+
+        /* Now flag tex coord components that have not been written yet */
+        write_mask |= mask_of(nr_comps) & ~written_mask;
+        for (unsigned c = 0; c < nr_comps; c++)
+                ins->swizzle[1][c] = c;
+
+        /* Sample index and shadow ref are expected in coord.z */
+        if (ms_or_comparator_idx >= 0) {
+                assert(!((write_mask | written_mask) & (1 << COMPONENT_Z)));
+
+                unsigned sample_or_ref =
+                        nir_src_index(ctx, &instr->src[ms_or_comparator_idx].src);
+
+                emit_explicit_constant(ctx, sample_or_ref, sample_or_ref);
+
+                if (ins->src[1] == ~0)
+                        ins->src[1] = make_compiler_temp_reg(ctx);
+
+                midgard_instruction mov = v_mov(sample_or_ref, ins->src[1]);
+
+                for (unsigned c = 0; c < MIR_VEC_COMPONENTS; c++)
+                        mov.swizzle[1][c] = COMPONENT_X;
+
+                mov.mask = 1 << COMPONENT_Z;
+                written_mask |= 1 << COMPONENT_Z;
+                ins->swizzle[1][COMPONENT_Z] = COMPONENT_Z;
+                emit_mir_instruction(ctx, mov);
+        }
+
+        /* Texelfetch coordinates uses all four elements (xyz/index) regardless
+         * of texture dimensionality, which means it's necessary to zero the
+         * unused components to keep everything happy.
+         */
+        if (ins->op == TEXTURE_OP_TEXEL_FETCH &&
+            (written_mask | write_mask) != 0xF) {
+                if (ins->src[1] == ~0)
+                        ins->src[1] = make_compiler_temp_reg(ctx);
+
+                /* mov index.zw, #0, or generalized */
+                midgard_instruction mov =
+                        v_mov(SSA_FIXED_REGISTER(REGISTER_CONSTANT), ins->src[1]);
+                mov.has_constants = true;
+                mov.mask = (written_mask | write_mask) ^ 0xF;
+                emit_mir_instruction(ctx, mov);
+                for (unsigned c = 0; c < MIR_VEC_COMPONENTS; c++) {
+                        if (mov.mask & (1 << c))
+                                ins->swizzle[1][c] = c;
+                }
+        }
+
+        if (ins->src[1] == ~0) {
+                /* No temporary reg created, use the src coords directly */
+                ins->src[1] = coords;
+	} else if (write_mask) {
+                /* Move the remaining coordinates to the temporary reg */
+                midgard_instruction mov = v_mov(coords, ins->src[1]);
+
+                for (unsigned c = 0; c < MIR_VEC_COMPONENTS; c++) {
+                        if ((1 << c) & write_mask) {
+                                mov.swizzle[1][c] = ins->swizzle[1][c];
+                                ins->swizzle[1][c] = c;
+                        } else {
+                                mov.swizzle[1][c] = COMPONENT_X;
+                        }
+                }
+
+                mov.mask = write_mask;
+                emit_mir_instruction(ctx, mov);
+        }
+}
+
 static void
 emit_texop_native(compiler_context *ctx, nir_tex_instr *instr,
                   unsigned midgard_texop)
@@ -1953,105 +2097,15 @@ emit_texop_native(compiler_context *ctx, nir_tex_instr *instr,
            for (int i = 0; i < 4; ++i)
               ins.swizzle[0][i] = COMPONENT_X;
 
-        /* We may need a temporary for the coordinate */
-
-        bool needs_temp_coord =
-                (midgard_texop == TEXTURE_OP_TEXEL_FETCH) ||
-                (instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE) ||
-                (instr->is_shadow);
-
-        unsigned coords = needs_temp_coord ? make_compiler_temp_reg(ctx) : 0;
-
         for (unsigned i = 0; i < instr->num_srcs; ++i) {
                 int index = nir_src_index(ctx, &instr->src[i].src);
-                unsigned nr_components = nir_src_num_components(instr->src[i].src);
                 unsigned sz = nir_src_bit_size(instr->src[i].src);
                 nir_alu_type T = nir_tex_instr_src_type(instr, i) | sz;
 
                 switch (instr->src[i].src_type) {
-                case nir_tex_src_coord: {
-                        emit_explicit_constant(ctx, index, index);
-
-                        unsigned coord_mask = mask_of(instr->coord_components);
-
-                        bool flip_zw = (instr->sampler_dim == GLSL_SAMPLER_DIM_2D) && (coord_mask & (1 << COMPONENT_Z));
-
-                        if (flip_zw)
-                                coord_mask ^= ((1 << COMPONENT_Z) | (1 << COMPONENT_W));
-
-                        if (instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE) {
-                                /* texelFetch is undefined on samplerCube */
-                                assert(midgard_texop != TEXTURE_OP_TEXEL_FETCH);
-
-                                /* For cubemaps, we use a special ld/st op to
-                                 * select the face and copy the xy into the
-                                 * texture register */
-
-                                midgard_instruction ld = m_ld_cubemap_coords(coords, 0);
-                                ld.src[1] = index;
-                                ld.src_types[1] = T;
-                                ld.mask = 0x3; /* xy */
-                                ld.load_store.arg_1 = 0x20;
-                                ld.swizzle[1][3] = COMPONENT_X;
-                                emit_mir_instruction(ctx, ld);
-
-                                /* xyzw -> xyxx */
-                                ins.swizzle[1][2] = instr->is_shadow ? COMPONENT_Z : COMPONENT_X;
-                                ins.swizzle[1][3] = COMPONENT_X;
-                        } else if (needs_temp_coord) {
-                                /* mov coord_temp, coords */
-                                midgard_instruction mov = v_mov(index, coords);
-                                mov.mask = coord_mask;
-
-                                if (flip_zw)
-                                        mov.swizzle[1][COMPONENT_W] = COMPONENT_Z;
-
-                                emit_mir_instruction(ctx, mov);
-                        } else {
-                                coords = index;
-                        }
-
-                        ins.src[1] = coords;
-                        ins.src_types[1] = T;
-
-                        /* Texelfetch coordinates uses all four elements
-                         * (xyz/index) regardless of texture dimensionality,
-                         * which means it's necessary to zero the unused
-                         * components to keep everything happy */
-
-                        if (midgard_texop == TEXTURE_OP_TEXEL_FETCH) {
-                                /* mov index.zw, #0, or generalized */
-                                midgard_instruction mov =
-                                        v_mov(SSA_FIXED_REGISTER(REGISTER_CONSTANT), coords);
-                                mov.has_constants = true;
-                                mov.mask = coord_mask ^ 0xF;
-                                emit_mir_instruction(ctx, mov);
-                        }
-
-                        if (instr->sampler_dim == GLSL_SAMPLER_DIM_2D) {
-                                /* Array component in w but NIR wants it in z,
-                                 * but if we have a temp coord we already fixed
-                                 * that up */
-
-                                if (nr_components == 3) {
-                                        ins.swizzle[1][2] = COMPONENT_Z;
-                                        ins.swizzle[1][3] = needs_temp_coord ? COMPONENT_W : COMPONENT_Z;
-                                } else if (nr_components == 2) {
-                                        ins.swizzle[1][2] =
-                                                instr->is_shadow ? COMPONENT_Z : COMPONENT_X;
-                                        ins.swizzle[1][3] = COMPONENT_X;
-                                } else
-                                        unreachable("Invalid texture 2D components");
-                        }
-
-                        if (midgard_texop == TEXTURE_OP_TEXEL_FETCH) {
-                                /* We zeroed */
-                                ins.swizzle[1][2] = COMPONENT_Z;
-                                ins.swizzle[1][3] = COMPONENT_W;
-                        }
-
+                case nir_tex_src_coord:
+                        set_tex_coord(ctx, instr, &ins);
                         break;
-                }
 
                 case nir_tex_src_bias:
                 case nir_tex_src_lod: {
@@ -2086,19 +2140,9 @@ emit_texop_native(compiler_context *ctx, nir_tex_instr *instr,
                 };
 
                 case nir_tex_src_comparator:
-                case nir_tex_src_ms_index: {
-                        unsigned comp = COMPONENT_Z;
-
-                        /* mov coord_temp.foo, coords */
-                        midgard_instruction mov = v_mov(index, coords);
-                        mov.mask = 1 << comp;
-
-                        for (unsigned i = 0; i < MIR_VEC_COMPONENTS; ++i)
-                                mov.swizzle[1][i] = COMPONENT_X;
-
-                        emit_mir_instruction(ctx, mov);
+                case nir_tex_src_ms_index:
+                        /* Nothing to do, handled in set_tex_coord() */
                         break;
-                }
 
                 default: {
                         fprintf(stderr, "Unknown texture source type: %d\n", instr->src[i].src_type);



More information about the mesa-commit mailing list