r600g: fix dynamic_input_array_index.shader_test
authorDave Airlie <airlied@redhat.com>
Fri, 24 Jan 2014 04:46:37 +0000 (14:46 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 5 Feb 2014 00:49:40 +0000 (10:49 +1000)
This follows what fglrx does, it unpacks the input we are
going to indirect into a bunch of registers and indirects
inside them.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/drivers/r600/r600_shader.c

index cc2000d5ed5e558ec46f9859c89896f6c65eb5b1..a58955a81485d69888d320a4a1821daed081450a 100644 (file)
@@ -834,10 +834,12 @@ static int tgsi_fetch_rel_const(struct r600_shader_ctx *ctx, unsigned int cb_idx
        return 0;
 }
 
-static int fetch_gs_input(struct r600_shader_ctx *ctx, unsigned index, unsigned vtx_id, unsigned int dst_reg)
+static int fetch_gs_input(struct r600_shader_ctx *ctx, struct tgsi_full_src_register *src, unsigned int dst_reg)
 {
        struct r600_bytecode_vtx vtx;
        int r;
+       unsigned index = src->Register.Index;
+       unsigned vtx_id = src->Dimension.Index;
        int offset_reg = vtx_id / 3;
        int offset_chan = vtx_id % 3;
 
@@ -847,6 +849,46 @@ static int fetch_gs_input(struct r600_shader_ctx *ctx, unsigned index, unsigned
        if (offset_reg == 0 && offset_chan == 2)
                offset_chan = 3;
 
+       if (src->Dimension.Indirect) {
+               int treg[3];
+               int t2;
+               struct r600_bytecode_alu alu;
+               int r, i;
+
+               /* you have got to be shitting me -
+                  we have to put the R0.x/y/w into Rt.x Rt+1.x Rt+2.x then index reg from Rt.
+                  at least this is what fglrx seems to do. */
+               for (i = 0; i < 3; i++) {
+                       treg[i] = r600_get_temp(ctx);
+               }
+               t2 = r600_get_temp(ctx);
+               for (i = 0; i < 3; i++) {
+                       memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+                       alu.op = ALU_OP1_MOV;
+                       alu.src[0].sel = 0;
+                       alu.src[0].chan = i == 2 ? 3 : i;
+                       alu.dst.sel = treg[i];
+                       alu.dst.chan = 0;
+                       alu.dst.write = 1;
+                       alu.last = 1;
+                       r = r600_bytecode_add_alu(ctx->bc, &alu);
+                       if (r)
+                               return r;
+               }
+               memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+               alu.op = ALU_OP1_MOV;
+               alu.src[0].sel = treg[0];
+               alu.src[0].rel = 1;
+               alu.dst.sel = t2;
+               alu.dst.write = 1;
+               alu.last = 1;
+               r = r600_bytecode_add_alu(ctx->bc, &alu);
+               if (r)
+                       return r;
+               offset_reg = t2;
+       }
+
+
        memset(&vtx, 0, sizeof(vtx));
        vtx.buffer_id = R600_GS_RING_CONST_BUFFER;
        vtx.fetch_type = 2;             /* VTX_FETCH_NO_INDEX_OFFSET */
@@ -884,10 +926,8 @@ static int tgsi_split_gs_inputs(struct r600_shader_ctx *ctx)
                }
                if (src->Register.File == TGSI_FILE_INPUT && src->Register.Dimension) {
                        int treg = r600_get_temp(ctx);
-                       int index = src->Register.Index;
-                       int vtx_id = src->Dimension.Index;
 
-                       fetch_gs_input(ctx, index, vtx_id, treg);
+                       fetch_gs_input(ctx, src, treg);
                        ctx->src[i].sel = treg;
                }
        }