diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp index 64af17c7a6d..35b76763921 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.cpp @@ -35,6 +35,25 @@ AluGroup::AluGroup() 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) { /* 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)) { ASSERTED auto opinfo = alu_ops.find(instr->opcode()); 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; + } } if (add_vec_instructions(instr) && !instr->has_alu_flag(alu_is_trans)) { instr->set_parent_group(this); + if (!instr->has_alu_flag(alu_is_lds) && is_kill(instr->opcode())) + m_has_kill_op = true; return true; } @@ -61,6 +85,8 @@ bool AluGroup::add_instruction(AluInstr *instr) opinfo->second.can_channel(AluOp::t, s_chip_class) && add_trans_instructions(instr)) { instr->set_parent_group(this); + if (is_kill(instr->opcode())) + m_has_kill_op = true; return true; } diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h index df58df8204a..2ff31628c2c 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h +++ b/src/gallium/drivers/r600/sfn/sfn_instr_alugroup.h @@ -87,6 +87,7 @@ public: static bool has_t() { return s_max_slots == 5;} bool addr_for_src() const { return m_addr_for_src;} + bool has_kill_op() const {return m_has_kill_op;} private: void forward_set_blockid(int id, int index) override; @@ -111,6 +112,7 @@ private: bool m_has_lds_op{false}; bool m_addr_is_index{false}; bool m_addr_for_src{false}; + bool m_has_kill_op{false}; }; diff --git a/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp b/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp index e63103491c8..6eccc003fc7 100644 --- a/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_scheduler.cpp @@ -294,7 +294,6 @@ void BlockSheduler::schedule_block(Block& in_block, Shader::ShaderBlocks& out_bl bool have_instr = collect_ready(cir); m_current_block = new Block(in_block.nesting_depth(), in_block.id()); - assert(m_current_block->id() >= 0); while (have_instr) { @@ -569,6 +568,13 @@ bool BlockSheduler::schedule_alu(Shader::ShaderBlocks& out_blocks) if (group->has_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; } diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp b/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp index 3519f489b8b..f9d8d7080c3 100644 --- a/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_shader_fs.cpp @@ -178,6 +178,7 @@ bool FragmentShader::process_stage_intrinsic(nir_intrinsic_instr *intr) value_factory().zero(), value_factory().zero(), {AluInstr::last})); + start_new_block(0); return true; case nir_intrinsic_load_sample_mask_in: if (m_apply_sample_mask) {