diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp b/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp index 5fb3c445a1b..14b97f2b7f2 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instr_tex.cpp @@ -357,6 +357,28 @@ bool TexInstr::from_nir(nir_tex_instr *tex, Shader& shader) return true; } +bool TexInstr::replace_source(PRegister old_src, PVirtualValue new_src) +{ + if (old_src->pin() != pin_free) + return false; + + if (!new_src->as_register()) + return false; + + bool success = false; + for (int i = 0; i < 4; ++i) { + if (m_src[i]->equal_to(*old_src)) { + m_src.set_value(i, new_src->as_register()); + success = true; + } + } + if (success) { + old_src->del_use(this); + new_src->as_register()->add_use(this); + } + return success; +} + struct SamplerId { int id; bool indirect; diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_tex.h b/src/gallium/drivers/r600/sfn/sfn_instr_tex.h index 03e010751cc..46fabd7f503 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_tex.h +++ b/src/gallium/drivers/r600/sfn/sfn_instr_tex.h @@ -154,6 +154,8 @@ public: auto prepare_instr() const { return m_prepare_instr;} + bool replace_source(PRegister old_src, PVirtualValue new_src) override; + private: bool do_ready() const override; diff --git a/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp b/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp index c166b0af7ba..a28ae322cba 100644 --- a/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp @@ -522,7 +522,20 @@ void SimplifySourceVecVisitor::visit(TexInstr *instr) { if (instr->opcode() != TexInstr::get_resinfo) { - replace_src(instr, instr->src()); + auto& src = instr->src(); + replace_src(instr, src); + int nvals = 0; + for (int i = 0; i < 4; ++i) + if (src[i]->chan() < 4) + ++nvals; + if (nvals == 1) { + for (int i = 0; i < 4; ++i) + if (src[i]->chan() < 4) + src[i]->set_pin(pin_free); + } + } + for (auto& prep : instr->prepare_instr()) { + prep->accept(*this); } } diff --git a/src/gallium/drivers/r600/sfn/sfn_virtualvalues.h b/src/gallium/drivers/r600/sfn/sfn_virtualvalues.h index 569eaa1d6bf..5c008e49ae8 100644 --- a/src/gallium/drivers/r600/sfn/sfn_virtualvalues.h +++ b/src/gallium/drivers/r600/sfn/sfn_virtualvalues.h @@ -272,21 +272,27 @@ public: return m_values[i]->value(); } - PRegister operator [] (int i) { - return m_values[i]->value(); - } + PRegister operator [] (int i) { + return m_values[i]->value(); + } - void set_value(int i, PRegister reg) { - assert(reg->sel() == m_sel); - m_swz[i] = reg->chan(); - m_values[i]->set_value(reg); - } + void set_value(int i, PRegister reg) { + if (reg->chan() < 4) { + for (int k = 0; k < 4; ++k) { + assert(i == k || m_values[k]->value()->chan() > 3 || + m_values[k]->value()->sel() == reg->sel()); + } + m_sel = reg->sel(); + } + m_swz[i] = reg->chan(); + m_values[i]->set_value(reg); + } - bool ready(int block_id, int index) const; + bool ready(int block_id, int index) const; private: - int m_sel; - Swizzle m_swz; - std::array m_values; + int m_sel; + Swizzle m_swz; + std::array m_values; }; bool operator == (const RegisterVec4& lhs, const RegisterVec4& rhs);