r600/sfn: Add MemRingOut instructions
authorGert Wollny <gert.wollny@collabora.com>
Fri, 27 Dec 2019 16:49:27 +0000 (17:49 +0100)
committerMarge Bot <eric+marge@anholt.net>
Mon, 10 Feb 2020 19:09:08 +0000 (19:09 +0000)
Preparing support for Geometry shaders.

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3225>

src/gallium/drivers/r600/sfn/sfn_instruction_export.cpp
src/gallium/drivers/r600/sfn/sfn_instruction_export.h
src/gallium/drivers/r600/sfn/sfn_ir_to_assembly.cpp

index fffcb09537cd4a8de479906dadac7b25b203f9e0..b109846489f43e9dfc7334d8a73dbcb9848cece8 100644 (file)
@@ -244,4 +244,89 @@ void StreamOutIntruction::do_print(std::ostream& os) const
       os << "+" << m_array_size;
 }
 
+MemRingOutIntruction::MemRingOutIntruction(ECFOpCode ring, EMemWriteType type,
+                                           const GPRVector& value,
+                                           unsigned base_addr, unsigned ncomp,
+                                           PValue index):
+   WriteoutInstruction(Instruction::ring, value),
+   m_ring_op(ring),
+   m_type(type),
+   m_base_address(base_addr),
+   m_num_comp(ncomp),
+   m_index(index)
+{
+   add_remappable_src_value(&m_index);
+
+   assert(m_ring_op  == cf_mem_ring || m_ring_op  == cf_mem_ring1||
+          m_ring_op  == cf_mem_ring2 || m_ring_op  == cf_mem_ring3);
+   assert(m_num_comp <= 4);
+}
+
+unsigned MemRingOutIntruction::ncomp() const
+{
+   switch (m_num_comp) {
+   case 1: return 0;
+   case 2: return 1;
+   case 3:
+   case 4: return 3;
+   default:
+      assert(0);
+   }
+   return 3;
+}
+
+bool MemRingOutIntruction::is_equal_to(const Instruction& lhs) const
+{
+   assert(lhs.type() == streamout);
+   const auto& oth = static_cast<const MemRingOutIntruction&>(lhs);
+
+   bool equal = gpr() == oth.gpr() &&
+                m_ring_op == oth.m_ring_op &&
+                m_type == oth.m_type &&
+                m_num_comp == oth.m_num_comp &&
+                m_base_address == oth.m_base_address;
+
+   if (m_type == mem_write_ind || m_type == mem_write_ind_ack)
+      equal &= (*m_index == *oth.m_index);
+   return equal;
+
+}
+
+static const char *write_type_str[4] = {"WRITE", "WRITE_IDX", "WRITE_ACK", "WRITE_IDX_ACK" };
+void MemRingOutIntruction::do_print(std::ostream& os) const
+{
+   os << "MEM_RING" << m_ring_op;
+   os << " " << write_type_str[m_type] << " " << m_base_address;
+   os << " " << gpr();
+   if (m_type == mem_write_ind || m_type == mem_write_ind_ack)
+      os << " @" << *m_index;
+   os << " ES:" << m_num_comp;
+}
+
+
+void MemRingOutIntruction::replace_values_child(const ValueSet& candiates,
+                                                PValue new_value)
+{
+   if (!m_index)
+      return;
+
+   for (auto c: candiates) {
+      if (*c == *m_index)
+         m_index = new_value;
+   }
+}
+
+void MemRingOutIntruction::remap_registers_child(std::vector<rename_reg_pair>& map,
+                                                 ValueMap& values)
+{
+   if (!m_index)
+      return;
+
+   assert(m_index->type() == Value::gpr);
+   auto new_index = map[m_index->sel()];
+   if (new_index.valid)
+      m_index = values.get_or_inject(new_index.new_reg, m_index->chan());
+   map[m_index->sel()].used = true;
+}
+
 }
