r600/sfn: correct handling of loading vec4 with fetching constants
authorGert Wollny <gert.wollny@collabora.com>
Sat, 18 Jul 2020 18:34:37 +0000 (20:34 +0200)
committerMarge Bot <eric+marge@anholt.net>
Mon, 20 Jul 2020 09:32:51 +0000 (09:32 +0000)
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5963>

src/gallium/drivers/r600/sfn/sfn_emitinstruction.cpp
src/gallium/drivers/r600/sfn/sfn_emitinstruction.h
src/gallium/drivers/r600/sfn/sfn_shader_base.cpp
src/gallium/drivers/r600/sfn/sfn_shader_base.h

index 40a99156f7c68722dd8aeb4db3e2b4c8a915ef58..62212b911c507150ffa9c3fb3afd378ed9cba38d 100644 (file)
@@ -93,9 +93,9 @@ EmitInstruction::get_deref_location(const nir_src& v) const
    return m_proc.get_deref_location(v);
 }
 
-PValue EmitInstruction::from_nir_with_fetch_constant(const nir_src& src, unsigned component)
+PValue EmitInstruction::from_nir_with_fetch_constant(const nir_src& src, unsigned component, int channel)
 {
-   return m_proc.from_nir_with_fetch_constant(src, component);
+   return m_proc.from_nir_with_fetch_constant(src, component, channel);
 }
 
 GPRVector EmitInstruction::vec_from_nir_with_fetch_constant(const nir_src& src, unsigned mask,
index 9e1958f431f6b85b90ddfbeb0bbd6b4505d7bc55..1629571351177e143f13e4efde2518c1bc3ffc21 100644 (file)
@@ -76,7 +76,7 @@ protected:
                          std::vector<PValue> src0,
                          const std::set<AluModifiers>& m_flags);
 
-   PValue from_nir_with_fetch_constant(const nir_src& src, unsigned component);
+   PValue from_nir_with_fetch_constant(const nir_src& src, unsigned component, int channel = -1);
    GPRVector vec_from_nir_with_fetch_constant(const nir_src& src, unsigned mask,
                                               const GPRVector::Swizzle& swizzle, bool match = false);
 
index 3a057784730babdc838249732b44e168c7c109e0..5e48e6da0fac3c4c850e2f46af94c50fef8504dc 100644 (file)
@@ -746,48 +746,83 @@ GPRVector ShaderFromNirProcessor::vec_from_nir_with_fetch_constant(const nir_src
    bool use_same = true;
    GPRVector::Values v;
 
+   std::array<bool,4> used_swizzles = {false, false, false, false};
+
+   /* Check whether all sources come from a GPR, and,
+    * if requested, whether they are swizzled as epected */
+
    for (int i = 0; i < 4 && use_same; ++i)  {
       if ((1 << i) & mask) {
          if (swizzle[i] < 4) {
             v[i] = from_nir(src, swizzle[i]);
             assert(v[i]);
-            if (v[i]->type() != Value::gpr)
-               use_same = false;
-            if (match && (v[i]->chan() != swizzle[i]))
-                use_same = false;
+            use_same &= (v[i]->type() == Value::gpr);
+            if (match) {
+               use_same &= (v[i]->chan() == swizzle[i]);
+            }
+            used_swizzles[v[i]->chan()] = true;
          }
       }
    }
 
+
+   /* Now check whether all inputs come from the same GPR, and fill
+    * empty slots in the vector with unused swizzles, bail out if
+    * the sources are not from the same GPR
+    */
+
    if (use_same) {
+      int next_free_swizzle = 0;
+      while (used_swizzles[next_free_swizzle] && next_free_swizzle < 4)
+         next_free_swizzle++;
+
+      /* Find the first GPR index used */
       int i = 0;
       while (!v[i] && i < 4) ++i;
       assert(i < 4);
-
       unsigned sel = v[i]->sel();
+
+
       for (i = 0; i < 4 && use_same; ++i) {
-         if (!v[i])
-            v[i] = PValue(new GPRValue(sel, swizzle[i]));
+         if (!v[i]) {
+            if (swizzle[i] >= 4)
+               v[i] = PValue(new GPRValue(sel, swizzle[i]));
+            else {
+               assert(next_free_swizzle < 4);
+               v[i] = PValue(new GPRValue(sel, next_free_swizzle));
+            }
+
+            if (swizzle[i] < 4) {
+               used_swizzles[next_free_swizzle] = true;
+               while (next_free_swizzle < 4 && used_swizzles[swizzle[next_free_swizzle]])
+                  next_free_swizzle++;
+            }
+         }
          else
             use_same &= v[i]->sel() == sel;
       }
    }
 
+   /* We can't re-use the source data because they either need re-swizzling, or
+    * they didn't come all from a GPR or the same GPR, so copy to a new vector
+    */
    if (!use_same) {
       AluInstruction *ir = nullptr;
-      int sel = allocate_temp_register();
+      GPRVector result(allocate_temp_register(), swizzle);
       for (int i = 0; i < 4; ++i) {
-         v[i] = PValue(new GPRValue(sel, swizzle[i]));
          if (swizzle[i] < 4 && (mask & (1 << i))) {
-            ir = new AluInstruction(op1_mov, v[i], from_nir(src, swizzle[i]),
+            ir = new AluInstruction(op1_mov, result[i], from_nir(src, swizzle[i]),
                                     EmitInstruction::write);
             emit_instruction(ir);
+         } else {
+
          }
       }
       if (ir)
          ir->set_flag(alu_last_instr);
-   }
-   return GPRVector(v);;
+      return result;
+   } else
+      return GPRVector(v);;
 }
 
 bool ShaderFromNirProcessor::emit_load_ubo(nir_intrinsic_instr* instr)
@@ -983,13 +1018,13 @@ AluInstruction *ShaderFromNirProcessor::emit_load_literal(const nir_load_const_i
    return ir;
 }
 
-PValue ShaderFromNirProcessor::from_nir_with_fetch_constant(const nir_src& src, unsigned component)
+PValue ShaderFromNirProcessor::from_nir_with_fetch_constant(const nir_src& src, unsigned component, int channel)
 {
    PValue value = from_nir(src, component);
    if (value->type() != Value::gpr &&
        value->type() != Value::gpr_vector &&
        value->type() != Value::gpr_array_value) {
-      PValue retval = get_temp_register();
+      PValue retval = get_temp_register(channel);
       emit_instruction(new AluInstruction(op1_mov, retval, value,
                                           EmitInstruction::last_write));
       value = retval;
index 0dcf36b087629f2408cca879ba6d5fb3e7d2c28e..13c9477577869677d674783e2bdbf72a96d3b5da 100644 (file)
@@ -62,7 +62,7 @@ public:
 
    void emit_instruction(Instruction *ir);
 
-   PValue from_nir_with_fetch_constant(const nir_src& src, unsigned component);
+   PValue from_nir_with_fetch_constant(const nir_src& src, unsigned component, int channel = -1);
    GPRVector vec_from_nir_with_fetch_constant(const nir_src& src, unsigned mask,
                                               const GPRVector::Swizzle& swizzle, bool match = false);