r600g: Fix missing SET_TEXTURE_OFFSETS
authorGlenn Kennard <glenn.kennard@gmail.com>
Sun, 17 Aug 2014 20:26:19 +0000 (22:26 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 19 Aug 2014 14:30:13 +0000 (16:30 +0200)
SB needs a bit of special handling to handle
instructions without obvious side effects, to
avoid it deleting them.

Fixes failing non-const ARB_gpu_shader5
textureOffsets piglits with sb enabled.

Signed-off-by: Glenn Kennard <glenn.kennard@gmail.com>
Signed-off-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/r600/r600_isa.h
src/gallium/drivers/r600/sb/sb_bc_finalize.cpp
src/gallium/drivers/r600/sb/sb_bc_parser.cpp
src/gallium/drivers/r600/sb/sb_pass.h

index c6bb869fd10f19b75d46d9f8e52cd55df3e932e9..ec3f7028a980909844575f92cb7116f8680d1a8a 100644 (file)
@@ -123,6 +123,9 @@ enum fetch_op_flags
 
        FF_VTX          = (1<<5),
        FF_MEM          = (1<<6),
+
+       FF_SET_TEXTURE_OFFSETS = (1<<7),
+       FF_USE_TEXTURE_OFFSETS = (1<<8),
 };
 
 /* flags for CF instructions */
