mesa/glsl: stop using GL shader type internally
[mesa.git] / src / mesa / state_tracker / st_glsl_to_nir.cpp
1 /*
2 * Copyright © 2015 Red Hat
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "st_nir.h"
25
26 #include "pipe/p_defines.h"
27 #include "pipe/p_screen.h"
28 #include "pipe/p_context.h"
29
30 #include "program/program.h"
31 #include "program/prog_statevars.h"
32 #include "program/prog_parameter.h"
33 #include "program/ir_to_mesa.h"
34 #include "program/hash_table.h"
35 #include "main/mtypes.h"
36 #include "main/errors.h"
37 #include "main/shaderapi.h"
38 #include "main/uniforms.h"
39
40 #include "st_context.h"
41 #include "st_program.h"
42 #include "st_glsl_types.h"
43
44 #include "compiler/nir/nir.h"
45 #include "compiler/glsl_types.h"
46 #include "compiler/glsl/glsl_to_nir.h"
47 #include "compiler/glsl/ir.h"
48
49
50 /* Depending on PIPE_CAP_TGSI_TEXCOORD (st->needs_texcoord_semantic) we
51 * may need to fix up varying slots so the glsl->nir path is aligned
52 * with the anything->tgsi->nir path.
53 */
54 static void
55 st_nir_fixup_varying_slots(struct st_context *st, struct exec_list *var_list)
56 {
57 if (st->needs_texcoord_semantic)
58 return;
59
60 nir_foreach_variable(var, var_list) {
61 if (var->data.location >= VARYING_SLOT_VAR0) {
62 var->data.location += 9;
63 } else if ((var->data.location >= VARYING_SLOT_TEX0) &&
64 (var->data.location <= VARYING_SLOT_TEX7)) {
65 var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0;
66 }
67 }
68 }
69
70 /* input location assignment for VS inputs must be handled specially, so
71 * that it is aligned w/ st's vbo state.
72 * (This isn't the case with, for ex, FS inputs, which only need to agree
73 * on varying-slot w/ the VS outputs)
74 */
75 static void
76 st_nir_assign_vs_in_locations(struct gl_program *prog,
77 struct exec_list *var_list, unsigned *size)
78 {
79 unsigned attr, num_inputs = 0;
80 unsigned input_to_index[VERT_ATTRIB_MAX] = {0};
81
82 /* TODO de-duplicate w/ similar code in st_translate_vertex_program()? */
83 for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
84 if ((prog->InputsRead & BITFIELD64_BIT(attr)) != 0) {
85 input_to_index[attr] = num_inputs;
86 num_inputs++;
87 if ((prog->DoubleInputsRead & BITFIELD64_BIT(attr)) != 0) {
88 /* add placeholder for second part of a double attribute */
89 num_inputs++;
90 }
91 }
92 }
93
94 *size = 0;
95 nir_foreach_variable(var, var_list) {
96 attr = var->data.location;
97 assert(attr < ARRAY_SIZE(input_to_index));
98 var->data.driver_location = input_to_index[attr];
99 (*size)++;
100 }
101 }
102
103 static int
104 st_nir_lookup_parameter_index(const struct gl_program_parameter_list *params,
105 const char *name)
106 {
107 int loc = _mesa_lookup_parameter_index(params, name);
108
109 /* is there a better way to do this? If we have something like:
110 *
111 * struct S {
112 * float f;
113 * vec4 v;
114 * };
115 * uniform S color;
116 *
117 * Then what we get in prog->Parameters looks like:
118 *
119 * 0: Name=color.f, Type=6, DataType=1406, Size=1
120 * 1: Name=color.v, Type=6, DataType=8b52, Size=4
121 *
122 * So the name doesn't match up and _mesa_lookup_parameter_index()
123 * fails. In this case just find the first matching "color.*"..
124 *
125 * Note for arrays you could end up w/ color[n].f, for example.
126 *
127 * glsl_to_tgsi works slightly differently in this regard. It is
128 * emitting something more low level, so it just translates the
129 * params list 1:1 to CONST[] regs. Going from GLSL IR to TGSI,
130 * it just calculates the additional offset of struct field members
131 * in glsl_to_tgsi_visitor::visit(ir_dereference_record *ir) or
132 * glsl_to_tgsi_visitor::visit(ir_dereference_array *ir). It never
133 * needs to work backwards to get base var loc from the param-list
134 * which already has them separated out.
135 */
136 if (loc < 0) {
137 int namelen = strlen(name);
138 for (unsigned i = 0; i < params->NumParameters; i++) {
139 struct gl_program_parameter *p = &params->Parameters[i];
140 if ((strncmp(p->Name, name, namelen) == 0) &&
141 ((p->Name[namelen] == '.') || (p->Name[namelen] == '['))) {
142 loc = i;
143 break;
144 }
145 }
146 }
147
148 return loc;
149 }
150
151 static void
152 st_nir_assign_uniform_locations(struct gl_program *prog,
153 struct gl_shader_program *shader_program,
154 struct exec_list *uniform_list, unsigned *size)
155 {
156 int max = 0;
157 int shaderidx = 0;
158
159 nir_foreach_variable(uniform, uniform_list) {
160 int loc;
161
162 /*
163 * UBO's have their own address spaces, so don't count them towards the
164 * number of global uniforms
165 */
166 if ((uniform->data.mode == nir_var_uniform || uniform->data.mode == nir_var_shader_storage) &&
167 uniform->interface_type != NULL)
168 continue;
169
170 if (uniform->type->is_sampler()) {
171 unsigned val;
172 bool found = shader_program->UniformHash->get(val, uniform->name);
173 loc = shaderidx++;
174 assert(found);
175 /* this ensure that nir_lower_samplers looks at the correct
176 * shader_program->UniformStorage[location]:
177 */
178 uniform->data.location = val;
179 } else if (strncmp(uniform->name, "gl_", 3) == 0) {
180 const gl_state_index *const stateTokens = (gl_state_index *)uniform->state_slots[0].tokens;
181 /* This state reference has already been setup by ir_to_mesa, but we'll
182 * get the same index back here.
183 */
184 loc = _mesa_add_state_reference(prog->Parameters, stateTokens);
185 } else {
186 loc = st_nir_lookup_parameter_index(prog->Parameters, uniform->name);
187 }
188
189 uniform->data.driver_location = loc;
190
191 max = MAX2(max, loc + st_glsl_type_size(uniform->type));
192 }
193 *size = max;
194 }
195
196 extern "C" {
197
198 /* First half of converting glsl_to_nir.. this leaves things in a pre-
199 * nir_lower_io state, so that shader variants can more easily insert/
200 * replace variables, etc.
201 */
202 nir_shader *
203 st_glsl_to_nir(struct st_context *st, struct gl_program *prog,
204 struct gl_shader_program *shader_program,
205 gl_shader_stage stage)
206 {
207 struct pipe_screen *pscreen = st->pipe->screen;
208 unsigned ptarget = st_shader_stage_to_ptarget(stage);
209 const nir_shader_compiler_options *options;
210 nir_shader *nir;
211
212 assert(pscreen->get_compiler_options); /* drivers using NIR must implement this */
213
214 options = (const nir_shader_compiler_options *)
215 pscreen->get_compiler_options(pscreen, PIPE_SHADER_IR_NIR, ptarget);
216 assert(options);
217
218 if (prog->nir)
219 return prog->nir;
220
221 nir = glsl_to_nir(shader_program, stage, options);
222 prog->nir = nir;
223
224 NIR_PASS_V(nir, nir_lower_io_to_temporaries,
225 nir_shader_get_entrypoint(nir),
226 true, true);
227 NIR_PASS_V(nir, nir_lower_global_vars_to_local);
228 NIR_PASS_V(nir, nir_split_var_copies);
229 NIR_PASS_V(nir, nir_lower_var_copies);
230 NIR_PASS_V(nir, st_nir_lower_builtin);
231
232 /* fragment shaders may need : */
233 if (stage == MESA_SHADER_FRAGMENT) {
234 static const gl_state_index wposTransformState[STATE_LENGTH] = {
235 STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM
236 };
237 nir_lower_wpos_ytransform_options wpos_options = {0};
238 struct pipe_screen *pscreen = st->pipe->screen;
239
240 memcpy(wpos_options.state_tokens, wposTransformState,
241 sizeof(wpos_options.state_tokens));
242 wpos_options.fs_coord_origin_upper_left =
243 pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT);
244 wpos_options.fs_coord_origin_lower_left =
245 pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
246 wpos_options.fs_coord_pixel_center_integer =
247 pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
248 wpos_options.fs_coord_pixel_center_half_integer =
249 pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER);
250
251 if (nir_lower_wpos_ytransform(nir, &wpos_options)) {
252 nir_validate_shader(nir);
253 _mesa_add_state_reference(prog->Parameters, wposTransformState);
254 }
255 }
256
257 if (st->ctx->_Shader->Flags & GLSL_DUMP) {
258 _mesa_log("\n");
259 _mesa_log("NIR IR for linked %s program %d:\n",
260 _mesa_shader_stage_to_string(stage),
261 shader_program->Name);
262 nir_print_shader(nir, _mesa_get_log_file());
263 _mesa_log("\n\n");
264 }
265
266 return nir;
267 }
268
269 /* TODO any better helper somewhere to sort a list? */
270
271 static void
272 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
273 {
274 nir_foreach_variable(var, var_list) {
275 if (var->data.location > new_var->data.location) {
276 exec_node_insert_node_before(&var->node, &new_var->node);
277 return;
278 }
279 }
280 exec_list_push_tail(var_list, &new_var->node);
281 }
282
283 static void
284 sort_varyings(struct exec_list *var_list)
285 {
286 struct exec_list new_list;
287 exec_list_make_empty(&new_list);
288 nir_foreach_variable_safe(var, var_list) {
289 exec_node_remove(&var->node);
290 insert_sorted(&new_list, var);
291 }
292 exec_list_move_nodes_to(&new_list, var_list);
293 }
294
295 /* Second half of preparing nir from glsl, which happens after shader
296 * variant lowering.
297 */
298 void
299 st_finalize_nir(struct st_context *st, struct gl_program *prog, nir_shader *nir)
300 {
301 NIR_PASS_V(nir, nir_split_var_copies);
302 NIR_PASS_V(nir, nir_lower_var_copies);
303 NIR_PASS_V(nir, nir_lower_io_types);
304
305 if (nir->stage == MESA_SHADER_VERTEX) {
306 /* Needs special handling so drvloc matches the vbo state: */
307 st_nir_assign_vs_in_locations(prog, &nir->inputs, &nir->num_inputs);
308 sort_varyings(&nir->outputs);
309 nir_assign_var_locations(&nir->outputs,
310 &nir->num_outputs,
311 st_glsl_type_size);
312 st_nir_fixup_varying_slots(st, &nir->outputs);
313 } else if (nir->stage == MESA_SHADER_FRAGMENT) {
314 sort_varyings(&nir->inputs);
315 nir_assign_var_locations(&nir->inputs,
316 &nir->num_inputs,
317 st_glsl_type_size);
318 st_nir_fixup_varying_slots(st, &nir->inputs);
319 nir_assign_var_locations(&nir->outputs,
320 &nir->num_outputs,
321 st_glsl_type_size);
322 } else {
323 unreachable("invalid shader type for tgsi bypass\n");
324 }
325
326 struct gl_shader_program *shader_program;
327 switch (nir->stage) {
328 case MESA_SHADER_VERTEX:
329 shader_program = ((struct st_vertex_program *)prog)->shader_program;
330 break;
331 case MESA_SHADER_FRAGMENT:
332 shader_program = ((struct st_fragment_program *)prog)->shader_program;
333 break;
334 default:
335 assert(!"should not be reached");
336 return;
337 }
338
339 st_nir_assign_uniform_locations(prog, shader_program,
340 &nir->uniforms, &nir->num_uniforms);
341
342 NIR_PASS_V(nir, nir_lower_system_values);
343 NIR_PASS_V(nir, nir_lower_io, nir_var_all, st_glsl_type_size);
344 NIR_PASS_V(nir, nir_lower_samplers, shader_program);
345 }
346
347 struct gl_program *
348 st_nir_get_mesa_program(struct gl_context *ctx,
349 struct gl_shader_program *shader_program,
350 struct gl_shader *shader)
351 {
352 struct gl_program *prog;
353 GLenum target = _mesa_shader_stage_to_program(shader->Stage);
354
355 validate_ir_tree(shader->ir);
356
357 prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name);
358 if (!prog)
359 return NULL;
360
361 prog->Parameters = _mesa_new_parameter_list();
362
363 _mesa_copy_linked_program_data(shader->Stage, shader_program, prog);
364 _mesa_generate_parameters_list_for_uniforms(shader_program, shader,
365 prog->Parameters);
366
367 /* Make a pass over the IR to add state references for any built-in
368 * uniforms that are used. This has to be done now (during linking).
369 * Code generation doesn't happen until the first time this shader is
370 * used for rendering. Waiting until then to generate the parameters is
371 * too late. At that point, the values for the built-in uniforms won't
372 * get sent to the shader.
373 */
374 foreach_in_list(ir_instruction, node, shader->ir) {
375 ir_variable *var = node->as_variable();
376
377 if ((var == NULL) || (var->data.mode != ir_var_uniform) ||
378 (strncmp(var->name, "gl_", 3) != 0))
379 continue;
380
381 const ir_state_slot *const slots = var->get_state_slots();
382 assert(slots != NULL);
383
384 for (unsigned int i = 0; i < var->get_num_state_slots(); i++) {
385 _mesa_add_state_reference(prog->Parameters,
386 (gl_state_index *) slots[i].tokens);
387 }
388 }
389
390 if (ctx->_Shader->Flags & GLSL_DUMP) {
391 _mesa_log("\n");
392 _mesa_log("GLSL IR for linked %s program %d:\n",
393 _mesa_shader_stage_to_string(shader->Stage),
394 shader_program->Name);
395 _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
396 _mesa_log("\n\n");
397 }
398
399 prog->Instructions = NULL;
400 prog->NumInstructions = 0;
401
402 do_set_program_inouts(shader->ir, prog, shader->Stage);
403
404 prog->SamplersUsed = shader->active_samplers;
405 prog->ShadowSamplers = shader->shadow_samplers;
406 _mesa_update_shader_textures_used(shader_program, prog);
407
408 _mesa_reference_program(ctx, &shader->Program, prog);
409
410 /* Avoid reallocation of the program parameter list, because the uniform
411 * storage is only associated with the original parameter list.
412 * This should be enough for Bitmap and DrawPixels constants.
413 */
414 _mesa_reserve_parameter_storage(prog->Parameters, 8);
415
416 /* This has to be done last. Any operation the can cause
417 * prog->ParameterValues to get reallocated (e.g., anything that adds a
418 * program constant) has to happen before creating this linkage.
419 */
420 _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters);
421
422 struct st_vertex_program *stvp;
423 struct st_fragment_program *stfp;
424
425 switch (shader->Stage) {
426 case MESA_SHADER_VERTEX:
427 stvp = (struct st_vertex_program *)prog;
428 stvp->shader_program = shader_program;
429 break;
430 case MESA_SHADER_FRAGMENT:
431 stfp = (struct st_fragment_program *)prog;
432 stfp->shader_program = shader_program;
433 break;
434 default:
435 assert(!"should not be reached");
436 return NULL;
437 }
438
439 return prog;
440 }
441
442 } /* extern "C" */