Mesa (master): r600/sfn: correct handling of loading vec4 with fetching constants
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Jul 20 09:42:30 UTC 2020
Module: Mesa
Branch: master
Commit: d31ef0b7a4b9bc4e36733e68aaff19399cb6d56c
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=d31ef0b7a4b9bc4e36733e68aaff19399cb6d56c
Author: Gert Wollny <gert.wollny at collabora.com>
Date: Sat Jul 18 20:34:37 2020 +0200
r600/sfn: correct handling of loading vec4 with fetching constants
Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5963>
---
.../drivers/r600/sfn/sfn_emitinstruction.cpp | 4 +-
src/gallium/drivers/r600/sfn/sfn_emitinstruction.h | 2 +-
src/gallium/drivers/r600/sfn/sfn_shader_base.cpp | 63 +++++++++++++++++-----
src/gallium/drivers/r600/sfn/sfn_shader_base.h | 2 +-
4 files changed, 53 insertions(+), 18 deletions(-)
diff --git a/src/gallium/drivers/r600/sfn/sfn_emitinstruction.cpp b/src/gallium/drivers/r600/sfn/sfn_emitinstruction.cpp
index 40a99156f7c..62212b911c5 100644
--- a/src/gallium/drivers/r600/sfn/sfn_emitinstruction.cpp
+++ b/src/gallium/drivers/r600/sfn/sfn_emitinstruction.cpp
@@ -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,
diff --git a/src/gallium/drivers/r600/sfn/sfn_emitinstruction.h b/src/gallium/drivers/r600/sfn/sfn_emitinstruction.h
index 9e1958f431f..16295713511 100644
--- a/src/gallium/drivers/r600/sfn/sfn_emitinstruction.h
+++ b/src/gallium/drivers/r600/sfn/sfn_emitinstruction.h
@@ -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);
diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp b/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp
index 3a057784730..5e48e6da0fa 100644
--- a/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp
+++ b/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp
@@ -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;
diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_base.h b/src/gallium/drivers/r600/sfn/sfn_shader_base.h
index 0dcf36b0876..13c94775778 100644
--- a/src/gallium/drivers/r600/sfn/sfn_shader_base.h
+++ b/src/gallium/drivers/r600/sfn/sfn_shader_base.h
@@ -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);
More information about the mesa-commit
mailing list