r600/sfn: Add support for geometry shader
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_nir.cpp
1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2019 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_nir.h"
28 #include "nir_builder.h"
29
30 #include "../r600_pipe.h"
31 #include "../r600_shader.h"
32
33 #include "sfn_instruction_tex.h"
34
35 #include "sfn_shader_vertex.h"
36 #include "sfn_shader_fragment.h"
37 #include "sfn_shader_geometry.h"
38 #include "sfn_nir_lower_fs_out_to_vector.h"
39 #include "sfn_ir_to_assembly.h"
40
41 #include <vector>
42
43 namespace r600 {
44
45 using std::vector;
46
47 ShaderFromNir::ShaderFromNir():sh(nullptr),
48 m_current_if_id(0),
49 m_current_loop_id(0)
50 {
51 }
52
53 bool ShaderFromNir::lower(const nir_shader *shader, r600_pipe_shader *pipe_shader,
54 r600_pipe_shader_selector *sel, r600_shader_key& key,
55 struct r600_shader* gs_shader)
56 {
57 sh = shader;
58 assert(sh);
59
60 switch (shader->info.stage) {
61 case MESA_SHADER_VERTEX:
62 if (key.vs.as_es) {
63 sfn_log << SfnLog::trans << "Start VS for GS\n";
64 impl.reset(new VertexShaderFromNirForGS(pipe_shader, *sel, key, gs_shader));
65 } else if (key.vs.as_ls) {
66 sfn_log << "VS: next type TCS and TES not yet supported\n";
67 return false;
68 } else {
69 sfn_log << SfnLog::trans << "Start VS for FS\n";
70 impl.reset(new VertexShaderFromNirForFS(pipe_shader, *sel, key));
71 }
72 break;
73 case MESA_SHADER_GEOMETRY:
74 sfn_log << SfnLog::trans << "Start GS\n";
75 impl.reset(new GeometryShaderFromNir(pipe_shader, *sel, key));
76 break;
77 case MESA_SHADER_FRAGMENT:
78 sfn_log << SfnLog::trans << "Start FS\n";
79 impl.reset(new FragmentShaderFromNir(*shader, pipe_shader->shader, *sel, key));
80 break;
81 default:
82 return false;
83 }
84
85 sfn_log << SfnLog::trans << "Process declarations\n";
86 if (!process_declaration())
87 return false;
88
89 // at this point all functions should be inlined
90 const nir_function *func = reinterpret_cast<const nir_function *>(exec_list_get_head_const(&sh->functions));
91
92 sfn_log << SfnLog::trans << "Scan shader\n";
93 nir_foreach_block(block, func->impl) {
94 nir_foreach_instr(instr, block) {
95 if (!impl->scan_instruction(instr)) {
96 fprintf(stderr, "Unhandled sysvalue access ");
97 nir_print_instr(instr, stderr);
98 fprintf(stderr, "\n");
99 return false;
100 }
101 }
102 }
103
104 sfn_log << SfnLog::trans << "Reserve registers\n";
105 if (!impl->allocate_reserved_registers()) {
106 return false;
107 }
108
109 ValuePool::array_list arrays;
110 sfn_log << SfnLog::trans << "Allocate local registers\n";
111 foreach_list_typed(nir_register, reg, node, &func->impl->registers) {
112 impl->allocate_local_register(*reg, arrays);
113 }
114
115 sfn_log << SfnLog::trans << "Emit shader start\n";
116 impl->allocate_arrays(arrays);
117
118 impl->emit_shader_start();
119
120 sfn_log << SfnLog::trans << "Process shader \n";
121 foreach_list_typed(nir_cf_node, node, node, &func->impl->body) {
122 if (!process_cf_node(node))
123 return false;
124 }
125
126 // Add optimizations here
127 sfn_log << SfnLog::trans << "Finalize\n";
128 impl->finalize();
129
130 if (!sfn_log.has_debug_flag(SfnLog::nomerge)) {
131 sfn_log << SfnLog::trans << "Merge registers\n";
132 impl->remap_registers();
133 }
134 sfn_log << SfnLog::trans << "Finished translating to R600 IR\n";
135 return true;
136 }
137
138 Shader ShaderFromNir::shader() const
139 {
140 return Shader{impl->m_output, impl->get_temp_registers()};
141 }
142
143
144 bool ShaderFromNir::process_cf_node(nir_cf_node *node)
145 {
146 SFN_TRACE_FUNC(SfnLog::flow, "CF");
147 switch (node->type) {
148 case nir_cf_node_block:
149 return process_block(nir_cf_node_as_block(node));
150 case nir_cf_node_if:
151 return process_if(nir_cf_node_as_if(node));
152 case nir_cf_node_loop:
153 return process_loop(nir_cf_node_as_loop(node));
154 default:
155 return false;
156 }
157 }
158
159 bool ShaderFromNir::process_if(nir_if *if_stmt)
160 {
161 SFN_TRACE_FUNC(SfnLog::flow, "IF");
162
163 if (!impl->emit_if_start(m_current_if_id, if_stmt))
164 return false;
165
166 int if_id = m_current_if_id++;
167 m_if_stack.push(if_id);
168
169 foreach_list_typed(nir_cf_node, n, node, &if_stmt->then_list)
170 if (!process_cf_node(n)) return false;
171
172 if (!if_stmt->then_list.is_empty()) {
173 if (!impl->emit_else_start(if_id))
174 return false;
175
176 foreach_list_typed(nir_cf_node, n, node, &if_stmt->else_list)
177 if (!process_cf_node(n)) return false;
178 }
179
180 if (!impl->emit_ifelse_end(if_id))
181 return false;
182
183 m_if_stack.pop();
184 return true;
185 }
186
187 bool ShaderFromNir::process_loop(nir_loop *node)
188 {
189 SFN_TRACE_FUNC(SfnLog::flow, "LOOP");
190 int loop_id = m_current_loop_id++;
191
192 if (!impl->emit_loop_start(loop_id))
193 return false;
194
195 foreach_list_typed(nir_cf_node, n, node, &node->body)
196 if (!process_cf_node(n)) return false;
197
198 if (!impl->emit_loop_end(loop_id))
199 return false;
200
201 return true;
202 }
203
204 bool ShaderFromNir::process_block(nir_block *block)
205 {
206 SFN_TRACE_FUNC(SfnLog::flow, "BLOCK");
207 nir_foreach_instr(instr, block) {
208 int r = emit_instruction(instr);
209 if (!r) {
210 sfn_log << SfnLog::err << "R600: Unsupported instruction: "
211 << *instr << "\n";
212 return false;
213 }
214 }
215 return true;
216 }
217
218
219 ShaderFromNir::~ShaderFromNir()
220 {
221 }
222
223 pipe_shader_type ShaderFromNir::processor_type() const
224 {
225 return impl->m_processor_type;
226 }
227
228
229 bool ShaderFromNir::emit_instruction(nir_instr *instr)
230 {
231 assert(impl);
232
233 sfn_log << SfnLog::instr << "Read instruction " << *instr << "\n";
234
235 switch (instr->type) {
236 case nir_instr_type_alu:
237 return impl->emit_alu_instruction(instr);
238 case nir_instr_type_deref:
239 return impl->emit_deref_instruction(nir_instr_as_deref(instr));
240 case nir_instr_type_intrinsic:
241 return impl->emit_intrinsic_instruction(nir_instr_as_intrinsic(instr));
242 case nir_instr_type_load_const:
243 return impl->set_literal_constant(nir_instr_as_load_const(instr));
244 case nir_instr_type_tex:
245 return impl->emit_tex_instruction(instr);
246 case nir_instr_type_jump:
247 return impl->emit_jump_instruction(nir_instr_as_jump(instr));
248 default:
249 fprintf(stderr, "R600: %s: ShaderFromNir Unsupported instruction: type %d:'", __func__, instr->type);
250 nir_print_instr(instr, stderr);
251 fprintf(stderr, "'\n");
252 return false;
253 case nir_instr_type_ssa_undef:
254 return impl->create_undef(nir_instr_as_ssa_undef(instr));
255 return true;
256 }
257 }
258
259 bool ShaderFromNir::process_declaration()
260 {
261 // scan declarations
262 nir_foreach_variable(variable, &sh->inputs) {
263 if (!impl->process_inputs(variable)) {
264 fprintf(stderr, "R600: error parsing input varible %s\n", variable->name);
265 return false;
266 }
267 }
268
269 // scan declarations
270 nir_foreach_variable(variable, &sh->outputs) {
271 if (!impl->process_outputs(variable)) {
272 fprintf(stderr, "R600: error parsing outputs varible %s\n", variable->name);
273 return false;
274 }
275 }
276
277 // scan declarations
278 nir_foreach_variable(variable, &sh->uniforms) {
279 if (!impl->process_uniforms(variable)) {
280 fprintf(stderr, "R600: error parsing outputs varible %s\n", variable->name);
281 return false;
282 }
283 }
284
285 return true;
286 }
287
288 const std::vector<Instruction::Pointer>& ShaderFromNir::shader_ir() const
289 {
290 assert(impl);
291 return impl->m_output;
292 }
293
294
295 AssemblyFromShader::~AssemblyFromShader()
296 {
297 }
298
299 bool AssemblyFromShader::lower(const std::vector<Instruction::Pointer>& ir)
300 {
301 return do_lower(ir);
302 }
303
304 static nir_ssa_def *
305 r600_nir_lower_pack_unpack_2x16_impl(nir_builder *b, nir_instr *instr, void *_options)
306 {
307 nir_alu_instr *alu = nir_instr_as_alu(instr);
308
309 switch (alu->op) {
310 case nir_op_unpack_half_2x16: {
311 nir_ssa_def *packed = nir_ssa_for_alu_src(b, alu, 0);
312 return nir_vec2(b, nir_unpack_half_2x16_split_x(b, packed),
313 nir_unpack_half_2x16_split_y(b, packed));
314
315 }
316 case nir_op_pack_half_2x16: {
317 nir_ssa_def *src_vec2 = nir_ssa_for_alu_src(b, alu, 0);
318 return nir_pack_half_2x16_split(b, nir_channel(b, src_vec2, 0),
319 nir_channel(b, src_vec2, 1));
320 }
321 default:
322 return nullptr;
323 }
324 }
325
326 bool r600_nir_lower_pack_unpack_2x16_filter(const nir_instr *instr, const void *_options)
327 {
328 return instr->type == nir_instr_type_alu;
329 }
330
331 bool r600_nir_lower_pack_unpack_2x16(nir_shader *shader)
332 {
333 return nir_shader_lower_instructions(shader,
334 r600_nir_lower_pack_unpack_2x16_filter,
335 r600_nir_lower_pack_unpack_2x16_impl,
336 nullptr);
337 };
338
339 static void
340 r600_nir_lower_scratch_address_impl(nir_builder *b, nir_intrinsic_instr *instr)
341 {
342 b->cursor = nir_before_instr(&instr->instr);
343
344 int address_index = 0;
345 int align;
346
347 if (instr->intrinsic == nir_intrinsic_store_scratch) {
348 align = instr->src[0].ssa->num_components;
349 address_index = 1;
350 } else{
351 align = instr->dest.ssa.num_components;
352 }
353
354 nir_ssa_def *address = instr->src[address_index].ssa;
355 nir_ssa_def *new_address = nir_ishr(b, address, nir_imm_int(b, 4 * align));
356
357 nir_instr_rewrite_src(&instr->instr, &instr->src[address_index],
358 nir_src_for_ssa(new_address));
359 }
360
361 bool r600_lower_scratch_addresses(nir_shader *shader)
362 {
363 bool progress = false;
364 nir_foreach_function(function, shader) {
365 nir_builder build;
366 nir_builder_init(&build, function->impl);
367
368 nir_foreach_block(block, function->impl) {
369 nir_foreach_instr(instr, block) {
370 if (instr->type != nir_instr_type_intrinsic)
371 continue;
372 nir_intrinsic_instr *op = nir_instr_as_intrinsic(instr);
373 if (op->intrinsic != nir_intrinsic_load_scratch &&
374 op->intrinsic != nir_intrinsic_store_scratch)
375 continue;
376 r600_nir_lower_scratch_address_impl(&build, op);
377 progress = true;
378 }
379 }
380 }
381 return progress;
382 }
383
384 }
385
386 using r600::r600_nir_lower_int_tg4;
387 using r600::r600_nir_lower_pack_unpack_2x16;
388 using r600::r600_lower_scratch_addresses;
389 using r600::r600_lower_fs_out_to_vector;
390
391 int
392 r600_glsl_type_size(const struct glsl_type *type, bool is_bindless)
393 {
394 return glsl_count_vec4_slots(type, false, is_bindless);
395 }
396
397 void
398 r600_get_natural_size_align_bytes(const struct glsl_type *type,
399 unsigned *size, unsigned *align)
400 {
401 if (type->base_type != GLSL_TYPE_ARRAY) {
402 *align = 1;
403 *size = 1;
404 } else {
405 unsigned elem_size, elem_align;
406 glsl_get_natural_size_align_bytes(type->fields.array,
407 &elem_size, &elem_align);
408 *align = 1;
409 *size = type->length;
410 }
411 }
412
413 static bool
414 optimize_once(nir_shader *shader)
415 {
416 bool progress = false;
417 NIR_PASS(progress, shader, nir_copy_prop);
418 NIR_PASS(progress, shader, nir_opt_dce);
419 NIR_PASS(progress, shader, nir_opt_algebraic);
420 NIR_PASS(progress, shader, nir_opt_constant_folding);
421 NIR_PASS(progress, shader, nir_opt_copy_prop_vars);
422 NIR_PASS(progress, shader, nir_opt_vectorize);
423
424 NIR_PASS(progress, shader, nir_opt_remove_phis);
425
426 if (nir_opt_trivial_continues(shader)) {
427 progress = true;
428 NIR_PASS(progress, shader, nir_copy_prop);
429 NIR_PASS(progress, shader, nir_opt_dce);
430 }
431
432 NIR_PASS(progress, shader, nir_opt_if, false);
433 NIR_PASS(progress, shader, nir_opt_dead_cf);
434 NIR_PASS(progress, shader, nir_opt_cse);
435 NIR_PASS(progress, shader, nir_opt_peephole_select, 200, true, true);
436
437 NIR_PASS(progress, shader, nir_opt_conditional_discard);
438 NIR_PASS(progress, shader, nir_opt_dce);
439 NIR_PASS(progress, shader, nir_opt_undef);
440
441 NIR_PASS(progress, shader, nir_remove_dead_variables, nir_var_shader_in);
442 NIR_PASS(progress, shader, nir_remove_dead_variables, nir_var_shader_out);
443 return progress;
444 }
445
446 bool has_saturate(const nir_function *func)
447 {
448 nir_foreach_block(block, func->impl) {
449 nir_foreach_instr(instr, block) {
450 if (instr->type == nir_instr_type_alu) {
451 auto alu = nir_instr_as_alu(instr);
452 if (alu->dest.saturate)
453 return true;
454 }
455 }
456 }
457 return false;
458 }
459
460 int r600_shader_from_nir(struct r600_context *rctx,
461 struct r600_pipe_shader *pipeshader,
462 r600_shader_key *key)
463 {
464 char filename[4000];
465 struct r600_pipe_shader_selector *sel = pipeshader->selector;
466
467 r600::ShaderFromNir convert;
468
469 if (rctx->screen->b.debug_flags & DBG_PREOPT_IR) {
470 fprintf(stderr, "PRE-OPT-NIR-----------.------------------------------\n");
471 nir_print_shader(sel->nir, stderr);
472 fprintf(stderr, "END PRE-OPT-NIR--------------------------------------\n\n");
473 }
474
475 NIR_PASS_V(sel->nir, nir_lower_vars_to_ssa);
476 NIR_PASS_V(sel->nir, nir_lower_regs_to_ssa);
477 NIR_PASS_V(sel->nir, nir_lower_phis_to_scalar);
478
479 static const struct nir_lower_tex_options lower_tex_options = {
480 .lower_txp = ~0u,
481 };
482 NIR_PASS_V(sel->nir, nir_lower_tex, &lower_tex_options);
483
484 NIR_PASS_V(sel->nir, r600::r600_nir_lower_txl_txf_array_or_cube);
485
486 NIR_PASS_V(sel->nir, r600_nir_lower_int_tg4);
487 NIR_PASS_V(sel->nir, r600_nir_lower_pack_unpack_2x16);
488
489 NIR_PASS_V(sel->nir, nir_lower_io, nir_var_uniform, r600_glsl_type_size,
490 nir_lower_io_lower_64bit_to_32);
491
492 if (sel->nir->info.stage == MESA_SHADER_VERTEX)
493 NIR_PASS_V(sel->nir, r600_vectorize_vs_inputs);
494
495 if (sel->nir->info.stage == MESA_SHADER_FRAGMENT)
496 NIR_PASS_V(sel->nir, r600_lower_fs_out_to_vector);
497
498 if (sel->nir->info.stage == MESA_SHADER_TESS_CTRL ||
499 sel->nir->info.stage == MESA_SHADER_TESS_EVAL)
500 NIR_PASS_V(sel->nir, nir_lower_io, nir_var_shader_in, r600_glsl_type_size,
501 nir_lower_io_lower_64bit_to_32);
502
503 if (sel->nir->info.stage == MESA_SHADER_TESS_CTRL)
504 NIR_PASS_V(sel->nir, nir_lower_io, nir_var_shader_out, r600_glsl_type_size,
505 nir_lower_io_lower_64bit_to_32);
506
507 const nir_function *func = reinterpret_cast<const nir_function *>(exec_list_get_head_const(&sel->nir->functions));
508 bool optimize = func->impl->registers.length() == 0 && !has_saturate(func);
509
510
511 /* It seems the output of this optimization is cached somewhere, and
512 * when there are registers, then we can no longer copy propagate, so
513 * skip the optimization then. (There is probably a better way, but yeah)
514 */
515 if (optimize)
516 while(optimize_once(sel->nir));
517
518 NIR_PASS_V(sel->nir, nir_lower_vars_to_scratch,
519 nir_var_function_temp,
520 100,
521 r600_get_natural_size_align_bytes);
522
523 while (optimize && optimize_once(sel->nir));
524
525 NIR_PASS_V(sel->nir, nir_lower_locals_to_regs);
526 //NIR_PASS_V(sel->nir, nir_opt_algebraic);
527 //NIR_PASS_V(sel->nir, nir_copy_prop);
528 NIR_PASS_V(sel->nir, nir_lower_to_source_mods, nir_lower_float_source_mods);
529 NIR_PASS_V(sel->nir, nir_convert_from_ssa, true);
530 NIR_PASS_V(sel->nir, nir_opt_dce);
531
532 if ((rctx->screen->b.debug_flags & DBG_NIR) &&
533 (rctx->screen->b.debug_flags & DBG_ALL_SHADERS)) {
534 fprintf(stderr, "-- NIR --------------------------------------------------------\n");
535 struct nir_function *func = (struct nir_function *)exec_list_get_head(&sel->nir->functions);
536 nir_index_ssa_defs(func->impl);
537 nir_print_shader(sel->nir, stderr);
538 fprintf(stderr, "-- END --------------------------------------------------------\n");
539 }
540
541 memset(&pipeshader->shader, 0, sizeof(r600_shader));
542 pipeshader->scratch_space_needed = sel->nir->scratch_size;
543
544 if (sel->nir->info.stage == MESA_SHADER_TESS_EVAL ||
545 sel->nir->info.stage == MESA_SHADER_VERTEX ||
546 sel->nir->info.stage == MESA_SHADER_GEOMETRY) {
547 pipeshader->shader.clip_dist_write |= ((1 << sel->nir->info.clip_distance_array_size) - 1);
548 pipeshader->shader.cull_dist_write = ((1 << sel->nir->info.cull_distance_array_size) - 1)
549 << sel->nir->info.clip_distance_array_size;
550 pipeshader->shader.cc_dist_mask = (1 << (sel->nir->info.cull_distance_array_size +
551 sel->nir->info.clip_distance_array_size)) - 1;
552 }
553
554 // For learning we print out the complete failed shader
555 // and instead of asserts we use exceptions
556 bool r;
557 try {
558 struct r600_shader* gs_shader = nullptr;
559 if (rctx->gs_shader)
560 gs_shader = &rctx->gs_shader->current->shader;
561 r = convert.lower(sel->nir, pipeshader, sel, *key, gs_shader);
562
563 } catch (std::logic_error& x) {
564 r = false;
565 }
566 if (!r || rctx->screen->b.debug_flags & DBG_ALL_SHADERS) {
567 static int shnr = 0;
568
569 snprintf(filename, 4000, "nir-%s_%d.inc", sel->nir->info.name, shnr++);
570
571 if (access(filename, F_OK) == -1) {
572 FILE *f = fopen(filename, "w");
573
574 if (f) {
575 fprintf(f, "const char *shader_blob_%s = {\nR\"(", sel->nir->info.name);
576 nir_print_shader(sel->nir, f);
577 fprintf(f, ")\";\n");
578 fclose(f);
579 }
580 }
581 if (!r)
582 return -2;
583 }
584
585 auto shader = convert.shader();
586
587 r600_screen *rscreen = rctx->screen;
588 r600_bytecode_init(&pipeshader->shader.bc, rscreen->b.chip_class, rscreen->b.family,
589 rscreen->has_compressed_msaa_texturing);
590
591 r600::sfn_log << r600::SfnLog::shader_info
592 << "pipeshader->shader.processor_type = "
593 << pipeshader->shader.processor_type << "\n";
594
595 pipeshader->shader.bc.type = pipeshader->shader.processor_type;
596 pipeshader->shader.bc.isa = rctx->isa;
597
598 r600::AssemblyFromShaderLegacy afs(&pipeshader->shader, key);
599 if (!afs.lower(shader.m_ir)) {
600 R600_ERR("%s: Lowering to assembly failed\n", __func__);
601 return -1;
602 }
603
604 if (sel->nir->info.stage == MESA_SHADER_GEOMETRY) {
605 r600::sfn_log << r600::SfnLog::shader_info << "Geometry shader, create copy shader\n";
606 generate_gs_copy_shader(rctx, pipeshader, &sel->so);
607 assert(pipeshader->gs_copy_shader);
608 } else {
609 r600::sfn_log << r600::SfnLog::shader_info << "This is not a Geometry shader\n";
610 }
611
612 return 0;
613 }