1 /* -*- mesa-c++ -*-
2 * Copyright 2019 Collabora LTD
3 * Author: Gert Wollny <gert.wollny@collabora.com>
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "r600_sfn.h"
8
9 #include "compiler/nir/nir.h"
10 #include "compiler/shader_enums.h"
11 #include "sfn/sfn_assembler.h"
12 #include "sfn/sfn_debug.h"
13 #include "sfn/sfn_memorypool.h"
14 #include "sfn/sfn_nir.h"
15 #include "sfn/sfn_shader.h"
16 #include "r600_asm.h"
17 #include "r600_pipe.h"
18 #include "util/macros.h"
19 #include "util/ralloc.h"
20
21 #include <cassert>
22 #include <cstdio>
23 #include <cstring>
24 #include <iostream>
25
26 char *
r600_finalize_nir(pipe_screen * screen,struct nir_shader * nir)27 r600_finalize_nir(pipe_screen *screen, struct nir_shader *nir)
28 {
29 auto rs = container_of(screen, r600_screen, b.b);
30 r600_finalize_nir_common(nir, rs->b.gfx_level);
31 return nullptr;
32 }
33
34 class MallocPoolRelease {
35 public:
MallocPoolRelease()36 MallocPoolRelease() { r600::init_pool(); }
~MallocPoolRelease()37 ~MallocPoolRelease() { r600::release_pool(); }
38 };
39
40 int
r600_shader_from_nir(struct r600_context * rctx,struct r600_pipe_shader * pipeshader,r600_shader_key * key)41 r600_shader_from_nir(struct r600_context *rctx,
42 struct r600_pipe_shader *pipeshader,
43 r600_shader_key *key)
44 {
45
46 MallocPoolRelease pool_release;
47
48 struct r600_pipe_shader_selector *sel = pipeshader->selector;
49
50 if (rctx->screen->b.debug_flags & DBG_PREOPT_IR) {
51 fprintf(stderr, "PRE-OPT-NIR-----------.------------------------------\n");
52 nir_print_shader(sel->nir, stderr);
53 fprintf(stderr, "END PRE-OPT-NIR--------------------------------------\n\n");
54 }
55
56 auto sh = nir_shader_clone(sel->nir, sel->nir);
57
58 r600_lower_and_optimize_nir(sh, key, rctx->b.gfx_level, &sel->so);
59
60 if (rctx->screen->b.debug_flags & DBG_ALL_SHADERS) {
61 fprintf(stderr,
62 "-- NIR --------------------------------------------------------\n");
63 struct nir_function *func =
64 (struct nir_function *)exec_list_get_head(&sh->functions);
65 nir_index_ssa_defs(func->impl);
66 nir_print_shader(sh, stderr);
67 fprintf(stderr,
68 "-- END --------------------------------------------------------\n");
69 }
70
71 memset(&pipeshader->shader, 0, sizeof(r600_shader));
72 pipeshader->scratch_space_needed = sh->scratch_size;
73
74 if (sh->info.stage == MESA_SHADER_TESS_EVAL || sh->info.stage == MESA_SHADER_VERTEX ||
75 sh->info.stage == MESA_SHADER_GEOMETRY) {
76 pipeshader->shader.clip_dist_write |=
77 ((1 << sh->info.clip_distance_array_size) - 1);
78 pipeshader->shader.cull_dist_write = ((1 << sh->info.cull_distance_array_size) - 1)
79 << sh->info.clip_distance_array_size;
80 pipeshader->shader.cc_dist_mask =
81 (1 << (sh->info.cull_distance_array_size + sh->info.clip_distance_array_size)) -
82 1;
83 }
84 struct r600_shader *gs_shader = nullptr;
85 if (rctx->gs_shader)
86 gs_shader = &rctx->gs_shader->current->shader;
87 r600_screen *rscreen = rctx->screen;
88
89 r600::Shader *shader =
90 r600::Shader::translate_from_nir(sh, &sel->so, gs_shader, *key,
91 rctx->isa->hw_class, rscreen->b.family);
92
93 assert(shader);
94 if (!shader)
95 return -2;
96
97 pipeshader->enabled_stream_buffers_mask = shader->enabled_stream_buffers_mask();
98 pipeshader->selector->info.file_count[TGSI_FILE_HW_ATOMIC] +=
99 shader->atomic_file_count();
100 pipeshader->selector->info.writes_memory =
101 shader->has_flag(r600::Shader::sh_writes_memory);
102
103 r600_finalize_and_optimize_shader(shader);
104
105 auto scheduled_shader = r600_schedule_shader(shader);
106 if (!scheduled_shader) {
107 return -1;
108 }
109
110 scheduled_shader->get_shader_info(&pipeshader->shader);
111 pipeshader->shader.uses_doubles = sh->info.bit_sizes_float & 64 ? 1 : 0;
112
113 r600_bytecode_init(&pipeshader->shader.bc,
114 rscreen->b.gfx_level,
115 rscreen->b.family,
116 rscreen->has_compressed_msaa_texturing);
117
118 /* We already schedule the code with this in mind, no need to handle this
119 * in the backend assembler */
120 pipeshader->shader.bc.ar_handling = AR_HANDLE_NORMAL;
121 pipeshader->shader.bc.r6xx_nop_after_rel_dst = 0;
122
123 r600::sfn_log << r600::SfnLog::shader_info << "pipeshader->shader.processor_type = "
124 << pipeshader->shader.processor_type << "\n";
125
126 pipeshader->shader.bc.type = pipeshader->shader.processor_type;
127 pipeshader->shader.bc.isa = rctx->isa;
128 pipeshader->shader.bc.ngpr = scheduled_shader->required_registers();
129
130 r600::Assembler afs(&pipeshader->shader, *key);
131 if (!afs.lower(scheduled_shader)) {
132 R600_ERR("%s: Lowering to assembly failed\n", __func__);
133
134 scheduled_shader->print(std::cerr);
135 /* For now crash if the shader could not be generated */
136 assert(0);
137 return -1;
138 }
139
140 if (sh->info.stage == MESA_SHADER_VERTEX) {
141 pipeshader->shader.vs_position_window_space =
142 sh->info.vs.window_space_position;
143 }
144
145 if (sh->info.stage == MESA_SHADER_FRAGMENT)
146 pipeshader->shader.ps_conservative_z =
147 sh->info.fs.depth_layout;
148
149 if (sh->info.stage == MESA_SHADER_GEOMETRY) {
150 r600::sfn_log << r600::SfnLog::shader_info
151 << "Geometry shader, create copy shader\n";
152 generate_gs_copy_shader(rctx, pipeshader, &sel->so);
153 assert(pipeshader->gs_copy_shader);
154 } else {
155 r600::sfn_log << r600::SfnLog::shader_info << "This is not a Geometry shader\n";
156 }
157 ralloc_free(sh);
158
159 return 0;
160 }
161