• 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_alu_defines.h"
30 #include "sfn_debug.h"
31 #include "sfn_instr_alugroup.h"
32 #include "sfn_instr_controlflow.h"
33 #include "sfn_instr_export.h"
34 #include "sfn_instr_fetch.h"
35 #include "sfn_instr_lds.h"
36 #include "sfn_instr_mem.h"
37 #include "sfn_instr_tex.h"
38 #include "sfn_shader.h"
39 
40 #include <sstream>
41 #include <string>
42 #include <vector>
43 
44 namespace r600 {
45 
46 using std::string;
47 using std::vector;
48 
InstrFactory()49 InstrFactory::InstrFactory():
50     group(nullptr)
51 {
52 }
53 
54 PInst
from_string(const std::string & s,int nesting_depth,bool is_cayman)55 InstrFactory::from_string(const std::string& s, int nesting_depth, bool is_cayman)
56 {
57    string type;
58    std::istringstream is(s);
59 
60    PInst result = nullptr;
61 
62    do {
63       is >> type;
64    } while (type.empty() && is.good());
65 
66    if (type == "ALU_GROUP_BEGIN") {
67       group = new AluGroup();
68       group->set_nesting_depth(nesting_depth);
69       return nullptr;
70    } else if (type == "ALU_GROUP_END") {
71       AluGroup *retval = group;
72       group = nullptr;
73       return retval;
74    } else if (type == "ALU") {
75       result = AluInstr::from_string(is, m_value_factory, group, is_cayman);
76    } else if (type == "TEX") {
77       result = TexInstr::from_string(is, m_value_factory);
78    } else if (type == "EXPORT") {
79       result = ExportInstr::from_string(is, m_value_factory);
80    } else if (type == "EXPORT_DONE") {
81       result = ExportInstr::last_from_string(is, m_value_factory);
82    } else if (type == "VFETCH") {
83       result = FetchInstr::from_string(is, m_value_factory);
84    } else if (type == "GET_BUF_RESINFO") {
85       result = QueryBufferSizeInstr::from_string(is, m_value_factory);
86    } else if (type == "LOAD_BUF") {
87       result = LoadFromBuffer::from_string(is, m_value_factory);
88    } else if (type == "READ_SCRATCH") {
89       result = LoadFromScratch::from_string(is, m_value_factory);
90    } else if (type == "IF") {
91       result = IfInstr::from_string(is, m_value_factory, is_cayman);
92    } else if (type == "WRITE_SCRATCH") {
93       result = ScratchIOInstr::from_string(is, m_value_factory);
94    } else if (type == "MEM_RING") {
95       result = MemRingOutInstr::from_string(is, m_value_factory);
96    } else if (type == "EMIT_VERTEX") {
97       result = EmitVertexInstr::from_string(is, false);
98    } else if (type == "EMIT_CUT_VERTEX") {
99       result = EmitVertexInstr::from_string(is, true);
100    } else if (type == "LDS_READ") {
101       result = LDSReadInstr::from_string(is, m_value_factory);
102    } else if (type == "LDS") {
103       result = LDSAtomicInstr::from_string(is, m_value_factory);
104    } else if (type == "WRITE_TF") {
105       result = WriteTFInstr::from_string(is, m_value_factory);
106    } else
107       result = ControlFlowInstr::from_string(type);
108 
109    if (!result && !group) {
110       std::cerr << "Error translating '" << s << "'\n";
111    }
112 
113    return result;
114 }
115 
116 bool
from_nir(nir_instr * instr,Shader & shader)117 InstrFactory::from_nir(nir_instr *instr, Shader& shader)
118 {
119    switch (instr->type) {
120    case nir_instr_type_alu:
121       return AluInstr::from_nir(nir_instr_as_alu(instr), shader);
122    case nir_instr_type_intrinsic:
123       return shader.process_intrinsic(nir_instr_as_intrinsic(instr));
124    case nir_instr_type_load_const:
125       return load_const(nir_instr_as_load_const(instr), shader);
126    case nir_instr_type_tex:
127       return TexInstr::from_nir(nir_instr_as_tex(instr), shader);
128    case nir_instr_type_jump:
129       return process_jump(nir_instr_as_jump(instr), shader);
130    case nir_instr_type_undef:
131       return process_undef(nir_instr_as_undef(instr), shader);
132    default:
133       fprintf(stderr, "Instruction type %d not supported\n", instr->type);
134       return false;
135    }
136 }
137 
138 bool
load_const(nir_load_const_instr * literal,Shader & shader)139 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:
161             src = m_value_factory.zero();
162             break;
163          case 1:
164             src = m_value_factory.one_i();
165             break;
166          case 0xffffffff:
167             src = m_value_factory.inline_const(ALU_SRC_M_1_INT, 0);
168             break;
169          case 0x3f800000:
170             src = m_value_factory.inline_const(ALU_SRC_1, 0);
171             break;
172          case 0x3f000000:
173             src = m_value_factory.inline_const(ALU_SRC_0_5, 0);
174             break;
175          default:
176             src = m_value_factory.literal(v);
177          }
178 
179          ir = new AluInstr(op1_mov, dest, src, {alu_write});
180          shader.emit_instruction(ir);
181       }
182       if (ir)
183          ir->set_alu_flag(alu_last_instr);
184    }
185    return true;
186 }
187 
188 bool
process_jump(nir_jump_instr * instr,Shader & shader)189 InstrFactory::process_jump(nir_jump_instr *instr, Shader& shader)
190 {
191    ControlFlowInstr::CFType type;
192    switch (instr->type) {
193    case nir_jump_break:
194       type = ControlFlowInstr::cf_loop_break;
195       break;
196 
197    case nir_jump_continue:
198       type = ControlFlowInstr::cf_loop_continue;
199       break;
200 
201    default: {
202       nir_instr *i = reinterpret_cast<nir_instr *>(instr);
203       sfn_log << SfnLog::err << "Jump instrunction " << *i << " not supported\n";
204       return false;
205    }
206    }
207    shader.emit_instruction(new ControlFlowInstr(type));
208    shader.start_new_block(0);
209 
210    return true;
211 }
212 
213 bool
process_undef(nir_undef_instr * undef,Shader & shader)214 InstrFactory::process_undef(nir_undef_instr *undef, Shader& shader)
215 {
216    for (int i = 0; i < undef->def.num_components; ++i) {
217       auto dest = shader.value_factory().undef(undef->def.index, i);
218       shader.emit_instruction(
219          new AluInstr(op1_mov, dest, value_factory().zero(), AluInstr::last_write));
220    }
221    return true;
222 }
223 
224 } // namespace r600
225