index f32800381c438e63e083b7220fe023bd3d740581..8ab827e71b2cf35955fa5c4037f106d63616aaf3 100644 (file)
@@ -136,7 +136,35 @@ enum EMemWriteType {
    mem_write_ind_ack = 3,
 };
 
+class MemRingOutIntruction: public WriteoutInstruction {
+public:
+
+   MemRingOutIntruction(ECFOpCode ring, EMemWriteType type,
+                        const GPRVector& value, unsigned base_addr,
+                        unsigned ncomp, PValue m_index);
+
+   unsigned op() const{return m_ring_op;}
+   unsigned ncomp() const;
+   unsigned addr() const {return m_base_address;}
+   EMemWriteType type() const {return m_type;}
+   unsigned index_reg() const {return m_index->sel();}
+   unsigned array_base() const {return m_base_address; }
+   void replace_values_child(const ValueSet& candiates, PValue new_value) override;
+   void remap_registers_child(std::vector<rename_reg_pair>& map,
+                        ValueMap& values) override;
+private:
+   bool is_equal_to(const Instruction& lhs) const override;
+   void do_print(std::ostream& os) const override;
+
+   ECFOpCode m_ring_op;
+   EMemWriteType m_type;
+   unsigned m_base_address;
+   unsigned m_num_comp;
+   PValue m_index;
+
+};
+
 }
 
 
-#endif // SFN_EXPORTINSTRUCTION_H
+#endif // SFN_EXPORTINSTRUCTION_H
\ No newline at end of file
index e9624c58b2ba843caac5e06c46ef571da81bbac4..c6beddd79c785d995ec0fc5f0e5a019c08924dbd 100644 (file)
@@ -47,6 +47,7 @@ private:
    bool emit_alu(const AluInstruction& ai, ECFAluOpCode cf_op);
    bool emit_export(const ExportInstruction & exi);
    bool emit_streamout(const StreamOutIntruction& instr);
+   bool emit_memringwrite(const MemRingOutIntruction& instr);
    bool emit_tex(const TexInstruction & tex_instr);
    bool emit_vtx(const FetchInstruction& fetch_instr);
    bool emit_if_start(const IfInstruction & if_instr);
@@ -164,6 +165,8 @@ bool AssemblyFromShaderLegacyImpl::emit(const Instruction::Pointer i)
       return emit_loop_continue(static_cast<const LoopContInstruction&>(*i));
    case Instruction::streamout:
       return emit_streamout(static_cast<const StreamOutIntruction&>(*i));
+   case Instruction::ring:
+      return emit_memringwrite(static_cast<const MemRingOutIntruction&>(*i));
    case Instruction::wait_ack:
       return emit_wait_ack(static_cast<const WaitAck&>(*i));
    case Instruction::mem_wr_scratch:
@@ -577,6 +580,32 @@ bool AssemblyFromShaderLegacyImpl::emit_streamout(const StreamOutIntruction& so_
    return true;
 }
 
+
+bool AssemblyFromShaderLegacyImpl::emit_memringwrite(const MemRingOutIntruction& instr)
+{
+   struct r600_bytecode_output output;
+   memset(&output, 0, sizeof(struct r600_bytecode_output));
+
+   output.gpr = instr.gpr().sel();
+   output.type = instr.type();
+   output.elem_size = instr.ncomp();
+   output.comp_mask = 0xF;
+   output.burst_count = 1;
+   output.op = instr.op();
+   if (instr.type() == mem_write_ind || instr.type() == mem_write_ind_ack) {
+      output.index_gpr = instr.index_reg();
+      output.array_size = 0xfff;
+   }
+   output.array_base = instr.array_base();
+
+   if (r600_bytecode_add_output(m_bc, &output)) {
+      R600_ERR("shader_from_nir: Error creating mem ring write instruction\n");
+      return false;
+   }
+   return true;
+}
+
+
 bool AssemblyFromShaderLegacyImpl::emit_tex(const TexInstruction & tex_instr)
 {
    auto addr = tex_instr.sampler_offset();