freedreno/ir3: fix issue w/ glamor composite shaders
authorRob Clark <robdclark@gmail.com>
Sat, 31 Mar 2018 18:36:37 +0000 (14:36 -0400)
committerRob Clark <robdclark@gmail.com>
Sat, 31 Mar 2018 20:25:13 +0000 (16:25 -0400)
Fixes an issue that became possible when we started lowering phi webs to
regs (a7ea2b4e) (although was not really seen until we also switched to
using peephole select pass (ec8bc54a) instead of lowering *all* if/else
to select).

If texture coord (or anything else that uses create_collect() to collect
scalar values in a sequence of scalar registers) was consuming a value
produced on either side of an if/else (ie. a phi lowered to nir reg,
which in ir3 is an "array" of length 1) then register allocation would
happen incorrectly and we'd end up sampling from garbage coordinates.

Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
src/gallium/drivers/freedreno/ir3/ir3_cp.c

index 62342be2bbbdb6825c6cd48bd968d0e9f85129df..3d3c85dd03b702be5719eee0f14cdde57b1e86c5 100644 (file)
@@ -686,8 +686,39 @@ create_collect(struct ir3_context *ctx, struct ir3_instruction *const *arr,
        collect = ir3_instr_create2(block, OPC_META_FI, 1 + arrsz);
        ir3_reg_create(collect, 0, flags);     /* dst */
        for (unsigned i = 0; i < arrsz; i++) {
-               compile_assert(ctx, (arr[i]->regs[0]->flags & IR3_REG_HALF) == flags);
-               ir3_reg_create(collect, 0, IR3_REG_SSA | flags)->instr = arr[i];
+               struct ir3_instruction *elem = arr[i];
+
+               /* Since arrays are pre-colored in RA, we can't assume that
+                * things will end up in the right place.  (Ie. if a collect
+                * joins elements from two different arrays.)  So insert an
+                * extra mov.
+                *
+                * We could possibly skip this if all the collected elements
+                * are contiguous elements in a single array.. not sure how
+                * likely that is to happen.
+                *
+                * Fixes a problem with glamor shaders, that in effect do
+                * something like:
+                *
+                *   if (foo)
+                *     texcoord = ..
+                *   else
+                *     texcoord = ..
+                *   color = texture2D(tex, texcoord);
+                *
+                * In this case, texcoord will end up as nir registers (which
+                * translate to ir3 array's of length 1.  And we can't assume
+                * the two (or more) arrays will get allocated in consecutive
+                * scalar registers.
+                *
+                */
+               if (elem->regs[0]->flags & IR3_REG_ARRAY) {
+                       type_t type = (flags & IR3_REG_HALF) ? TYPE_U16 : TYPE_U32;
+                       elem = ir3_MOV(block, elem, type);
+               }
+
+               compile_assert(ctx, (elem->regs[0]->flags & IR3_REG_HALF) == flags);
+               ir3_reg_create(collect, 0, IR3_REG_SSA | flags)->instr = elem;
        }
 
        return collect;
index 67a7714b9c5078198770c354a5556e1608b0ccd5..e3a3a9db690758f53f330555ff57114158e8bb69 100644 (file)
@@ -59,6 +59,9 @@ static bool is_eligible_mov(struct ir3_instruction *instr, bool allow_flags)
                if (src->flags & IR3_REG_RELATIV)
                        return false;
 
+               if (src->flags & IR3_REG_ARRAY)
+                       return false;
+
                if (!allow_flags)
                        if (src->flags & (IR3_REG_FABS | IR3_REG_FNEG |
                                        IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT))