r600/sfn: Always start a new CF after a KILL instruction
Docu says:
Ensure that the KILL* instruction is the last instruction
in an ALU clause, because the remaining instructions executed
in the clause do not reflect the updated valid state after
the kill operation.
Fixes: 79ca456b48
r600/sfn: rewrite NIR backend
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18983>
This commit is contained in:
@@ -35,6 +35,25 @@ AluGroup::AluGroup()
|
|||||||
std::fill(m_slots.begin(), m_slots.end(), nullptr);
|
std::fill(m_slots.begin(), m_slots.end(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_kill(EAluOp op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case op2_kille:
|
||||||
|
case op2_kille_int:
|
||||||
|
case op2_killne:
|
||||||
|
case op2_killne_int:
|
||||||
|
case op2_killge:
|
||||||
|
case op2_killge_int:
|
||||||
|
case op2_killge_uint:
|
||||||
|
case op2_killgt:
|
||||||
|
case op2_killgt_int:
|
||||||
|
case op2_killgt_uint:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool AluGroup::add_instruction(AluInstr *instr)
|
bool AluGroup::add_instruction(AluInstr *instr)
|
||||||
{
|
{
|
||||||
/* we can only schedule one op that accesses LDS or
|
/* we can only schedule one op that accesses LDS or
|
||||||
@@ -45,12 +64,17 @@ bool AluGroup::add_instruction(AluInstr *instr)
|
|||||||
if (instr->has_alu_flag(alu_is_trans)) {
|
if (instr->has_alu_flag(alu_is_trans)) {
|
||||||
ASSERTED auto opinfo = alu_ops.find(instr->opcode());
|
ASSERTED auto opinfo = alu_ops.find(instr->opcode());
|
||||||
assert(opinfo->second.can_channel(AluOp::t, s_chip_class));
|
assert(opinfo->second.can_channel(AluOp::t, s_chip_class));
|
||||||
if (add_trans_instructions(instr))
|
if (add_trans_instructions(instr)) {
|
||||||
|
if (is_kill(instr->opcode()))
|
||||||
|
m_has_kill_op = true;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_vec_instructions(instr) && !instr->has_alu_flag(alu_is_trans)) {
|
if (add_vec_instructions(instr) && !instr->has_alu_flag(alu_is_trans)) {
|
||||||
instr->set_parent_group(this);
|
instr->set_parent_group(this);
|
||||||
|
if (!instr->has_alu_flag(alu_is_lds) && is_kill(instr->opcode()))
|
||||||
|
m_has_kill_op = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +85,8 @@ bool AluGroup::add_instruction(AluInstr *instr)
|
|||||||
opinfo->second.can_channel(AluOp::t, s_chip_class) &&
|
opinfo->second.can_channel(AluOp::t, s_chip_class) &&
|
||||||
add_trans_instructions(instr)) {
|
add_trans_instructions(instr)) {
|
||||||
instr->set_parent_group(this);
|
instr->set_parent_group(this);
|
||||||
|
if (is_kill(instr->opcode()))
|
||||||
|
m_has_kill_op = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -87,6 +87,7 @@ public:
|
|||||||
static bool has_t() { return s_max_slots == 5;}
|
static bool has_t() { return s_max_slots == 5;}
|
||||||
|
|
||||||
bool addr_for_src() const { return m_addr_for_src;}
|
bool addr_for_src() const { return m_addr_for_src;}
|
||||||
|
bool has_kill_op() const {return m_has_kill_op;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void forward_set_blockid(int id, int index) override;
|
void forward_set_blockid(int id, int index) override;
|
||||||
@@ -111,6 +112,7 @@ private:
|
|||||||
bool m_has_lds_op{false};
|
bool m_has_lds_op{false};
|
||||||
bool m_addr_is_index{false};
|
bool m_addr_is_index{false};
|
||||||
bool m_addr_for_src{false};
|
bool m_addr_for_src{false};
|
||||||
|
bool m_has_kill_op{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -294,7 +294,6 @@ void BlockSheduler::schedule_block(Block& in_block, Shader::ShaderBlocks& out_bl
|
|||||||
bool have_instr = collect_ready(cir);
|
bool have_instr = collect_ready(cir);
|
||||||
|
|
||||||
m_current_block = new Block(in_block.nesting_depth(), in_block.id());
|
m_current_block = new Block(in_block.nesting_depth(), in_block.id());
|
||||||
|
|
||||||
assert(m_current_block->id() >= 0);
|
assert(m_current_block->id() >= 0);
|
||||||
|
|
||||||
while (have_instr) {
|
while (have_instr) {
|
||||||
@@ -569,6 +568,13 @@ bool BlockSheduler::schedule_alu(Shader::ShaderBlocks& out_blocks)
|
|||||||
if (group->has_lds_group_end())
|
if (group->has_lds_group_end())
|
||||||
m_current_block->lds_group_end();
|
m_current_block->lds_group_end();
|
||||||
|
|
||||||
|
if (group->has_kill_op()) {
|
||||||
|
assert(!group->has_lds_group_start());
|
||||||
|
start_new_block(out_blocks, Block::alu);
|
||||||
|
m_current_block->set_instr_flag(Instr::force_cf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -178,6 +178,7 @@ bool FragmentShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
|
|||||||
value_factory().zero(),
|
value_factory().zero(),
|
||||||
value_factory().zero(),
|
value_factory().zero(),
|
||||||
{AluInstr::last}));
|
{AluInstr::last}));
|
||||||
|
start_new_block(0);
|
||||||
return true;
|
return true;
|
||||||
case nir_intrinsic_load_sample_mask_in:
|
case nir_intrinsic_load_sample_mask_in:
|
||||||
if (m_apply_sample_mask) {
|
if (m_apply_sample_mask) {
|
||||||
|
Reference in New Issue
Block a user