3 * Copyright (c) 2018 Collabora LTD
5 * Author: Gert Wollny <gert.wollny@collabora.com>
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:
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
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.
27 #include "../r600_pipe.h"
28 #include "../r600_shader.h"
29 #include "sfn_shader_vertex.h"
31 #include "sfn_shader_fragment.h"
32 #include "sfn_ir_to_assembly.h"
34 #include "sfn_instruction_fetch.h"
38 #define ENABLE_DEBUG 1
41 #define DEBUG_SFN(X) \
54 ShaderFromNirProcessor::ShaderFromNirProcessor(pipe_shader_type ptype
,
55 r600_pipe_shader_selector
& sel
,
56 r600_shader
&sh_info
):
57 m_processor_type(ptype
),
61 m_pending_else(nullptr),
62 m_next_hwatomic_loc(0),
65 m_sh_info
.processor_type
= ptype
;
69 ShaderFromNirProcessor::~ShaderFromNirProcessor()
73 bool ShaderFromNirProcessor::scan_instruction(nir_instr
*instr
)
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;
85 return scan_sysvalue_access(instr
);
88 bool ShaderFromNirProcessor::process_uniforms(nir_variable
*uniform
)
91 m_uniform_type_map
[uniform
->data
.location
] = uniform
->type
;
93 if (uniform
->type
->contains_atomic()) {
94 int natomics
= uniform
->type
->atomic_size() / ATOMIC_COUNTER_SIZE
;
95 sh_info().nhwatomic
+= natomics
;
97 if (uniform
->type
->is_array())
98 sh_info().indirect_files
|= 1 << TGSI_FILE_HW_ATOMIC
;
100 sh_info().uses_atomics
= 1;
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;
111 m_sel
.info
.file_count
[TGSI_FILE_HW_ATOMIC
] += atom
.end
- atom
.start
+ 1;
113 sfn_log
<< SfnLog::io
<< "HW_ATOMIC file count: "
114 << m_sel
.info
.file_count
[TGSI_FILE_HW_ATOMIC
] << "\n";
117 if (uniform
->type
->is_image() || uniform
->data
.mode
== nir_var_mem_ssbo
) {
118 sh_info().uses_images
= 1;
124 bool ShaderFromNirProcessor::process_inputs(nir_variable
*input
)
126 return do_process_inputs(input
);
129 bool ShaderFromNirProcessor::process_outputs(nir_variable
*output
)
131 return do_process_outputs(output
);
134 void ShaderFromNirProcessor::add_array_deref(nir_deref_instr
*instr
)
136 nir_variable
*var
= nir_deref_instr_get_variable(instr
);
138 assert(instr
->mode
== nir_var_function_temp
);
139 assert(glsl_type_is_array(var
->type
));
141 // add an alias for the index to the register(s);
146 void ShaderFromNirProcessor::set_var_address(nir_deref_instr
*instr
)
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
;
153 sfn_log
<< SfnLog::io
<< "Add var deref:" << index
154 << " with DDL:" << instr
->var
->data
.driver_location
<< "\n";
157 void ShaderFromNirProcessor::evaluate_spi_sid(r600_shader_io
& io
)
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
:
168 case TGSI_SEMANTIC_GENERIC
:
169 io
.spi_sid
= io
.sid
+ 1;
172 /* For non-generic params - pack name and sid into 8 bits */
173 io
.spi_sid
= (0x80 | (io
.name
<< 3) | io
.sid
) + 1;
177 const nir_variable
*ShaderFromNirProcessor::get_deref_location(const nir_src
& src
) const
179 unsigned index
= src
.is_ssa
? src
.ssa
->index
: src
.reg
.reg
->index
;
181 sfn_log
<< SfnLog::io
<< "Search for deref:" << index
<< "\n";
183 auto v
= m_var_derefs
.find(index
);
184 if (v
!= m_var_derefs
.end())
187 fprintf(stderr
, "R600: could not find deref with index %d\n", index
);
191 /*nir_deref_instr *deref = nir_instr_as_deref(src.ssa->parent_instr);
192 return nir_deref_instr_get_variable(deref); */
195 bool ShaderFromNirProcessor::emit_tex_instruction(nir_instr
* instr
)
197 return m_tex_instr
.emit(instr
);
200 void ShaderFromNirProcessor::emit_instruction(Instruction
*ir
)
202 if (m_pending_else
) {
203 m_output
.push_back(PInstruction(m_pending_else
));
204 m_pending_else
= nullptr;
207 r600::sfn_log
<< SfnLog::instr
<< " as '" << *ir
<< "'\n";
208 m_output
.push_back(Instruction::Pointer(ir
));
211 void ShaderFromNirProcessor::emit_shader_start()
213 /* placeholder, may become an abstract method */
216 bool ShaderFromNirProcessor::emit_jump_instruction(nir_jump_instr
*instr
)
218 switch (instr
->type
) {
219 case nir_jump_break
: {
220 auto b
= new LoopBreakInstruction();
224 case nir_jump_continue
: {
225 auto b
= new LoopContInstruction();
230 nir_instr
*i
= reinterpret_cast<nir_instr
*>(instr
);
231 sfn_log
<< SfnLog::err
<< "Jump instrunction " << *i
<< " not supported\n";
238 bool ShaderFromNirProcessor::emit_alu_instruction(nir_instr
* instr
)
240 return m_alu_instr
.emit(instr
);
243 bool ShaderFromNirProcessor::emit_deref_instruction_override(UNUSED nir_deref_instr
* instr
)
248 bool ShaderFromNirProcessor::emit_loop_start(int loop_id
)
250 LoopBeginInstruction
*loop
= new LoopBeginInstruction();
251 emit_instruction(loop
);
252 m_loop_begin_block_map
[loop_id
] = loop
;
255 bool ShaderFromNirProcessor::emit_loop_end(int loop_id
)
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";
263 LoopEndInstruction
*loop
= new LoopEndInstruction(start
->second
);
264 emit_instruction(loop
);
266 m_loop_begin_block_map
.erase(start
);
270 bool ShaderFromNirProcessor::emit_if_start(int if_id
, nir_if
*if_stmt
)
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
);
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
;
287 bool ShaderFromNirProcessor::emit_else_start(int if_id
)
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";
295 if (iif
->second
->type() != Instruction::cond_if
) {
296 std::cerr
<< "Error: ELSE branch " << if_id
<< " not started by an IF branch\n";
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
;
307 bool ShaderFromNirProcessor::emit_ifelse_end(int if_id
)
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";
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";
320 /* Clear pending else, if the else branch was empty, non will be emitted */
322 m_pending_else
= nullptr;
324 IfElseEndInstruction
*ir
= new IfElseEndInstruction();
325 emit_instruction(ir
);
330 bool ShaderFromNirProcessor::emit_intrinsic_instruction(nir_intrinsic_instr
* instr
)
332 r600::sfn_log
<< SfnLog::instr
<< "emit '"
333 << *reinterpret_cast<nir_instr
*>(instr
)
334 << "' (" << __func__
<< ")\n";
336 if (emit_intrinsic_instruction_override(instr
))
339 switch (instr
->intrinsic
) {
340 case nir_intrinsic_load_deref
: {
341 auto var
= get_deref_location(instr
->src
[0]);
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";
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
);
355 cerr
<< "r600-nir: Unsupported mode" << mode_helper
->second
356 << "for src variable\n";
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
:
374 fprintf(stderr
, "r600-nir: Unsupported intrinsic %d\n", instr
->intrinsic
);
380 bool ShaderFromNirProcessor::emit_intrinsic_instruction_override(UNUSED nir_intrinsic_instr
* instr
)
386 ShaderFromNirProcessor::emit_load_function_temp(UNUSED
const nir_variable
*var
, UNUSED nir_intrinsic_instr
*instr
)
391 bool ShaderFromNirProcessor::load_preloaded_value(const nir_dest
& dest
, int chan
, PValue value
, bool as_last
)
394 auto ir
= new AluInstruction(op1_mov
, from_nir(dest
, 0), value
, {alu_write
});
396 ir
->set_flag(alu_last_instr
);
397 emit_instruction(ir
);
399 inject_register(dest
.ssa
.index
, chan
, value
, true);
404 GPRVector
*ShaderFromNirProcessor::vec_from_nir_with_fetch_constant(const nir_src
& src
,
405 UNUSED
unsigned mask
,
406 const GPRVector::Swizzle
& swizzle
)
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
);
416 AluInstruction
*ir
= nullptr;
417 int sel
= allocate_temp_register();
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
);
428 ir
->set_flag(alu_last_instr
);
430 result
= new GPRVector(v
);
435 bool ShaderFromNirProcessor::emit_load_ubo(nir_intrinsic_instr
* instr
)
437 nir_src
& src0
= instr
->src
[0];
438 nir_src
& src1
= instr
->src
[1];
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
);
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
);
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
;
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
);
458 ir
= new AluInstruction(op1_mov
, from_nir(instr
->dest
, i
), u
, {alu_write
});
459 emit_instruction(ir
);
463 ir
->set_flag(alu_last_instr
);
467 /* literal0 is lost ...*/
468 return load_uniform_indirect(instr
, from_nir(instr
->src
[1], 0, 0), 0, literal0
->value
[0].u32
+ 1);
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);
477 for (int i
= 0; i
< 4; ++i
)
478 trgt
.set_reg_i(i
, from_nir(instr
->dest
, i
));
480 auto ir
= new FetchInstruction(vc_fetch
, no_index_offset
, trgt
, addr
, 0,
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
));
487 m_sh_info
.indirect_files
|= 1 << TGSI_FILE_CONSTANT
;
493 bool ShaderFromNirProcessor::emit_discard_if(nir_intrinsic_instr
* instr
)
495 r600::sfn_log
<< SfnLog::instr
<< "emit '"
496 << *reinterpret_cast<nir_instr
*>(instr
)
497 << "' (" << __func__
<< ")\n";
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
}));
504 emit_instruction(new AluInstruction(op2_kille
, PValue(new GPRValue(0,0)),
505 {Value::zero
, Value::zero
}, {alu_last_instr
}));
507 m_sh_info
.uses_kill
= 1;
511 bool ShaderFromNirProcessor::emit_load_input_deref(const nir_variable
*var
,
512 nir_intrinsic_instr
* instr
)
514 return do_emit_load_deref(var
, instr
);
517 bool ShaderFromNirProcessor::reserve_uniform(nir_intrinsic_instr
* instr
)
519 r600::sfn_log
<< SfnLog::instr
<< __func__
<< ": emit '"
520 << *reinterpret_cast<nir_instr
*>(instr
)
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
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
);
535 int base
= nir_intrinsic_base(instr
);
537 AluInstruction
*ir
= nullptr;
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";
544 if (instr
->dest
.is_ssa
)
545 add_uniform((instr
->dest
.ssa
.index
<< 2) + i
, u
);
547 ir
= new AluInstruction(op1_mov
, from_nir(instr
->dest
, i
),
549 emit_instruction(ir
);
553 ir
->set_flag(alu_last_instr
);
555 PValue addr
= from_nir(instr
->src
[0], 0, 0);
556 return load_uniform_indirect(instr
, addr
, 16 * base
, 0);
561 bool ShaderFromNirProcessor::load_uniform_indirect(nir_intrinsic_instr
* instr
, PValue addr
, int offest
, int bufferid
)
564 std::cerr
<< "r600-nir: don't know how uniform is addressed\n";
569 for (int i
= 0; i
< 4; ++i
)
570 trgt
.set_reg_i(i
, from_nir(instr
->dest
, i
));
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);
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
));
584 m_sh_info
.indirect_files
|= 1 << TGSI_FILE_CONSTANT
;
588 AluInstruction
*ShaderFromNirProcessor::emit_load_literal(const nir_load_const_instr
* literal
, const nir_src
& src
, unsigned writemask
)
590 AluInstruction
*ir
= nullptr;
591 for (int i
= 0; i
< literal
->def
.num_components
; ++i
) {
592 if (writemask
& (1 << i
)){
594 switch (literal
->def
.bit_size
) {
597 sfn_log
<< SfnLog::reg
<< "Got literal of bit size 1\n";
598 lsrc
= literal
->value
[i
].b
?
599 PValue(new LiteralValue( 0xffffffff, i
)) :
603 sfn_log
<< SfnLog::reg
<< "Got literal of bit size 32\n";
604 if (literal
->value
[i
].u32
== 0)
606 else if (literal
->value
[i
].u32
== 1)
608 else if (literal
->value
[i
].f32
== 1.0f
)
610 else if (literal
->value
[i
].f32
== 0.5f
)
611 lsrc
= Value::zero_dot_5
;
613 lsrc
= PValue(new LiteralValue(literal
->value
[i
].u32
, i
));
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
));
620 ir
= new AluInstruction(op1_mov
, create_register_from_nir_src(src
, i
), lsrc
, EmitInstruction::write
);
622 emit_instruction(ir
);
628 PValue
ShaderFromNirProcessor::from_nir_with_fetch_constant(const nir_src
& src
, unsigned component
)
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
));
643 bool ShaderFromNirProcessor::emit_store_deref(nir_intrinsic_instr
* instr
)
645 auto out_var
= get_deref_location(instr
->src
[0]);
649 return do_emit_store_deref(out_var
, instr
);
652 bool ShaderFromNirProcessor::emit_deref_instruction(nir_deref_instr
* instr
)
654 r600::sfn_log
<< SfnLog::instr
<< __func__
<< ": emit '"
655 << *reinterpret_cast<nir_instr
*>(instr
)
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
662 if (emit_deref_instruction_override(instr
))
665 switch (instr
->deref_type
) {
666 case nir_deref_type_var
:
667 set_var_address(instr
);
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
:
674 fprintf(stderr
, "R600: deref type %d not supported\n", instr
->deref_type
);
679 void ShaderFromNirProcessor::load_uniform(const nir_alu_src
&src
)
681 AluInstruction
*ir
= nullptr;
684 assert(src
.src
.is_ssa
);
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
);
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
);
698 ir
->set_flag(alu_last_instr
);
703 bool ShaderFromNirProcessor::emit_instruction(EAluOp opcode
, PValue dest
,
704 std::vector
<PValue
> srcs
,
705 const std::set
<AluModifiers
>& m_flags
)
707 AluInstruction
*ir
= new AluInstruction(opcode
, dest
, srcs
, m_flags
);
708 emit_instruction(ir
);
712 void ShaderFromNirProcessor::add_param_output_reg(int loc
, const GPRVector
*gpr
)
714 m_output_register_map
[loc
] = gpr
;
717 void ShaderFromNirProcessor::emit_export_instruction(WriteoutInstruction
*ir
)
719 r600::sfn_log
<< SfnLog::instr
<< " as '" << *ir
<< "'\n";
720 m_export_output
.push_back(PInstruction(ir
));
723 const GPRVector
* ShaderFromNirProcessor::output_register(unsigned location
) const
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
;
732 void ShaderFromNirProcessor::set_input(unsigned pos
, PValue var
)
734 r600::sfn_log
<< SfnLog::io
<< "Set input[" << pos
<< "] =" << *var
<< "\n";
738 void ShaderFromNirProcessor::set_output(unsigned pos
, PValue var
)
740 r600::sfn_log
<< SfnLog::io
<< "Set output[" << pos
<< "] =" << *var
<< "\n";
741 m_outputs
[pos
] = var
;
744 void ShaderFromNirProcessor::finalize()
748 for (auto& i
: m_inputs
)
749 m_sh_info
.input
[i
.first
].gpr
= i
.second
->sel();
751 for (auto& i
: m_outputs
)
752 m_sh_info
.output
[i
.first
].gpr
= i
.second
->sel();
754 m_output
.insert(m_output
.end(), m_export_output
.begin(), m_export_output
.end());
755 m_export_output
.clear();