@@ -523,7 +526,7 @@ static const struct fetch_op_info fetch_op_table[] = {
                {"GET_GRADIENTS_H_FINE",          {       -1,        -1,  0x000107,  0x000107 }, FF_GETGRAD },
                {"GET_GRADIENTS_V_FINE",          {       -1,        -1,  0x000108,  0x000108 }, FF_GETGRAD },
                {"GET_LERP",                      { 0x000009,  0x000009,        -1,        -1 }, 0 },
-               {"SET_TEXTURE_OFFSETS",           {       -1,        -1,  0x000009,  0x000009 }, 0 },
+               {"SET_TEXTURE_OFFSETS",           {       -1,        -1,  0x000009,  0x000009 }, FF_SET_TEXTURE_OFFSETS },
                {"KEEP_GRADIENTS",                {       -1,  0x00000A,  0x00000A,  0x00000A }, 0 },
                {"SET_GRADIENTS_H",               { 0x00000B,  0x00000B,  0x00000B,  0x00000B }, FF_SETGRAD },
                {"SET_GRADIENTS_V",               { 0x00000C,  0x00000C,  0x00000C,  0x00000C }, FF_SETGRAD },
@@ -550,7 +553,7 @@ static const struct fetch_op_info fetch_op_table[] = {
                {"GATHER4",                       {       -1,        -1,  0x000015,  0x000015 }, FF_TEX },
                {"SAMPLE_G_LB",                   { 0x000016,  0x000016,  0x000016,  0x000016 }, FF_TEX | FF_USEGRAD},
                {"SAMPLE_G_LZ",                   { 0x000017,  0x000017,        -1,        -1 }, FF_TEX | FF_USEGRAD},
-               {"GATHER4_O",                     {       -1,        -1,  0x000017,  0x000017 }, FF_TEX },
+               {"GATHER4_O",                     {       -1,        -1,  0x000017,  0x000017 }, FF_TEX | FF_USE_TEXTURE_OFFSETS},
                {"SAMPLE_C",                      { 0x000018,  0x000018,  0x000018,  0x000018 }, FF_TEX },
                {"SAMPLE_C_L",                    { 0x000019,  0x000019,  0x000019,  0x000019 }, FF_TEX },
                {"SAMPLE_C_LB",                   { 0x00001A,  0x00001A,  0x00001A,  0x00001A }, FF_TEX },
@@ -560,7 +563,7 @@ static const struct fetch_op_info fetch_op_table[] = {
                {"GATHER4_C",                     {       -1,        -1,  0x00001D,  0x00001D }, FF_TEX },
                {"SAMPLE_C_G_LB",                 { 0x00001E,  0x00001E,  0x00001E,  0x00001E }, FF_TEX | FF_USEGRAD},
                {"SAMPLE_C_G_LZ",                 { 0x00001F,  0x00001F,        -1,        -1 }, FF_TEX | FF_USEGRAD},
-               {"GATHER4_C_O",                   {       -1,        -1,  0x00001F,  0x00001F }, FF_TEX }
+               {"GATHER4_C_O",                   {       -1,        -1,  0x00001F,  0x00001F }, FF_TEX | FF_USE_TEXTURE_OFFSETS}
 };
 
 static const struct cf_op_info cf_op_table[] = {
index 99a20eb00c80a07dbcc0cab3541edcbf7e0766d2..5c22f96469026cabffa7dffa6a0152b747dfbdb4 100644 (file)
@@ -394,81 +394,96 @@ void bc_finalizer::finalize_alu_src(alu_group_node* g, alu_node* a) {
        }
 }
 
-void bc_finalizer::emit_set_grad(fetch_node* f) {
+void bc_finalizer::copy_fetch_src(fetch_node &dst, fetch_node &src, unsigned arg_start)
+{
+       int reg = -1;
 
-       assert(f->src.size() == 12);
-       unsigned ops[2] = { FETCH_OP_SET_GRADIENTS_V, FETCH_OP_SET_GRADIENTS_H };
+       for (unsigned chan = 0; chan < 4; ++chan) {
 
-       unsigned arg_start = 0;
+               dst.bc.dst_sel[chan] = SEL_MASK;
 
-       for (unsigned op = 0; op < 2; ++op) {
-               fetch_node *n = sh.create_fetch();
-               n->bc.set_op(ops[op]);
+               unsigned sel = SEL_MASK;
 
-               // FIXME extract this loop into a separate method and reuse it
+               value *v = src.src[arg_start + chan];
 
-               int reg = -1;
+               if (!v || v->is_undef()) {
+                       sel = SEL_MASK;
+               } else if (v->is_const()) {
+                       literal l = v->literal_value;
+                       if (l == literal(0))
+                               sel = SEL_0;
+                       else if (l == literal(1.0f))
+                               sel = SEL_1;
+                       else {
+                               sblog << "invalid fetch constant operand  " << chan << " ";
+                               dump::dump_op(&src);
+                               sblog << "\n";
+                               abort();
+                       }
 
-               arg_start += 4;
+               } else if (v->is_any_gpr()) {
+                       unsigned vreg = v->gpr.sel();
+                       unsigned vchan = v->gpr.chan();
 
-               for (unsigned chan = 0; chan < 4; ++chan) {
+                       if (reg == -1)
+                               reg = vreg;
+                       else if ((unsigned)reg != vreg) {
+                               sblog << "invalid fetch source operand  " << chan << " ";
+                               dump::dump_op(&src);
+                               sblog << "\n";
+                               abort();
+                       }
 
-                       n->bc.dst_sel[chan] = SEL_MASK;
+                       sel = vchan;
 
-                       unsigned sel = SEL_MASK;
+               } else {
+                       sblog << "invalid fetch source operand  " << chan << " ";
+                       dump::dump_op(&src);
+                       sblog << "\n";
+                       abort();
+               }
 
-                       value *v = f->src[arg_start + chan];
+               dst.bc.src_sel[chan] = sel;
+       }
 
-                       if (!v || v->is_undef()) {
-                               sel = SEL_MASK;
-                       } else if (v->is_const()) {
-                               literal l = v->literal_value;
-                               if (l == literal(0))
-                                       sel = SEL_0;
-                               else if (l == literal(1.0f))
-                                       sel = SEL_1;
-                               else {
-                                       sblog << "invalid fetch constant operand  " << chan << " ";
-                                       dump::dump_op(f);
-                                       sblog << "\n";
-                                       abort();
-                               }
+       if (reg >= 0)
+               update_ngpr(reg);
 
-                       } else if (v->is_any_gpr()) {
-                               unsigned vreg = v->gpr.sel();
-                               unsigned vchan = v->gpr.chan();
+       dst.bc.src_gpr = reg >= 0 ? reg : 0;
+}
 
-                               if (reg == -1)
-                                       reg = vreg;
-                               else if ((unsigned)reg != vreg) {
-                                       sblog << "invalid fetch source operand  " << chan << " ";
-                                       dump::dump_op(f);
-                                       sblog << "\n";
-                                       abort();
-                               }
+void bc_finalizer::emit_set_grad(fetch_node* f) {
 
-                               sel = vchan;
+       assert(f->src.size() == 12);
+       unsigned ops[2] = { FETCH_OP_SET_GRADIENTS_V, FETCH_OP_SET_GRADIENTS_H };
 
-                       } else {
-                               sblog << "invalid fetch source operand  " << chan << " ";
-                               dump::dump_op(f);
-                               sblog << "\n";
-                               abort();
-                       }
+       unsigned arg_start = 0;
 
-                       n->bc.src_sel[chan] = sel;
-               }
+       for (unsigned op = 0; op < 2; ++op) {
+               fetch_node *n = sh.create_fetch();
+               n->bc.set_op(ops[op]);
 
-               if (reg >= 0)
-                       update_ngpr(reg);
+               arg_start += 4;
 
-               n->bc.src_gpr = reg >= 0 ? reg : 0;
+               copy_fetch_src(*n, *f, arg_start);
 
                f->insert_before(n);
        }
 
 }
 
+void bc_finalizer::emit_set_texture_offsets(fetch_node &f) {
+       assert(f.src.size() == 8);
+
+       fetch_node *n = sh.create_fetch();
+
+       n->bc.set_op(FETCH_OP_SET_TEXTURE_OFFSETS);
+
+       copy_fetch_src(*n, f, 4);
+
+       f.insert_before(n);
+}
+
 void bc_finalizer::finalize_fetch(fetch_node* f) {
 
        int reg = -1;
@@ -483,6 +498,8 @@ void bc_finalizer::finalize_fetch(fetch_node* f) {
                src_count = 1;
        } else if (flags & FF_USEGRAD) {
                emit_set_grad(f);
+       } else if (flags & FF_USE_TEXTURE_OFFSETS) {
+               emit_set_texture_offsets(*f);
        }
 
        for (unsigned chan = 0; chan < src_count; ++chan) {
index 7181e27acf07797e4811b87ed120b37bd339cbda..346ccc9dbc5a0a8f83b8a1364ccd973032168c8d 100644 (file)
@@ -520,7 +520,7 @@ int bc_parser::decode_fetch_clause(cf_node* cf) {
 
 int bc_parser::prepare_fetch_clause(cf_node *cf) {
 
-       vvec grad_v, grad_h;
+       vvec grad_v, grad_h, texture_offsets;
 
        for (node_iterator I = cf->begin(), E = cf->end(); I != E; ++I) {
 
@@ -538,7 +538,7 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) {
                        sh->uses_gradients = true;
                }
 
-               if (flags & FF_SETGRAD) {
+               if (flags & (FF_SETGRAD | FF_SET_TEXTURE_OFFSETS)) {
 
                        vvec *grad = NULL;
 
@@ -549,6 +549,9 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) {
                                case FETCH_OP_SET_GRADIENTS_H:
                                        grad = &grad_h;
                                        break;
+                               case FETCH_OP_SET_TEXTURE_OFFSETS:
+                                       grad = &texture_offsets;
+                                       break;
                                default:
                                        assert(!"unexpected SET_GRAD instruction");
                                        return -1;
@@ -568,11 +571,15 @@ int bc_parser::prepare_fetch_clause(cf_node *cf) {
                                        (*grad)[s] = sh->get_const_value(1.0f);
                        }
                } else {
-
+                       // Fold source values for instructions with hidden target values in to the instructions
+                       // using them. The set instructions are later re-emitted by bc_finalizer
                        if (flags & FF_USEGRAD) {
                                n->src.resize(12);
                                std::copy(grad_v.begin(), grad_v.end(), n->src.begin() + 4);
                                std::copy(grad_h.begin(), grad_h.end(), n->src.begin() + 8);
+                       } else if (flags & FF_USE_TEXTURE_OFFSETS) {
+                               n->src.resize(8);
+                               std::copy(texture_offsets.begin(), texture_offsets.end(), n->src.begin() + 4);
                        } else {
                                n->src.resize(4);
                        }
index c955656449fbf04fa97d3df5b4f70c1c37b4a5a9..812d14a9d967fd01ffe2e35cc0192bbe5bdbf436 100644 (file)
@@ -713,6 +713,9 @@ public:
 
        void cf_peephole();
 
+private:
+       void copy_fetch_src(fetch_node &dst, fetch_node &src, unsigned arg_start);
+       void emit_set_texture_offsets(fetch_node &f);
 };