freedreno/ir3: fix fixing-up register footprint
authorRob Clark <robdclark@gmail.com>
Wed, 28 Feb 2018 22:33:29 +0000 (17:33 -0500)
committerRob Clark <robdclark@gmail.com>
Mon, 5 Mar 2018 13:05:33 +0000 (08:05 -0500)
It isn't just vertex shaders that need to fixup reg footprint for inputs
populated before shader starts.

This problem showed up with compute shaders.  If you have (for example)
a localregid sysval, but only the .x component is used, the hw still
writes the .yz components, which could overflow into other threads
causing corruption.  Showed up in cl cts 'basic/test_basic intmath_int'.
But in theory the same problem could crop up elsewhere.

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

index 1c8d836a87f720e7fae2efd9a242a61f2551d517..8644bc1921890c5c652a7702d746a86006356aa4 100644 (file)
@@ -3418,7 +3418,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
                        so->varying_in++;
                        so->inputs[i].compmask = (1 << maxcomp) - 1;
                        inloc += maxcomp;
-               } else {
+               } else if (!so->inputs[i].sysval){
                        so->inputs[i].compmask = compmask;
                }
                so->inputs[i].regid = regid;
index 3d6cae9f80ee31b50a0e1d3fee6ed3d4527a235d..555c654374e4fee7a82d364db3ded4b26760108e 100644 (file)
@@ -70,26 +70,35 @@ delete_variant(struct ir3_shader_variant *v)
 static void
 fixup_regfootprint(struct ir3_shader_variant *v)
 {
-       if (v->type == SHADER_VERTEX) {
-               unsigned i;
-               for (i = 0; i < v->inputs_count; i++) {
-                       /* skip frag inputs fetch via bary.f since their reg's are
-                        * not written by gpu before shader starts (and in fact the
-                        * regid's might not even be valid)
-                        */
-                       if (v->inputs[i].bary)
-                               continue;
+       unsigned i;
 
-                       if (v->inputs[i].compmask) {
-                               int32_t regid = (v->inputs[i].regid + 3) >> 2;
-                               v->info.max_reg = MAX2(v->info.max_reg, regid);
-                       }
-               }
-               for (i = 0; i < v->outputs_count; i++) {
-                       int32_t regid = (v->outputs[i].regid + 3) >> 2;
+       for (i = 0; i < v->inputs_count; i++) {
+               /* skip frag inputs fetch via bary.f since their reg's are
+                * not written by gpu before shader starts (and in fact the
+                * regid's might not even be valid)
+                */
+               if (v->inputs[i].bary)
+                       continue;
+
+               /* ignore high regs that are global to all threads in a warp
+                * (they exist by default) (a5xx+)
+                */
+               if (v->inputs[i].regid >= regid(48,0))
+                       continue;
+
+               if (v->inputs[i].compmask) {
+                       unsigned n = util_last_bit(v->inputs[i].compmask) - 1;
+                       int32_t regid = (v->inputs[i].regid + n) >> 2;
                        v->info.max_reg = MAX2(v->info.max_reg, regid);
                }
-       } else if (v->type == SHADER_FRAGMENT) {
+       }
+
+       for (i = 0; i < v->outputs_count; i++) {
+               int32_t regid = (v->outputs[i].regid + 3) >> 2;
+               v->info.max_reg = MAX2(v->info.max_reg, regid);
+       }
+
+       if (v->type == SHADER_FRAGMENT) {
                /* NOTE: not sure how to turn pos_regid off..  but this could
                 * be, for example, r1.x while max reg used by the shader is
                 * r0.*, in which case we need to fixup the reg footprint: