1 /*
2 * Copyright 2012 Intel Corporation
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "blorp_priv.h"
7 #include "blorp_nir_builder.h"
8 #include "compiler/brw_compiler.h"
9 #include "compiler/brw_nir.h"
10 #include "dev/intel_debug.h"
11
12 static const nir_shader_compiler_options *
blorp_nir_options_brw(struct blorp_context * blorp,gl_shader_stage stage)13 blorp_nir_options_brw(struct blorp_context *blorp,
14 gl_shader_stage stage)
15 {
16 const struct brw_compiler *compiler = blorp->compiler->brw;
17 return compiler->nir_options[stage];
18 }
19
20 static struct blorp_program
blorp_compile_fs_brw(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir,bool multisample_fbo,bool use_repclear)21 blorp_compile_fs_brw(struct blorp_context *blorp, void *mem_ctx,
22 struct nir_shader *nir,
23 bool multisample_fbo,
24 bool use_repclear)
25 {
26 const struct brw_compiler *compiler = blorp->compiler->brw;
27
28 struct brw_wm_prog_data *wm_prog_data = rzalloc(mem_ctx, struct brw_wm_prog_data);
29 wm_prog_data->base.nr_params = 0;
30 wm_prog_data->base.param = NULL;
31
32 struct brw_nir_compiler_opts opts = {};
33 brw_preprocess_nir(compiler, nir, &opts);
34 nir_remove_dead_variables(nir, nir_var_shader_in, NULL);
35 nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
36
37 struct brw_wm_prog_key wm_key;
38 memset(&wm_key, 0, sizeof(wm_key));
39 wm_key.multisample_fbo = multisample_fbo ? BRW_ALWAYS : BRW_NEVER;
40 wm_key.nr_color_regions = 1;
41
42 struct brw_compile_fs_params params = {
43 .base = {
44 .mem_ctx = mem_ctx,
45 .nir = nir,
46 .log_data = blorp->driver_ctx,
47 .debug_flag = DEBUG_BLORP,
48 },
49 .key = &wm_key,
50 .prog_data = wm_prog_data,
51
52 .use_rep_send = use_repclear,
53 .max_polygons = 1,
54 };
55
56 const unsigned *kernel = brw_compile_fs(compiler, ¶ms);
57 return (struct blorp_program){
58 .kernel = kernel,
59 .kernel_size = wm_prog_data->base.program_size,
60 .prog_data = wm_prog_data,
61 .prog_data_size = sizeof(*wm_prog_data),
62 };
63 }
64
65 static struct blorp_program
blorp_compile_vs_brw(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir)66 blorp_compile_vs_brw(struct blorp_context *blorp, void *mem_ctx,
67 struct nir_shader *nir)
68 {
69 const struct brw_compiler *compiler = blorp->compiler->brw;
70
71 struct brw_nir_compiler_opts opts = {};
72 brw_preprocess_nir(compiler, nir, &opts);
73 nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
74
75 struct brw_vs_prog_data *vs_prog_data = rzalloc(mem_ctx, struct brw_vs_prog_data);
76 vs_prog_data->inputs_read = nir->info.inputs_read;
77
78 brw_compute_vue_map(compiler->devinfo,
79 &vs_prog_data->base.vue_map,
80 nir->info.outputs_written,
81 nir->info.separate_shader,
82 1);
83
84 struct brw_vs_prog_key vs_key = { 0, };
85
86 struct brw_compile_vs_params params = {
87 .base = {
88 .mem_ctx = mem_ctx,
89 .nir = nir,
90 .log_data = blorp->driver_ctx,
91 .debug_flag = DEBUG_BLORP,
92 },
93 .key = &vs_key,
94 .prog_data = vs_prog_data,
95 };
96
97 const unsigned *kernel = brw_compile_vs(compiler, ¶ms);
98 return (struct blorp_program) {
99 .kernel = kernel,
100 .kernel_size = vs_prog_data->base.base.program_size,
101 .prog_data = vs_prog_data,
102 .prog_data_size = sizeof(*vs_prog_data),
103 };
104 }
105
106 static bool
lower_base_workgroup_id(nir_builder * b,nir_intrinsic_instr * intrin,UNUSED void * data)107 lower_base_workgroup_id(nir_builder *b, nir_intrinsic_instr *intrin,
108 UNUSED void *data)
109 {
110 if (intrin->intrinsic != nir_intrinsic_load_base_workgroup_id)
111 return false;
112
113 b->cursor = nir_instr_remove(&intrin->instr);
114 nir_def_rewrite_uses(&intrin->def, nir_imm_zero(b, 3, 32));
115 return true;
116 }
117
118 static struct blorp_program
blorp_compile_cs_brw(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir)119 blorp_compile_cs_brw(struct blorp_context *blorp, void *mem_ctx,
120 struct nir_shader *nir)
121 {
122 const struct brw_compiler *compiler = blorp->compiler->brw;
123
124 struct brw_nir_compiler_opts opts = {};
125 brw_preprocess_nir(compiler, nir, &opts);
126 nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
127
128 NIR_PASS_V(nir, nir_lower_io, nir_var_uniform, type_size_scalar_bytes,
129 (nir_lower_io_options)0);
130
131 STATIC_ASSERT(offsetof(struct blorp_wm_inputs, subgroup_id) + 4 ==
132 sizeof(struct blorp_wm_inputs));
133 nir->num_uniforms = offsetof(struct blorp_wm_inputs, subgroup_id);
134 unsigned nr_params = nir->num_uniforms / 4;
135
136 struct brw_cs_prog_data *cs_prog_data = rzalloc(mem_ctx, struct brw_cs_prog_data);
137 cs_prog_data->base.nr_params = nr_params;
138 cs_prog_data->base.param = rzalloc_array(NULL, uint32_t, nr_params);
139
140 NIR_PASS_V(nir, brw_nir_lower_cs_intrinsics, compiler->devinfo,
141 cs_prog_data);
142 NIR_PASS_V(nir, nir_shader_intrinsics_pass, lower_base_workgroup_id,
143 nir_metadata_control_flow, NULL);
144
145 struct brw_cs_prog_key cs_key;
146 memset(&cs_key, 0, sizeof(cs_key));
147
148 struct brw_compile_cs_params params = {
149 .base = {
150 .mem_ctx = mem_ctx,
151 .nir = nir,
152 .log_data = blorp->driver_ctx,
153 .debug_flag = DEBUG_BLORP,
154 },
155 .key = &cs_key,
156 .prog_data = cs_prog_data,
157 };
158
159 const unsigned *kernel = brw_compile_cs(compiler, ¶ms);
160
161 ralloc_free(cs_prog_data->base.param);
162 cs_prog_data->base.param = NULL;
163
164 return (struct blorp_program) {
165 .kernel = kernel,
166 .kernel_size = cs_prog_data->base.program_size,
167 .prog_data = cs_prog_data,
168 .prog_data_size = sizeof(*cs_prog_data),
169 };
170 }
171
172 #pragma pack(push, 1)
173 struct layer_offset_vs_key {
174 struct blorp_base_key base;
175 unsigned num_inputs;
176 };
177 #pragma pack(pop)
178
179 /* In the case of doing attachment clears, we are using a surface state that
180 * is handed to us so we can't set (and don't even know) the base array layer.
181 * In order to do a layered clear in this scenario, we need some way of adding
182 * the base array layer to the instance id. Unfortunately, our hardware has
183 * no real concept of "base instance", so we have to do it manually in a
184 * vertex shader.
185 */
186 static bool
blorp_params_get_layer_offset_vs_brw(struct blorp_batch * batch,struct blorp_params * params)187 blorp_params_get_layer_offset_vs_brw(struct blorp_batch *batch,
188 struct blorp_params *params)
189 {
190 struct blorp_context *blorp = batch->blorp;
191 struct layer_offset_vs_key blorp_key = {
192 .base = BLORP_BASE_KEY_INIT(BLORP_SHADER_TYPE_LAYER_OFFSET_VS),
193 };
194
195 struct brw_wm_prog_data *wm_prog_data = params->wm_prog_data;
196 if (wm_prog_data)
197 blorp_key.num_inputs = wm_prog_data->num_varying_inputs;
198
199 if (blorp->lookup_shader(batch, &blorp_key, sizeof(blorp_key),
200 ¶ms->vs_prog_kernel, ¶ms->vs_prog_data))
201 return true;
202
203 void *mem_ctx = ralloc_context(NULL);
204
205 nir_builder b;
206 blorp_nir_init_shader(&b, blorp, mem_ctx, MESA_SHADER_VERTEX,
207 blorp_shader_type_to_name(blorp_key.base.shader_type));
208
209 const struct glsl_type *uvec4_type = glsl_vector_type(GLSL_TYPE_UINT, 4);
210
211 /* First we deal with the header which has instance and base instance */
212 nir_variable *a_header = nir_variable_create(b.shader, nir_var_shader_in,
213 uvec4_type, "header");
214 a_header->data.location = VERT_ATTRIB_GENERIC0;
215
216 nir_variable *v_layer = nir_variable_create(b.shader, nir_var_shader_out,
217 glsl_int_type(), "layer_id");
218 v_layer->data.location = VARYING_SLOT_LAYER;
219
220 /* Compute the layer id */
221 nir_def *header = nir_load_var(&b, a_header);
222 nir_def *base_layer = nir_channel(&b, header, 0);
223 nir_def *instance = nir_channel(&b, header, 1);
224 nir_store_var(&b, v_layer, nir_iadd(&b, instance, base_layer), 0x1);
225
226 /* Then we copy the vertex from the next slot to VARYING_SLOT_POS */
227 nir_variable *a_vertex = nir_variable_create(b.shader, nir_var_shader_in,
228 glsl_vec4_type(), "a_vertex");
229 a_vertex->data.location = VERT_ATTRIB_GENERIC1;
230
231 nir_variable *v_pos = nir_variable_create(b.shader, nir_var_shader_out,
232 glsl_vec4_type(), "v_pos");
233 v_pos->data.location = VARYING_SLOT_POS;
234
235 nir_copy_var(&b, v_pos, a_vertex);
236
237 /* Then we copy everything else */
238 for (unsigned i = 0; i < blorp_key.num_inputs; i++) {
239 nir_variable *a_in = nir_variable_create(b.shader, nir_var_shader_in,
240 uvec4_type, "input");
241 a_in->data.location = VERT_ATTRIB_GENERIC2 + i;
242
243 nir_variable *v_out = nir_variable_create(b.shader, nir_var_shader_out,
244 uvec4_type, "output");
245 v_out->data.location = VARYING_SLOT_VAR0 + i;
246
247 nir_copy_var(&b, v_out, a_in);
248 }
249
250 const struct blorp_program p =
251 blorp_compile_vs(blorp, mem_ctx, b.shader);
252
253 bool result =
254 blorp->upload_shader(batch, MESA_SHADER_VERTEX,
255 &blorp_key, sizeof(blorp_key),
256 p.kernel, p.kernel_size,
257 p.prog_data, p.prog_data_size,
258 ¶ms->vs_prog_kernel, ¶ms->vs_prog_data);
259
260 ralloc_free(mem_ctx);
261 return result;
262 }
263
264 void
blorp_init_brw(struct blorp_context * blorp,void * driver_ctx,struct isl_device * isl_dev,const struct brw_compiler * brw,const struct blorp_config * config)265 blorp_init_brw(struct blorp_context *blorp, void *driver_ctx,
266 struct isl_device *isl_dev, const struct brw_compiler *brw,
267 const struct blorp_config *config)
268 {
269 blorp_init(blorp, driver_ctx, isl_dev, config);
270 assert(brw);
271
272 blorp->compiler->brw = brw;
273 blorp->compiler->nir_options = blorp_nir_options_brw;
274 blorp->compiler->compile_fs = blorp_compile_fs_brw;
275 blorp->compiler->compile_vs = blorp_compile_vs_brw;
276 blorp->compiler->compile_cs = blorp_compile_cs_brw;
277 blorp->compiler->params_get_layer_offset_vs =
278 blorp_params_get_layer_offset_vs_brw;
279 }
280