[Mesa-dev] [PATCH] panfrost: Fix general purpose varying handling

Boris Brezillon boris.brezillon at collabora.com
Thu Jun 13 15:37:42 UTC 2019


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.

Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
---
Found the bug while debugging gallium-hud on panfrost. The vertex and
fragment shaders used for the fonts do not have the same number of
general purpose varying input/ouput. This ->src_offset mismatch leads
to wrong texture coordinates when sampling the font texture.
---
 .../panfrost/midgard/midgard_compile.c        |  6 +--
 src/gallium/drivers/panfrost/pan_assemble.c   |  7 +--
 src/gallium/drivers/panfrost/pan_context.c    | 44 ++++++++++++++++---
 src/gallium/drivers/panfrost/pan_context.h    |  2 +-
 4 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/gallium/drivers/panfrost/midgard/midgard_compile.c b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
index 6761b2768143..1374c1ee6475 100644
--- a/src/gallium/drivers/panfrost/midgard/midgard_compile.c
+++ b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
@@ -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);
                 }
         }
 
diff --git a/src/gallium/drivers/panfrost/pan_assemble.c b/src/gallium/drivers/panfrost/pan_assemble.c
index a6ba5fa6790e..de8a53ce05d7 100644
--- a/src/gallium/drivers/panfrost/pan_assemble.c
+++ b/src/gallium/drivers/panfrost/pan_assemble.c
@@ -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;
 }
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index 53c2fe3cee79..d178a0f1db21 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -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 =
diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h
index 6f3bca939e51..3eac8d6b5a2b 100644
--- a/src/gallium/drivers/panfrost/pan_context.h
+++ b/src/gallium/drivers/panfrost/pan_context.h
@@ -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];
-- 
2.20.1



More information about the mesa-dev mailing list