freedreno/a3xx: fix const confusion
authorRob Clark <robclark@freedesktop.org>
Tue, 14 Jan 2014 14:54:02 +0000 (09:54 -0500)
committerRob Clark <robclark@freedesktop.org>
Sat, 1 Feb 2014 16:57:09 +0000 (11:57 -0500)
Gallium can leave const buffers bound above what is used by the current
shader.  Which can have a couple bad effects:

1) write beyond const space assigned, which can trigger HLSQ lockup
2) double emit of immed consts, first with bound const buffer vals
followed by with actual immed vals.  This seems to be a sort of
undefined condition.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
src/gallium/drivers/freedreno/a3xx/fd3_compiler.c
src/gallium/drivers/freedreno/a3xx/fd3_emit.c

index 3fd3c5a6f32e4ab67653d40feb5955be7d466170..c8e66fc76dd3a0cf9cd41dde3219fc163a6afa3b 100644 (file)
@@ -157,7 +157,7 @@ compile_init(struct fd3_compile_context *ctx, struct fd3_shader_stateobj *so,
                        info->file_max[TGSI_FILE_OUTPUT] + 1;
 
        so->first_immediate = ctx->base_reg[TGSI_FILE_IMMEDIATE];
-       ctx->immediate_idx = 4 * (info->file_max[TGSI_FILE_IMMEDIATE] + 1);
+       ctx->immediate_idx = 4 * (ctx->info.file_max[TGSI_FILE_IMMEDIATE] + 1);
 
        ret = tgsi_parse_init(&ctx->parser, tokens);
        if (ret != TGSI_PARSE_OK)
index c479666b1cf5b50f1aaadea94879de39e4172a17..543c116ce2f70a273fb17cad95ab0ad418b151ad 100644 (file)
@@ -115,12 +115,10 @@ emit_constants(struct fd_ringbuffer *ring,
                // I expect that size should be a multiple of vec4's:
                assert(size == align(size, 4));
 
-               /* gallium could have const-buffer still bound, even though the
-                * shader is not using it.  Writing consts above constlen (or
-                * rather, HLSQ_{VS,FS}_CONTROL_REG.CONSTLENGTH) will cause a
-                * hang.
+               /* gallium could leave const buffers bound above what the
+                * current shader uses.. don't let that confuse us.
                 */
-               if ((base / 4) >= shader->constlen)
+               if (base >= (4 * shader->first_immediate))
                        break;
 
                if (constbuf->dirty_mask & (1 << index)) {
@@ -137,9 +135,11 @@ emit_constants(struct fd_ringbuffer *ring,
        /* emit shader immediates: */
        if (shader) {
                for (i = 0; i < shader->immediates_count; i++) {
-                       fd3_emit_constant(ring, sb,
-                                       4 * (shader->first_immediate + i),
-                                       0, 4, shader->immediates[i].val, NULL);
+                       base = 4 * (shader->first_immediate + i);
+                       if (base >= (4 * shader->constlen))
+                               break;
+                       fd3_emit_constant(ring, sb, base,
+                               0, 4, shader->immediates[i].val, NULL);
                }
        }
 }