From: Gert Wollny Date: Sat, 18 Jul 2020 18:34:37 +0000 (+0200) Subject: r600/sfn: correct handling of loading vec4 with fetching constants X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d31ef0b7a4b9bc4e36733e68aaff19399cb6d56c;p=mesa.git r600/sfn: correct handling of loading vec4 with fetching constants Signed-off-by: Gert Wollny Part-of: --- 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 src0, const std::set& 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 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);