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