• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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