panfrost: Fix general purpose varying handling
authorBoris Brezillon <boris.brezillon@collabora.com>
Thu, 13 Jun 2019 12:56:02 +0000 (14:56 +0200)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Thu, 13 Jun 2019 17:54:18 +0000 (10:54 -0700)
When both the fragment and vertex shaders point to the same varying
location they expect to share the same varying slot.
Make sure vertex and fragment varyings pointing to the same loc have
->src_offset set to the same value.

[Alyssa: In addition a patch implement txs, this fixes GALLIUM_HUD on
Panfrost]

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/gallium/drivers/panfrost/midgard/midgard_compile.c
src/gallium/drivers/panfrost/pan_assemble.c
src/gallium/drivers/panfrost/pan_context.c
src/gallium/drivers/panfrost/pan_context.h

index 6761b27681433226fe65430a695b1c0d2246c3ee..1374c1ee6475a06a88077de33248c504163818d4 100644 (file)
@@ -2414,9 +2414,9 @@ midgard_compile_shader_nir(nir_shader *nir, midgard_program *program, bool is_bl
                 unsigned loc = var->data.driver_location;
                 unsigned sz = glsl_type_size(var->type, FALSE);
 
-                for (int c = loc; c < (loc + sz); ++c) {
-                        program->varyings[c] = var->data.location;
-                        max_varying = MAX2(max_varying, c);
+                for (int c = 0; c < sz; ++c) {
+                        program->varyings[loc + c] = var->data.location + c;
+                        max_varying = MAX2(max_varying, loc + c);
                 }
         }
 
index a6ba5fa6790e5938df9583d7473f8122f0950669..de8a53ce05d7f7a928d0f500ff97b2257117c4fc 100644 (file)
@@ -105,8 +105,6 @@ panfrost_shader_compile(struct panfrost_context *ctx, struct mali_shader_meta *m
         unsigned default_vec4_swizzle = panfrost_get_default_swizzle(4);
 
         /* Iterate the varyings and emit the corresponding descriptor */
-        unsigned general_purpose_count = 0;
-
         for (unsigned i = 0; i < program.varying_count; ++i) {
                 unsigned location = program.varyings[i];
 
@@ -136,12 +134,9 @@ panfrost_shader_compile(struct panfrost_context *ctx, struct mali_shader_meta *m
                         state->reads_point_coord = true;
                 } else {
                         v.index = 0;
-                        v.src_offset = 16 * (general_purpose_count++);
                 }
 
                 state->varyings[i] = v;
+                state->varyings_loc[i] = location;
         }
-
-        /* Set the stride for the general purpose fp32 vec4 varyings */
-        state->general_varying_stride = (4 * 4) * general_purpose_count;
 }
index 53c2fe3cee79fa507bbf611503f04013599da7fb..d178a0f1db2117537086b86a51ac76cca56555b5 100644 (file)
@@ -697,6 +697,7 @@ panfrost_emit_varying_descriptor(
 
         struct panfrost_shader_state *vs = &ctx->vs->variants[ctx->vs->active_variant];
         struct panfrost_shader_state *fs = &ctx->fs->variants[ctx->fs->active_variant];
+        unsigned int num_gen_varyings = 0;
 
         /* Allocate the varying descriptor */
 
@@ -706,6 +707,42 @@ panfrost_emit_varying_descriptor(
         struct panfrost_transfer trans = panfrost_allocate_transient(ctx,
                         vs_size + fs_size);
 
+        /*
+         * Assign ->src_offset now that we know about all the general purpose
+         * varyings that will be used by the fragment and vertex shaders.
+         */
+        for (unsigned i = 0; i < vs->tripipe->varying_count; i++) {
+                /*
+                 * General purpose varyings have ->index set to 0, skip other
+                 * entries.
+                 */
+                if (vs->varyings[i].index)
+                        continue;
+
+                vs->varyings[i].src_offset = 16 * (num_gen_varyings++);
+        }
+
+        for (unsigned i = 0; i < fs->tripipe->varying_count; i++) {
+                unsigned j;
+
+                if (fs->varyings[i].index)
+                        continue;
+
+                /*
+                 * Re-use the VS general purpose varying pos if it exists,
+                 * create a new one otherwise.
+                 */
+                for (j = 0; j < vs->tripipe->varying_count; j++) {
+                        if (fs->varyings_loc[i] == vs->varyings_loc[j])
+                                break;
+                }
+
+                if (j < vs->tripipe->varying_count)
+                        fs->varyings[i].src_offset = vs->varyings[j].src_offset;
+                else
+                        fs->varyings[i].src_offset = 16 * (num_gen_varyings++);
+        }
+
         memcpy(trans.cpu, vs->varyings, vs_size);
         memcpy(trans.cpu + vs_size, fs->varyings, fs_size);
 
@@ -716,11 +753,8 @@ panfrost_emit_varying_descriptor(
         union mali_attr varyings[PIPE_MAX_ATTRIBS];
         unsigned idx = 0;
 
-        /* General varyings -- use the VS's, since those are more likely to be
-         * accurate on desktop */
-
-        panfrost_emit_varyings(ctx, &varyings[idx++],
-                        vs->general_varying_stride, invocation_count);
+        panfrost_emit_varyings(ctx, &varyings[idx++], num_gen_varyings * 16,
+                               invocation_count);
 
         /* fp32 vec4 gl_Position */
         ctx->payload_tiler.postfix.position_varying =
index 6f3bca939e5130434442b30aa9f9ad5aff31e8bc..3eac8d6b5a2b059124b4ca7e18c20cd4edec640b 100644 (file)
@@ -267,8 +267,8 @@ struct panfrost_shader_state {
         bool writes_point_size;
         bool reads_point_coord;
 
-        unsigned general_varying_stride;
         struct mali_attr_meta varyings[PIPE_MAX_ATTRIBS];
+        gl_varying_slot varyings_loc[PIPE_MAX_ATTRIBS];
 
         unsigned sysval_count;
         unsigned sysval[MAX_SYSVAL_COUNT];