xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_instrfactory.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* -*- mesa-c++  -*-
2  * Copyright 2022 Collabora LTD
3  * Author: Gert Wollny <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "sfn_instrfactory.h"
8 
9 #include "sfn_alu_defines.h"
10 #include "sfn_debug.h"
11 #include "sfn_instr_alugroup.h"
12 #include "sfn_instr_controlflow.h"
13 #include "sfn_instr_export.h"
14 #include "sfn_instr_fetch.h"
15 #include "sfn_instr_lds.h"
16 #include "sfn_instr_mem.h"
17 #include "sfn_instr_tex.h"
18 #include "sfn_shader.h"
19 
20 #include <sstream>
21 #include <string>
22 #include <vector>
23 
24 namespace r600 {
25 
26 using std::string;
27 using std::vector;
28 
InstrFactory()29 InstrFactory::InstrFactory():
30     group(nullptr)
31 {
32 }
33 
34 PInst
from_string(const std::string & s,int nesting_depth,bool is_cayman)35 InstrFactory::from_string(const std::string& s, int nesting_depth, bool is_cayman)
36 {
37    string type;
38    std::istringstream is(s);
39 
40    PInst result = nullptr;
41 
42    do {
43       is >> type;
44    } while (type.empty() && is.good());
45 
46    if (type == "ALU_GROUP_BEGIN") {
47       group = new AluGroup();
48       group->set_nesting_depth(nesting_depth);
49       return nullptr;
50    } else if (type == "ALU_GROUP_END") {
51       AluGroup *retval = group;
52       group = nullptr;
53       return retval;
54    } else if (type == "ALU") {
55       result = AluInstr::from_string(is, m_value_factory, group, is_cayman);
56    } else if (type == "TEX") {
57       result = TexInstr::from_string(is, m_value_factory);
58    } else if (type == "EXPORT") {
59       result = ExportInstr::from_string(is, m_value_factory);
60    } else if (type == "EXPORT_DONE") {
61       result = ExportInstr::last_from_string(is, m_value_factory);
62    } else if (type == "VFETCH") {
63       result = FetchInstr::from_string(is, m_value_factory);
64    } else if (type == "GET_BUF_RESINFO") {
65       result = QueryBufferSizeInstr::from_string(is, m_value_factory);
66    } else if (type == "LOAD_BUF") {
67       result = LoadFromBuffer::from_string(is, m_value_factory);
68    } else if (type == "READ_SCRATCH") {
69       result = LoadFromScratch::from_string(is, m_value_factory);
70    } else if (type == "IF") {
71       result = IfInstr::from_string(is, m_value_factory, is_cayman);
72    } else if (type == "WRITE_SCRATCH") {
73       result = ScratchIOInstr::from_string(is, m_value_factory);
74    } else if (type == "MEM_RING") {
75       result = MemRingOutInstr::from_string(is, m_value_factory);
76    } else if (type == "EMIT_VERTEX") {
77       result = EmitVertexInstr::from_string(is, false);
78    } else if (type == "EMIT_CUT_VERTEX") {
79       result = EmitVertexInstr::from_string(is, true);
80    } else if (type == "LDS_READ") {
81       result = LDSReadInstr::from_string(is, m_value_factory);
82    } else if (type == "LDS") {
83       result = LDSAtomicInstr::from_string(is, m_value_factory);
84    } else if (type == "WRITE_TF") {
85       result = WriteTFInstr::from_string(is, m_value_factory);
86    } else
87       result = ControlFlowInstr::from_string(type);
88 
89    if (!result && !group) {
90       std::cerr << "Error translating '" << s << "'\n";
91    }
92 
93    return result;
94 }
95 
96 bool
from_nir(nir_instr * instr,Shader & shader)97 InstrFactory::from_nir(nir_instr *instr, Shader& shader)
98 {
99    switch (instr->type) {
100    case nir_instr_type_alu:
101       return AluInstr::from_nir(nir_instr_as_alu(instr), shader);
102    case nir_instr_type_intrinsic:
103       return shader.process_intrinsic(nir_instr_as_intrinsic(instr));
104    case nir_instr_type_load_const:
105       return load_const(nir_instr_as_load_const(instr), shader);
106    case nir_instr_type_tex:
107       return TexInstr::from_nir(nir_instr_as_tex(instr), shader);
108    case nir_instr_type_jump:
109       return process_jump(nir_instr_as_jump(instr), shader);
110    case nir_instr_type_undef:
111       return process_undef(nir_instr_as_undef(instr), shader);
112    default:
113       fprintf(stderr, "Instruction type %d not supported\n", instr->type);
114       return false;
115    }
116 }
117 
118 bool
load_const(nir_load_const_instr * literal,Shader & shader)119 InstrFactory::load_const(nir_load_const_instr *literal, Shader& shader)
120 {
121    AluInstr *ir = nullptr;
122 
123    if (literal->def.bit_size == 64) {
124       for (int i = 0; i < literal->def.num_components; ++i) {
125          auto dest0 = m_value_factory.dest(literal->def, 2 * i, pin_none);
126          auto src0 = m_value_factory.literal(literal->value[i].u64 & 0xffffffff);
127          shader.emit_instruction(new AluInstr(op1_mov, dest0, src0, {alu_write}));
128 
129          auto dest1 = m_value_factory.dest(literal->def, 2 * i + 1, pin_none);
130          auto src1 = m_value_factory.literal((literal->value[i].u64 >> 32) & 0xffffffff);
131          shader.emit_instruction(new AluInstr(op1_mov, dest1, src1, AluInstr::last_write));
132       }
133    } else {
134       Pin pin = literal->def.num_components == 1 ? pin_free : pin_none;
135       for (int i = 0; i < literal->def.num_components; ++i) {
136          auto dest = m_value_factory.dest(literal->def, i, pin);
137          uint32_t v = literal->value[i].i32;
138          PVirtualValue src = nullptr;
139          switch (v) {
140          case 0:
141             src = m_value_factory.zero();
142             break;
143          case 1:
144             src = m_value_factory.one_i();
145             break;
146          case 0xffffffff:
147             src = m_value_factory.inline_const(ALU_SRC_M_1_INT, 0);
148             break;
149          case 0x3f800000:
150             src = m_value_factory.inline_const(ALU_SRC_1, 0);
151             break;
152          case 0x3f000000:
153             src = m_value_factory.inline_const(ALU_SRC_0_5, 0);
154             break;
155          default:
156             src = m_value_factory.literal(v);
157          }
158 
159          ir = new AluInstr(op1_mov, dest, src, {alu_write});
160          shader.emit_instruction(ir);
161       }
162       if (ir)
163          ir->set_alu_flag(alu_last_instr);
164    }
165    return true;
166 }
167 
168 bool
process_jump(nir_jump_instr * instr,Shader & shader)169 InstrFactory::process_jump(nir_jump_instr *instr, Shader& shader)
170 {
171    ControlFlowInstr::CFType type;
172    switch (instr->type) {
173    case nir_jump_break:
174       type = ControlFlowInstr::cf_loop_break;
175       break;
176 
177    case nir_jump_continue:
178       type = ControlFlowInstr::cf_loop_continue;
179       break;
180 
181    default: {
182       nir_instr *i = reinterpret_cast<nir_instr *>(instr);
183       sfn_log << SfnLog::err << "Jump instrunction " << *i << " not supported\n";
184       return false;
185    }
186    }
187    shader.emit_instruction(new ControlFlowInstr(type));
188    shader.start_new_block(0);
189 
190    return true;
191 }
192 
193 bool
process_undef(nir_undef_instr * undef,Shader & shader)194 InstrFactory::process_undef(nir_undef_instr *undef, Shader& shader)
195 {
196    for (int i = 0; i < undef->def.num_components; ++i) {
197       auto dest = shader.value_factory().undef(undef->def.index, i);
198       shader.emit_instruction(
199          new AluInstr(op1_mov, dest, value_factory().zero(), AluInstr::last_write));
200    }
201    return true;
202 }
203 
204 } // namespace r600
205