tgsi_declaration() configures inputs. Then tgsi_interp_egcm() uses one
of them for interpolation. Unfortunately it was choosing registers by using
Src[0].Register.Index of the interpolation instruction as an index into shader
inputs. Of course it was working by pure coincidence. E.g. for pidglit test
"interpolateAtSample" the order of inputs happened to be IMM[1], then IN[0],
then IN[1]. So instead of indexing into IN[1] it was indexing into IN[0].

The workaround is saving tgsi_file_type in inputs at tgsi_declaration(), and
later at tgsi_interp_egcm() (possibly in other places too) cycling through the
inputs searching for the appropriate one.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=100785

------

Because of unfamilarity with the code architecture I am unsure how to handle
some things, i.e.:

α) For some reason tgsi_declaration() never sees "ctx->shader->input[0]" (i.e.
IMM[1]). It's configured at the end of "allocate_system_value_inputs()" which
is fine, but I can't snoop around for places other than tgsi_declaration()
where inputs could be configured — it would be unreliable and fragile. I tried
forcing to start parse from the beginning just before the cycle where
tgsi_declaration() is called, but it didn't help, for some reason the "0" input
does not appear in the cycle.

I thought at this point it would be better to just ask.

β) I put an assert at tgsi_interp_egcm() in case some bug left the input
register unconfigured. In release version it'd return -ECANCELED — the other
possible fail I found in the function is -ENOMEM, so I don't know if there's a
better value. That said, I don't think it matters much either — there's a
unique print+assert.

Signed-off-by: Constantine Kharlamov <[email protected]>
---
 src/gallium/drivers/r600/r600_shader.c | 23 +++++++++++++++++++++--
 src/gallium/drivers/r600/r600_shader.h |  5 +++--
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_shader.c 
b/src/gallium/drivers/r600/r600_shader.c
index 156dba085d..b373a70bca 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -861,6 +861,7 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
                        ctx->shader->input[i].interpolate = 
d->Interp.Interpolate;
                        ctx->shader->input[i].interpolate_location = 
d->Interp.Location;
                        ctx->shader->input[i].gpr = 
ctx->file_offset[TGSI_FILE_INPUT] + d->Range.First + j;
+                       ctx->shader->input[i].type = TGSI_FILE_INPUT;
                        if (ctx->type == PIPE_SHADER_FRAGMENT) {
                                ctx->shader->input[i].spi_sid = 
r600_spi_sid(&ctx->shader->input[i]);
                                switch (ctx->shader->input[i].name) {
@@ -905,6 +906,7 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
                        ctx->shader->output[i].gpr = 
ctx->file_offset[TGSI_FILE_OUTPUT] + d->Range.First + j;
                        ctx->shader->output[i].interpolate = 
d->Interp.Interpolate;
                        ctx->shader->output[i].write_mask = 
d->Declaration.UsageMask;
+                       ctx->shader->input[i].type = TGSI_FILE_OUTPUT;
                        if (ctx->type == PIPE_SHADER_VERTEX ||
                            ctx->type == PIPE_SHADER_GEOMETRY ||
                            ctx->type == PIPE_SHADER_TESS_EVAL) {
@@ -6316,17 +6318,34 @@ static int tgsi_msb(struct r600_shader_ctx *ctx)
        return 0;
 }
 
+static int tgsi_index_reg_in_inputs(const struct r600_shader *in, const struct 
tgsi_src_register *reg)
+{
+       for (int i = 0, same_type_i = 0; i < in->ninput; ++i) {
+               if (in->input[i].type == reg->File) {
+                       if (same_type_i == reg->Index)
+                               return i;
+                       else
+                               ++same_type_i;
+               }
+       }
+       return -1;
+}
+
 static int tgsi_interp_egcm(struct r600_shader_ctx *ctx)
 {
        struct tgsi_full_instruction *inst = 
&ctx->parse.FullToken.FullInstruction;
        struct r600_bytecode_alu alu;
        int r, i = 0, k, interp_gpr, interp_base_chan, tmp, lasti;
        unsigned location;
-       int input;
+       const int input = tgsi_index_reg_in_inputs(ctx->shader, 
&inst->Src[0].Register);
 
        assert(inst->Src[0].Register.File == TGSI_FILE_INPUT);
 
-       input = inst->Src[0].Register.Index;
+       if (input == -1) {
+               R600_ERR("The register not found in inputs!");
+               assert(false);
+               return -ECANCELED;
+       }
 
        /* Interpolators have been marked for use already by 
allocate_system_value_inputs */
        if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET ||
diff --git a/src/gallium/drivers/r600/r600_shader.h 
b/src/gallium/drivers/r600/r600_shader.h
index cfdb020033..ea141e43b5 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -45,15 +45,16 @@ struct r600_shader_io {
        unsigned                name;
        unsigned                gpr;
        unsigned                done;
+       enum tgsi_file_type     type;
        int                     sid;
        int                     spi_sid;
        unsigned                interpolate;
        unsigned                ij_index;
-       unsigned        interpolate_location; //  TGSI_INTERPOLATE_LOC_CENTER, 
CENTROID, SAMPLE
+       unsigned                interpolate_location; //  
TGSI_INTERPOLATE_LOC_CENTER, CENTROID, SAMPLE
        unsigned                lds_pos; /* for evergreen */
        unsigned                back_color_input;
        unsigned                write_mask;
-       int                             ring_offset;
+       int                     ring_offset;
 };
 
 struct r600_shader {
-- 
2.13.0

_______________________________________________
mesa-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to