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