1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2022 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@collabora.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "sfn_instrfactory.h"
28
29 #include "sfn_instr_alugroup.h"
30 #include "sfn_debug.h"
31 #include "sfn_instr_controlflow.h"
32 #include "sfn_instr_export.h"
33 #include "sfn_instr_fetch.h"
34 #include "sfn_instr_lds.h"
35 #include "sfn_instr_mem.h"
36 #include "sfn_instr_tex.h"
37
38 #include "sfn_alu_defines.h"
39
40 #include "sfn_shader.h"
41
42 #include <string>
43 #include <sstream>
44 #include <vector>
45
46 namespace r600 {
47
48 using std::string;
49 using std::vector;
50
InstrFactory()51 InstrFactory::InstrFactory():
52 group(nullptr)
53 {
54
55 }
56
from_string(const std::string & s,int nesting_depth)57 PInst InstrFactory::from_string(const std::string& s, int nesting_depth)
58 {
59 string type;
60 std::istringstream is(s);
61
62 PInst result = nullptr;
63
64 do {
65 is >> type;
66 } while (type.empty() && is.good());
67
68 if (type == "ALU_GROUP_BEGIN") {
69 group = new AluGroup();
70 group->set_nesting_depth(nesting_depth);
71 return nullptr;
72 } else if (type == "ALU_GROUP_END") {
73 AluGroup *retval = group;
74 group = nullptr;
75 return retval;
76 } else if (type == "ALU") {
77 result = AluInstr::from_string(is, m_value_factory, group);
78 } else if (type == "TEX") {
79 result = TexInstr::from_string(is, m_value_factory);
80 } else if (type == "EXPORT") {
81 result = ExportInstr::from_string(is, m_value_factory);
82 } else if (type == "EXPORT_DONE") {
83 result = ExportInstr::last_from_string(is, m_value_factory);
84 } else if (type == "VFETCH") {
85 result = FetchInstr::from_string(is, m_value_factory);
86 } else if (type == "GET_BUF_RESINFO") {
87 result = QueryBufferSizeInstr::from_string(is, m_value_factory);
88 } else if (type == "LOAD_BUF") {
89 result = LoadFromBuffer::from_string(is, m_value_factory);
90 } else if (type == "READ_SCRATCH") {
91 result = LoadFromScratch::from_string(is, m_value_factory);
92 } else if (type == "IF") {
93 result = IfInstr::from_string(is, m_value_factory);
94 } else if (type == "WRITE_SCRATCH") {
95 result = ScratchIOInstr::from_string(is, m_value_factory);
96 } else if (type == "MEM_RING") {
97 result = MemRingOutInstr::from_string(is, m_value_factory);
98 } else if (type == "EMIT_VERTEX") {
99 result = EmitVertexInstr::from_string(is, false);
100 } else if (type == "EMIT_CUT_VERTEX") {
101 result = EmitVertexInstr::from_string(is, true);
102 } else if (type == "LDS_READ") {
103 result = LDSReadInstr::from_string(is, m_value_factory);
104 } else if (type == "LDS") {
105 result = LDSAtomicInstr::from_string(is, m_value_factory);
106 } else if (type == "WRITE_TF") {
107 result = WriteTFInstr::from_string(is, m_value_factory);
108 } else
109 result = ControlFlowInstr::from_string(type);
110
111 if (!result && !group) {
112 std::cerr << "Error translating '" << s << "'\n";
113 }
114
115 return result;
116 }
117
from_nir(nir_instr * instr,Shader & shader)118 bool InstrFactory::from_nir(nir_instr *instr, Shader& shader)
119 {
120 switch (instr->type) {
121 case nir_instr_type_alu:
122 return AluInstr::from_nir(nir_instr_as_alu(instr), shader);
123 case nir_instr_type_intrinsic:
124 return shader.process_intrinsic(nir_instr_as_intrinsic(instr));
125 case nir_instr_type_load_const:
126 return load_const(nir_instr_as_load_const(instr), shader);
127 case nir_instr_type_tex:
128 return TexInstr::from_nir(nir_instr_as_tex(instr), shader);
129 case nir_instr_type_jump:
130 return process_jump(nir_instr_as_jump(instr), shader);
131 case nir_instr_type_ssa_undef:
132 return process_undef(nir_instr_as_ssa_undef(instr), shader);
133 default:
134 fprintf(stderr, "Instruction type %d not supported\n", instr->type);
135 return false;
136 }
137 }
138
load_const(nir_load_const_instr * literal,Shader & shader)139 bool InstrFactory::load_const(nir_load_const_instr *literal, Shader& shader)
140 {
141 AluInstr *ir = nullptr;
142
143 if (literal->def.bit_size == 64) {
144 for (int i = 0; i < literal->def.num_components; ++i) {
145 auto dest0 = m_value_factory.dest(literal->def, 2 * i, pin_none);
146 auto src0 = m_value_factory.literal(literal->value[i].u64 & 0xffffffff);
147 shader.emit_instruction(new AluInstr(op1_mov, dest0, src0, {alu_write}));
148
149 auto dest1 = m_value_factory.dest(literal->def, 2 * i + 1, pin_none);
150 auto src1 = m_value_factory.literal((literal->value[i].u64 >> 32) & 0xffffffff);
151 shader.emit_instruction(new AluInstr(op1_mov, dest1, src1, AluInstr::last_write));
152 }
153 } else {
154 Pin pin = literal->def.num_components == 1 ? pin_free : pin_none;
155 for (int i = 0; i < literal->def.num_components; ++i) {
156 auto dest = m_value_factory.dest(literal->def, i, pin);
157 uint32_t v = literal->value[i].i32;
158 PVirtualValue src = nullptr;
159 switch (v) {
160 case 0: src = m_value_factory.zero(); break;
161 case 1: src = m_value_factory.one_i(); break;
162 case 0xffffffff: src = m_value_factory.inline_const(ALU_SRC_M_1_INT, 0); break;
163 case 0x3f800000: src = m_value_factory.inline_const(ALU_SRC_1, 0); break;
164 case 0x3f000000: src = m_value_factory.inline_const(ALU_SRC_0_5, 0); break;
165 default: src = m_value_factory.literal(v);
166 }
167
168 ir = new AluInstr(op1_mov, dest, src, {alu_write});
169 shader.emit_instruction(ir);
170 }
171 if (ir)
172 ir->set_alu_flag(alu_last_instr);
173
174 }
175 return true;
176 }
177
process_jump(nir_jump_instr * instr,Shader & shader)178 bool InstrFactory::process_jump(nir_jump_instr *instr, Shader& shader)
179 {
180 ControlFlowInstr::CFType type;
181 switch (instr->type) {
182 case nir_jump_break:
183 type = ControlFlowInstr::cf_loop_break;
184 break;
185
186 case nir_jump_continue:
187 type = ControlFlowInstr::cf_loop_continue;
188 break;
189
190 default: {
191 nir_instr *i = reinterpret_cast<nir_instr*>(instr);
192 sfn_log << SfnLog::err << "Jump instrunction " << *i << " not supported\n";
193 return false;
194 }
195 }
196 shader.emit_instruction(new ControlFlowInstr(type));
197 shader.start_new_block(0);
198
199 return true;
200 }
201
process_undef(nir_ssa_undef_instr * undef,Shader & shader)202 bool InstrFactory::process_undef(nir_ssa_undef_instr *undef, Shader& shader)
203 {
204 for (int i = 0; i < undef->def.num_components; ++i) {
205 auto dest = shader.value_factory().undef(undef->def.index, i);
206 shader.emit_instruction(new AluInstr(op1_mov, dest,
207 value_factory().zero(),
208 AluInstr::last_write));
209 }
210 return true;
211 }
212
213
214 }
215