freedreno/ir3: Set up outputs for multi-slot varyings.
authorEric Anholt <eric@anholt.net>
Wed, 22 Apr 2020 19:22:30 +0000 (12:22 -0700)
committerMarge Bot <eric+marge@anholt.net>
Fri, 1 May 2020 16:26:32 +0000 (16:26 +0000)
Necessary to avoid compiler assertion failures in:

dEQP-GLES31.functional.program_interface_query.program_output.type.interface_blocks.out.named_block_explicit_location.struct.mat3x2

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4562>

src/freedreno/ir3/ir3_compiler_nir.c

index 812ce7f9489cfeefdef82ece49233208b173af34..bd65f91e780e35a2c882281aa4a11f9790f8c01e 100644 (file)
@@ -3130,7 +3130,8 @@ static void
 setup_output(struct ir3_context *ctx, nir_variable *out)
 {
        struct ir3_shader_variant *so = ctx->so;
-       unsigned ncomp = glsl_get_components(out->type);
+       unsigned slots = glsl_count_vec4_slots(out->type, false, false);
+       unsigned ncomp = glsl_get_components(glsl_without_array(out->type));
        unsigned n = out->data.driver_location;
        unsigned frac = out->data.location_frac;
        unsigned slot = out->data.location;
@@ -3192,30 +3193,34 @@ setup_output(struct ir3_context *ctx, nir_variable *out)
                ir3_context_error(ctx, "unknown shader type: %d\n", ctx->so->type);
        }
 
-       compile_assert(ctx, n < ARRAY_SIZE(so->outputs));
 
-       so->outputs[n].slot = slot;
-       so->outputs_count = MAX2(so->outputs_count, n + 1);
+       so->outputs_count = out->data.driver_location + slots;
+       compile_assert(ctx, so->outputs_count < ARRAY_SIZE(so->outputs));
 
-       for (int i = 0; i < ncomp; i++) {
-               unsigned idx = (n * 4) + i + frac;
-               compile_assert(ctx, idx < ctx->noutputs);
-               ctx->outputs[idx] = create_immed(ctx->block, fui(0.0));
-       }
+       for (int i = 0; i < slots; i++) {
+               int slot_base = n + i;
+               so->outputs[slot_base].slot = slot + i;
 
-       /* if varying packing doesn't happen, we could end up in a situation
-        * with "holes" in the output, and since the per-generation code that
-        * sets up varying linkage registers doesn't expect to have more than
-        * one varying per vec4 slot, pad the holes.
-        *
-        * Note that this should probably generate a performance warning of
-        * some sort.
-        */
-       for (int i = 0; i < frac; i++) {
-               unsigned idx = (n * 4) + i;
-               if (!ctx->outputs[idx]) {
+               for (int i = 0; i < ncomp; i++) {
+                       unsigned idx = (slot_base * 4) + i + frac;
+                       compile_assert(ctx, idx < ctx->noutputs);
                        ctx->outputs[idx] = create_immed(ctx->block, fui(0.0));
                }
+
+               /* if varying packing doesn't happen, we could end up in a situation
+                * with "holes" in the output, and since the per-generation code that
+                * sets up varying linkage registers doesn't expect to have more than
+                * one varying per vec4 slot, pad the holes.
+                *
+                * Note that this should probably generate a performance warning of
+                * some sort.
+                */
+               for (int i = 0; i < frac; i++) {
+                       unsigned idx = (slot_base * 4) + i;
+                       if (!ctx->outputs[idx]) {
+                               ctx->outputs[idx] = create_immed(ctx->block, fui(0.0));
+                       }
+               }
        }
 }