r600/sfn: Add a basic nir shader backend
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_shader_base.cpp
1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2018 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 "../r600_pipe.h"
28 #include "../r600_shader.h"
29 #include "sfn_shader_vertex.h"
30
31 #include "sfn_shader_fragment.h"
32 #include "sfn_ir_to_assembly.h"
33 #include "sfn_nir.h"
34 #include "sfn_instruction_fetch.h"
35
36 #include <iostream>
37
38 #define ENABLE_DEBUG 1
39
40 #ifdef ENABLE_DEBUG
41 #define DEBUG_SFN(X) \
42 do {\
43 X; \
44 } while (0)
45 #else
46 #define DEBUG_SFN(X)
47 #endif
48
49 namespace r600 {
50
51 using namespace std;
52
53
54 ShaderFromNirProcessor::ShaderFromNirProcessor(pipe_shader_type ptype,
55 r600_pipe_shader_selector& sel,
56 r600_shader &sh_info):
57 m_processor_type(ptype),
58 m_sh_info(sh_info),
59 m_tex_instr(*this),
60 m_alu_instr(*this),
61 m_pending_else(nullptr),
62 m_next_hwatomic_loc(0),
63 m_sel(sel)
64 {
65 m_sh_info.processor_type = ptype;
66 }
67
68
69 ShaderFromNirProcessor::~ShaderFromNirProcessor()
70 {
71 }
72
73 bool ShaderFromNirProcessor::scan_instruction(nir_instr *instr)
74 {
75 switch (instr->type) {
76 case nir_instr_type_tex: {
77 nir_tex_instr *t = nir_instr_as_tex(instr);
78 if (t->sampler_dim == GLSL_SAMPLER_DIM_BUF)
79 sh_info().uses_tex_buffers = true;
80 }
81 default:
82 ;
83 }
84
85 return scan_sysvalue_access(instr);
86 }
87
88 bool ShaderFromNirProcessor::process_uniforms(nir_variable *uniform)
89 {
90 // m_uniform_type_map
91 m_uniform_type_map[uniform->data.location] = uniform->type;
92
93 if (uniform->type->contains_atomic()) {
94 int natomics = uniform->type->atomic_size() / ATOMIC_COUNTER_SIZE;
95 sh_info().nhwatomic += natomics;
96
97 if (uniform->type->is_array())
98 sh_info().indirect_files |= 1 << TGSI_FILE_HW_ATOMIC;
99
100 sh_info().uses_atomics = 1;
101
102 struct r600_shader_atomic& atom = sh_info().atomics[sh_info().nhwatomic_ranges];
103 ++sh_info().nhwatomic_ranges;
104 atom.buffer_id = uniform->data.binding;
105 atom.hw_idx = m_next_hwatomic_loc;
106 atom.start = m_next_hwatomic_loc;
107 atom.end = atom.start + natomics - 1;
108 m_next_hwatomic_loc = atom.end + 1;
109 //atom.array_id = uniform->type->is_array() ? 1 : 0;
110
111 m_sel.info.file_count[TGSI_FILE_HW_ATOMIC] += atom.end - atom.start + 1;
112
113 sfn_log << SfnLog::io << "HW_ATOMIC file count: "
114 << m_sel.info.file_count[TGSI_FILE_HW_ATOMIC] << "\n";
115 }
116
117 if (uniform->type->is_image() || uniform->data.mode == nir_var_mem_ssbo) {
118 sh_info().uses_images = 1;
119 }
120
121 return true;
122 }
123
124 bool ShaderFromNirProcessor::process_inputs(nir_variable *input)
125 {
126 return do_process_inputs(input);
127 }
128
129 bool ShaderFromNirProcessor::process_outputs(nir_variable *output)
130 {
131 return do_process_outputs(output);
132 }
133
134 void ShaderFromNirProcessor::add_array_deref(nir_deref_instr *instr)
135 {
136 nir_variable *var = nir_deref_instr_get_variable(instr);
137
138 assert(instr->mode == nir_var_function_temp);
139 assert(glsl_type_is_array(var->type));
140
141 // add an alias for the index to the register(s);
142
143
144 }
145
146 void ShaderFromNirProcessor::set_var_address(nir_deref_instr *instr)
147 {
148 auto& dest = instr->dest;
149 unsigned index = dest.is_ssa ? dest.ssa.index : dest.reg.reg->index;
150 m_var_mode[instr->var] = instr->mode;
151 m_var_derefs[index] = instr->var;
152
153 sfn_log << SfnLog::io << "Add var deref:" << index
154 << " with DDL:" << instr->var->data.driver_location << "\n";
155 }
156
157 void ShaderFromNirProcessor::evaluate_spi_sid(r600_shader_io& io)
158 {
159 switch (io.name) {
160 case TGSI_SEMANTIC_POSITION:
161 case TGSI_SEMANTIC_PSIZE:
162 case TGSI_SEMANTIC_EDGEFLAG:
163 case TGSI_SEMANTIC_FACE:
164 case TGSI_SEMANTIC_SAMPLEMASK:
165 case TGSI_SEMANTIC_CLIPVERTEX:
166 io.spi_sid = 0;
167 break;
168 case TGSI_SEMANTIC_GENERIC:
169 io.spi_sid = io.sid + 1;
170 break;
171 default:
172 /* For non-generic params - pack name and sid into 8 bits */
173 io.spi_sid = (0x80 | (io.name << 3) | io.sid) + 1;
174 }
175 }
176
177 const nir_variable *ShaderFromNirProcessor::get_deref_location(const nir_src& src) const
178 {
179 unsigned index = src.is_ssa ? src.ssa->index : src.reg.reg->index;
180
181 sfn_log << SfnLog::io << "Search for deref:" << index << "\n";
182
183 auto v = m_var_derefs.find(index);
184 if (v != m_var_derefs.end())
185 return v->second;
186
187 fprintf(stderr, "R600: could not find deref with index %d\n", index);
188
189 return nullptr;
190
191 /*nir_deref_instr *deref = nir_instr_as_deref(src.ssa->parent_instr);
192 return nir_deref_instr_get_variable(deref); */
193 }
194
195 bool ShaderFromNirProcessor::emit_tex_instruction(nir_instr* instr)
196 {
197 return m_tex_instr.emit(instr);
198 }
199
200 void ShaderFromNirProcessor::emit_instruction(Instruction *ir)
201 {
202 if (m_pending_else) {
203 m_output.push_back(PInstruction(m_pending_else));
204 m_pending_else = nullptr;
205 }
206
207 r600::sfn_log << SfnLog::instr << " as '" << *ir << "'\n";
208 m_output.push_back(Instruction::Pointer(ir));
209 }
210
211 void ShaderFromNirProcessor::emit_shader_start()
212 {
213 /* placeholder, may become an abstract method */
214 }
215
216 bool ShaderFromNirProcessor::emit_jump_instruction(nir_jump_instr *instr)
217 {
218 switch (instr->type) {
219 case nir_jump_break: {
220 auto b = new LoopBreakInstruction();
221 emit_instruction(b);
222 return true;
223 }
224 case nir_jump_continue: {
225 auto b = new LoopContInstruction();
226 emit_instruction(b);
227 return true;
228 }
229 default: {
230 nir_instr *i = reinterpret_cast<nir_instr*>(instr);
231 sfn_log << SfnLog::err << "Jump instrunction " << *i << " not supported\n";
232 return false;
233 }
234 }
235 return true;
236 }
237
238 bool ShaderFromNirProcessor::emit_alu_instruction(nir_instr* instr)
239 {
240 return m_alu_instr.emit(instr);
241 }
242
243 bool ShaderFromNirProcessor::emit_deref_instruction_override(UNUSED nir_deref_instr* instr)
244 {
245 return false;
246 }
247
248 bool ShaderFromNirProcessor::emit_loop_start(int loop_id)
249 {
250 LoopBeginInstruction *loop = new LoopBeginInstruction();
251 emit_instruction(loop);
252 m_loop_begin_block_map[loop_id] = loop;
253 return true;
254 }
255 bool ShaderFromNirProcessor::emit_loop_end(int loop_id)
256 {
257 auto start = m_loop_begin_block_map.find(loop_id);
258 if (start == m_loop_begin_block_map.end()) {
259 sfn_log << SfnLog::err << "End loop: Loop start for "
260 << loop_id << " not found\n";
261 return false;
262 }
263 LoopEndInstruction *loop = new LoopEndInstruction(start->second);
264 emit_instruction(loop);
265
266 m_loop_begin_block_map.erase(start);
267 return true;
268 }
269
270 bool ShaderFromNirProcessor::emit_if_start(int if_id, nir_if *if_stmt)
271 {
272
273 auto value = from_nir(if_stmt->condition, 0, 0);
274 AluInstruction *pred = new AluInstruction(op2_pred_setne_int, PValue(new GPRValue(0,0)),
275 value, Value::zero, EmitInstruction::last);
276 pred->set_flag(alu_update_exec);
277 pred->set_flag(alu_update_pred);
278 pred->set_cf_type(cf_alu_push_before);
279
280 IfInstruction *ir = new IfInstruction(pred);
281 emit_instruction(ir);
282 assert(m_if_block_start_map.find(if_id) == m_if_block_start_map.end());
283 m_if_block_start_map[if_id] = ir;
284 return true;
285 }
286
287 bool ShaderFromNirProcessor::emit_else_start(int if_id)
288 {
289 auto iif = m_if_block_start_map.find(if_id);
290 if (iif == m_if_block_start_map.end()) {
291 std::cerr << "Error: ELSE branch " << if_id << " without starting conditional branch\n";
292 return false;
293 }
294
295 if (iif->second->type() != Instruction::cond_if) {
296 std::cerr << "Error: ELSE branch " << if_id << " not started by an IF branch\n";
297 return false;
298 }
299 IfInstruction *if_instr = static_cast<IfInstruction *>(iif->second);
300 ElseInstruction *ir = new ElseInstruction(if_instr);
301 m_if_block_start_map[if_id] = ir;
302 m_pending_else = ir;
303
304 return true;
305 }
306
307 bool ShaderFromNirProcessor::emit_ifelse_end(int if_id)
308 {
309 auto ifelse = m_if_block_start_map.find(if_id);
310 if (ifelse == m_if_block_start_map.end()) {
311 std::cerr << "Error: ENDIF " << if_id << " without THEN or ELSE branch\n";
312 return false;
313 }
314
315 if (ifelse->second->type() != Instruction::cond_if &&
316 ifelse->second->type() != Instruction::cond_else) {
317 std::cerr << "Error: ENDIF " << if_id << " doesn't close an IF or ELSE branch\n";
318 return false;
319 }
320 /* Clear pending else, if the else branch was empty, non will be emitted */
321
322 m_pending_else = nullptr;
323
324 IfElseEndInstruction *ir = new IfElseEndInstruction();
325 emit_instruction(ir);
326
327 return true;
328 }
329
330 bool ShaderFromNirProcessor::emit_intrinsic_instruction(nir_intrinsic_instr* instr)
331 {
332 r600::sfn_log << SfnLog::instr << "emit '"
333 << *reinterpret_cast<nir_instr*>(instr)
334 << "' (" << __func__ << ")\n";
335
336 if (emit_intrinsic_instruction_override(instr))
337 return true;
338
339 switch (instr->intrinsic) {
340 case nir_intrinsic_load_deref: {
341 auto var = get_deref_location(instr->src[0]);
342 if (!var)
343 return false;
344 auto mode_helper = m_var_mode.find(var);
345 if (mode_helper == m_var_mode.end()) {
346 cerr << "r600-nir: variable '" << var->name << "' not found\n";
347 return false;
348 }
349 switch (mode_helper->second) {
350 case nir_var_shader_in:
351 return emit_load_input_deref(var, instr);
352 case nir_var_function_temp:
353 return emit_load_function_temp(var, instr);
354 default:
355 cerr << "r600-nir: Unsupported mode" << mode_helper->second
356 << "for src variable\n";
357 return false;
358 }
359 }
360 case nir_intrinsic_store_deref:
361 return emit_store_deref(instr);
362 case nir_intrinsic_load_uniform:
363 return reserve_uniform(instr);
364 case nir_intrinsic_discard:
365 case nir_intrinsic_discard_if:
366 return emit_discard_if(instr);
367 case nir_intrinsic_load_ubo:
368 return emit_load_ubo(instr);
369 case nir_intrinsic_copy_deref:
370 case nir_intrinsic_load_constant:
371 case nir_intrinsic_load_input:
372 case nir_intrinsic_store_output:
373 default:
374 fprintf(stderr, "r600-nir: Unsupported intrinsic %d\n", instr->intrinsic);
375 return false;
376 }
377 return false;
378 }
379
380 bool ShaderFromNirProcessor::emit_intrinsic_instruction_override(UNUSED nir_intrinsic_instr* instr)
381 {
382 return false;
383 }
384
385 bool
386 ShaderFromNirProcessor::emit_load_function_temp(UNUSED const nir_variable *var, UNUSED nir_intrinsic_instr *instr)
387 {
388 return false;
389 }
390
391 bool ShaderFromNirProcessor::load_preloaded_value(const nir_dest& dest, int chan, PValue value, bool as_last)
392 {
393 if (!dest.is_ssa) {
394 auto ir = new AluInstruction(op1_mov, from_nir(dest, 0), value, {alu_write});
395 if (as_last)
396 ir->set_flag(alu_last_instr);
397 emit_instruction(ir);
398 } else {
399 inject_register(dest.ssa.index, chan, value, true);
400 }
401 return true;
402 }
403
404 GPRVector *ShaderFromNirProcessor::vec_from_nir_with_fetch_constant(const nir_src& src,
405 UNUSED unsigned mask,
406 const GPRVector::Swizzle& swizzle)
407 {
408 GPRVector *result = nullptr;
409 int sel = lookup_register_index(src);
410 if (sel >= 0 && from_nir(src, 0)->type() == Value::gpr &&
411 from_nir(src, 0)->chan() == 0) {
412 /* If the x-channel is really an x-channel register then we are pretty
413 * save that the value come like we need them */
414 result = new GPRVector(from_nir(src, 0)->sel(), swizzle);
415 } else {
416 AluInstruction *ir = nullptr;
417 int sel = allocate_temp_register();
418 GPRVector::Values v;
419 for (int i = 0; i < 4; ++i) {
420 v[i] = PValue(new GPRValue(sel, swizzle[i]));
421 if (swizzle[i] < 4 && (mask & (1 << i))) {
422 ir = new AluInstruction(op1_mov, v[i], from_nir(src, swizzle[i]),
423 EmitInstruction::write);
424 emit_instruction(ir);
425 }
426 }
427 if (ir)
428 ir->set_flag(alu_last_instr);
429
430 result = new GPRVector(v);
431 }
432 return result;
433 }
434
435 bool ShaderFromNirProcessor::emit_load_ubo(nir_intrinsic_instr* instr)
436 {
437 nir_src& src0 = instr->src[0];
438 nir_src& src1 = instr->src[1];
439
440 int sel_bufid_reg = src0.is_ssa ? src0.ssa->index : src0.reg.reg->index;
441 const nir_load_const_instr* literal0 = get_literal_constant(sel_bufid_reg);
442
443 int ofs_reg = src1.is_ssa ? src1.ssa->index : src1.reg.reg->index;
444 const nir_load_const_instr* literal1 = get_literal_constant(ofs_reg);
445 if (literal0) {
446 if (literal1) {
447 uint bufid = literal0->value[0].u32;
448 uint buf_ofs = literal1->value[0].u32 >> 4;
449 int buf_cmp = ((literal1->value[0].u32 >> 2) & 3);
450 AluInstruction *ir = nullptr;
451 for (int i = 0; i < instr->num_components; ++i) {
452 int cmp = buf_cmp + i;
453 assert(cmp < 4);
454 auto u = PValue(new UniformValue(512 + buf_ofs, cmp, bufid + 1));
455 if (instr->dest.is_ssa)
456 add_uniform((instr->dest.ssa.index << 2) + i, u);
457 else {
458 ir = new AluInstruction(op1_mov, from_nir(instr->dest, i), u, {alu_write});
459 emit_instruction(ir);
460 }
461 }
462 if (ir)
463 ir->set_flag(alu_last_instr);
464 return true;
465
466 } else {
467 /* literal0 is lost ...*/
468 return load_uniform_indirect(instr, from_nir(instr->src[1], 0, 0), 0, literal0->value[0].u32 + 1);
469 }
470 } else {
471 /* TODO: This can also be solved by using the CF indes on the ALU block, and
472 * this would probably make sense when there are more then one loads with
473 * the same buffer ID. */
474 PValue bufid = from_nir(instr->src[0], 0, 0);
475 PValue addr = from_nir_with_fetch_constant(instr->src[1], 0);
476 GPRVector trgt;
477 for (int i = 0; i < 4; ++i)
478 trgt.set_reg_i(i, from_nir(instr->dest, i));
479
480 auto ir = new FetchInstruction(vc_fetch, no_index_offset, trgt, addr, 0,
481 1, bufid, bim_zero);
482
483 emit_instruction(ir);
484 for (int i = 0; i < instr->num_components ; ++i) {
485 add_uniform((instr->dest.ssa.index << 2) + i, trgt.reg_i(i));
486 }
487 m_sh_info.indirect_files |= 1 << TGSI_FILE_CONSTANT;
488 return true;
489 }
490
491 }
492
493 bool ShaderFromNirProcessor::emit_discard_if(nir_intrinsic_instr* instr)
494 {
495 r600::sfn_log << SfnLog::instr << "emit '"
496 << *reinterpret_cast<nir_instr*>(instr)
497 << "' (" << __func__ << ")\n";
498
499 if (instr->intrinsic == nir_intrinsic_discard_if) {
500 emit_instruction(new AluInstruction(op2_killne_int, PValue(new GPRValue(0,0)),
501 {from_nir(instr->src[0], 0, 0), Value::zero}, {alu_last_instr}));
502
503 } else {
504 emit_instruction(new AluInstruction(op2_kille, PValue(new GPRValue(0,0)),
505 {Value::zero, Value::zero}, {alu_last_instr}));
506 }
507 m_sh_info.uses_kill = 1;
508 return true;
509 }
510
511 bool ShaderFromNirProcessor::emit_load_input_deref(const nir_variable *var,
512 nir_intrinsic_instr* instr)
513 {
514 return do_emit_load_deref(var, instr);
515 }
516
517 bool ShaderFromNirProcessor::reserve_uniform(nir_intrinsic_instr* instr)
518 {
519 r600::sfn_log << SfnLog::instr << __func__ << ": emit '"
520 << *reinterpret_cast<nir_instr*>(instr)
521 << "'\n";
522
523
524 /* If the target register is a SSA register and the loading is not
525 * indirect then we can do lazy loading, i.e. the uniform value can
526 * be used directly. Otherwise we have to load the data for real
527 * rigt away.
528 */
529
530 /* Try to find the literal that defines the array index */
531 const nir_load_const_instr* literal = nullptr;
532 if (instr->src[0].is_ssa)
533 literal = get_literal_constant(instr->src[0].ssa->index);
534
535 int base = nir_intrinsic_base(instr);
536 if (literal) {
537 AluInstruction *ir = nullptr;
538
539 for (int i = 0; i < instr->num_components ; ++i) {
540 PValue u = PValue(new UniformValue(512 + literal->value[0].u32 + base, i));
541 sfn_log << SfnLog::io << "uniform "
542 << instr->dest.ssa.index << " const["<< i << "]: "<< instr->const_index[i] << "\n";
543
544 if (instr->dest.is_ssa)
545 add_uniform((instr->dest.ssa.index << 2) + i, u);
546 else {
547 ir = new AluInstruction(op1_mov, from_nir(instr->dest, i),
548 u, {alu_write});
549 emit_instruction(ir);
550 }
551 }
552 if (ir)
553 ir->set_flag(alu_last_instr);
554 } else {
555 PValue addr = from_nir(instr->src[0], 0, 0);
556 return load_uniform_indirect(instr, addr, 16 * base, 0);
557 }
558 return true;
559 }
560
561 bool ShaderFromNirProcessor::load_uniform_indirect(nir_intrinsic_instr* instr, PValue addr, int offest, int bufferid)
562 {
563 if (!addr) {
564 std::cerr << "r600-nir: don't know how uniform is addressed\n";
565 return false;
566 }
567
568 GPRVector trgt;
569 for (int i = 0; i < 4; ++i)
570 trgt.set_reg_i(i, from_nir(instr->dest, i));
571
572 if (addr->type() != Value::gpr) {
573 emit_instruction(op1_mov, trgt.reg_i(0), {addr}, {alu_write, alu_last_instr});
574 addr = trgt.reg_i(0);
575 }
576
577 /* FIXME: buffer index and index mode are not set correctly */
578 auto ir = new FetchInstruction(vc_fetch, no_index_offset, trgt, addr, offest,
579 bufferid, PValue(), bim_none);
580 emit_instruction(ir);
581 for (int i = 0; i < instr->num_components ; ++i) {
582 add_uniform((instr->dest.ssa.index << 2) + i, trgt.reg_i(i));
583 }
584 m_sh_info.indirect_files |= 1 << TGSI_FILE_CONSTANT;
585 return true;
586 }
587
588 AluInstruction *ShaderFromNirProcessor::emit_load_literal(const nir_load_const_instr * literal, const nir_src& src, unsigned writemask)
589 {
590 AluInstruction *ir = nullptr;
591 for (int i = 0; i < literal->def.num_components ; ++i) {
592 if (writemask & (1 << i)){
593 PValue lsrc;
594 switch (literal->def.bit_size) {
595
596 case 1:
597 sfn_log << SfnLog::reg << "Got literal of bit size 1\n";
598 lsrc = literal->value[i].b ?
599 PValue(new LiteralValue( 0xffffffff, i)) :
600 Value::zero;
601 break;
602 case 32:
603 sfn_log << SfnLog::reg << "Got literal of bit size 32\n";
604 if (literal->value[i].u32 == 0)
605 lsrc = Value::zero;
606 else if (literal->value[i].u32 == 1)
607 lsrc = Value::one_i;
608 else if (literal->value[i].f32 == 1.0f)
609 lsrc = Value::one_f;
610 else if (literal->value[i].f32 == 0.5f)
611 lsrc = Value::zero_dot_5;
612 else
613 lsrc = PValue(new LiteralValue(literal->value[i].u32, i));
614 break;
615 default:
616 sfn_log << SfnLog::reg << "Got literal of bit size " << literal->def.bit_size
617 << " falling back to 32 bit\n";
618 lsrc = PValue(new LiteralValue(literal->value[i].u32, i));
619 }
620 ir = new AluInstruction(op1_mov, create_register_from_nir_src(src, i), lsrc, EmitInstruction::write);
621
622 emit_instruction(ir);
623 }
624 }
625 return ir;
626 }
627
628 PValue ShaderFromNirProcessor::from_nir_with_fetch_constant(const nir_src& src, unsigned component)
629 {
630 PValue value = from_nir(src, component);
631 if (value->type() != Value::gpr &&
632 value->type() != Value::gpr_vector &&
633 value->type() != Value::gpr_array_value) {
634 unsigned temp = allocate_temp_register();
635 PValue retval(new GPRValue(temp, component));
636 emit_instruction(new AluInstruction(op1_mov, retval, value,
637 EmitInstruction::last_write));
638 value = retval;
639 }
640 return value;
641 }
642
643 bool ShaderFromNirProcessor::emit_store_deref(nir_intrinsic_instr* instr)
644 {
645 auto out_var = get_deref_location(instr->src[0]);
646 if (!out_var)
647 return false;
648
649 return do_emit_store_deref(out_var, instr);
650 }
651
652 bool ShaderFromNirProcessor::emit_deref_instruction(nir_deref_instr* instr)
653 {
654 r600::sfn_log << SfnLog::instr << __func__ << ": emit '"
655 << *reinterpret_cast<nir_instr*>(instr)
656 << "'\n";
657
658 /* Give the specific shader type a chance to process this, i.e. Geometry and
659 * tesselation shaders need specialized deref_array, for the other shaders
660 * it is lowered.
661 */
662 if (emit_deref_instruction_override(instr))
663 return true;
664
665 switch (instr->deref_type) {
666 case nir_deref_type_var:
667 set_var_address(instr);
668 return true;
669 case nir_deref_type_array:
670 case nir_deref_type_array_wildcard:
671 case nir_deref_type_struct:
672 case nir_deref_type_cast:
673 default:
674 fprintf(stderr, "R600: deref type %d not supported\n", instr->deref_type);
675 }
676 return false;
677 }
678
679 void ShaderFromNirProcessor::load_uniform(const nir_alu_src &src)
680 {
681 AluInstruction *ir = nullptr;
682 PValue sv[4];
683
684 assert(src.src.is_ssa);
685
686 for (int i = 0; i < src.src.ssa->num_components ; ++i) {
687 unsigned uindex = (src.src.ssa->index << 2) + i;
688 sv[i] = uniform(uindex);
689 assert(sv[i]);
690 }
691
692 for (int i = 0; i < src.src.ssa->num_components ; ++i) {
693 ir = new AluInstruction(op1_mov, create_register_from_nir_src(src.src, i), sv[i],
694 EmitInstruction::write);
695 emit_instruction(ir);
696 }
697 if (ir)
698 ir->set_flag(alu_last_instr);
699 }
700
701
702
703 bool ShaderFromNirProcessor::emit_instruction(EAluOp opcode, PValue dest,
704 std::vector<PValue> srcs,
705 const std::set<AluModifiers>& m_flags)
706 {
707 AluInstruction *ir = new AluInstruction(opcode, dest, srcs, m_flags);
708 emit_instruction(ir);
709 return true;
710 }
711
712 void ShaderFromNirProcessor::add_param_output_reg(int loc, const GPRVector *gpr)
713 {
714 m_output_register_map[loc] = gpr;
715 }
716
717 void ShaderFromNirProcessor::emit_export_instruction(WriteoutInstruction *ir)
718 {
719 r600::sfn_log << SfnLog::instr << " as '" << *ir << "'\n";
720 m_export_output.push_back(PInstruction(ir));
721 }
722
723 const GPRVector * ShaderFromNirProcessor::output_register(unsigned location) const
724 {
725 const GPRVector *retval = nullptr;
726 auto val = m_output_register_map.find(location);
727 if (val != m_output_register_map.end())
728 retval = val->second;
729 return retval;
730 }
731
732 void ShaderFromNirProcessor::set_input(unsigned pos, PValue var)
733 {
734 r600::sfn_log << SfnLog::io << "Set input[" << pos << "] =" << *var << "\n";
735 m_inputs[pos] = var;
736 }
737
738 void ShaderFromNirProcessor::set_output(unsigned pos, PValue var)
739 {
740 r600::sfn_log << SfnLog::io << "Set output[" << pos << "] =" << *var << "\n";
741 m_outputs[pos] = var;
742 }
743
744 void ShaderFromNirProcessor::finalize()
745 {
746 do_finalize();
747
748 for (auto& i : m_inputs)
749 m_sh_info.input[i.first].gpr = i.second->sel();
750
751 for (auto& i : m_outputs)
752 m_sh_info.output[i.first].gpr = i.second->sel();
753
754 m_output.insert(m_output.end(), m_export_output.begin(), m_export_output.end());
755 m_export_output.clear();
756 }
757
758 }