1 #include "glsl_optimizer.h"
2 #include "ast.h"
3 #include "glsl_parser_extras.h"
4 #include "glsl_parser.h"
5 #include "ir_optimization.h"
6 #include "ir_print_metal_visitor.h"
7 #include "ir_print_glsl_visitor.h"
8 #include "ir_print_visitor.h"
9 #include "ir_stats.h"
10 #include "loop_analysis.h"
11 #include "program.h"
12 #include "linker.h"
13 #include "standalone_scaffolding.h"
14
15
16 extern "C" struct gl_shader *
17 _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
18
DeleteShader(struct gl_context * ctx,struct gl_shader * shader)19 static void DeleteShader(struct gl_context *ctx, struct gl_shader *shader)
20 {
21 ralloc_free(shader);
22 }
23
24
25 static void
initialize_mesa_context(struct gl_context * ctx,glslopt_target api)26 initialize_mesa_context(struct gl_context *ctx, glslopt_target api)
27 {
28 gl_api mesaAPI;
29 switch(api)
30 {
31 default:
32 case kGlslTargetOpenGL:
33 mesaAPI = API_OPENGL_COMPAT;
34 break;
35 case kGlslTargetOpenGLES20:
36 mesaAPI = API_OPENGLES2;
37 break;
38 case kGlslTargetOpenGLES30:
39 mesaAPI = API_OPENGL_CORE;
40 break;
41 case kGlslTargetMetal:
42 mesaAPI = API_OPENGL_CORE;
43 break;
44 }
45 initialize_context_to_defaults (ctx, mesaAPI);
46
47 switch(api)
48 {
49 default:
50 case kGlslTargetOpenGL:
51 ctx->Const.GLSLVersion = 150;
52 break;
53 case kGlslTargetOpenGLES20:
54 ctx->Extensions.OES_standard_derivatives = true;
55 ctx->Extensions.EXT_shadow_samplers = true;
56 ctx->Extensions.EXT_frag_depth = true;
57 ctx->Extensions.EXT_shader_framebuffer_fetch = true;
58 break;
59 case kGlslTargetOpenGLES30:
60 ctx->Extensions.ARB_ES3_compatibility = true;
61 ctx->Extensions.EXT_shader_framebuffer_fetch = true;
62 break;
63 case kGlslTargetMetal:
64 ctx->Const.GLSLVersion = 150;
65 ctx->Extensions.ARB_ES3_compatibility = true;
66 ctx->Extensions.EXT_shader_framebuffer_fetch = true;
67 break;
68 }
69
70
71 // allow high amount of texcoords
72 ctx->Const.MaxTextureCoordUnits = 16;
73
74 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
75 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
76 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = 16;
77
78 // For GLES2.0 this would be 1, but we do support GL_EXT_draw_buffers
79 ctx->Const.MaxDrawBuffers = 8;
80
81 ctx->Driver.NewShader = _mesa_new_shader;
82 ctx->Driver.DeleteShader = DeleteShader;
83 }
84
85
86 struct glslopt_ctx {
glslopt_ctxglslopt_ctx87 glslopt_ctx (glslopt_target target) {
88 this->target = target;
89 mem_ctx = ralloc_context (NULL);
90 initialize_mesa_context (&mesa_ctx, target);
91 }
~glslopt_ctxglslopt_ctx92 ~glslopt_ctx() {
93 ralloc_free (mem_ctx);
94 }
95 struct gl_context mesa_ctx;
96 void* mem_ctx;
97 glslopt_target target;
98 };
99
glslopt_initialize(glslopt_target target)100 glslopt_ctx* glslopt_initialize (glslopt_target target)
101 {
102 return new glslopt_ctx(target);
103 }
104
glslopt_cleanup(glslopt_ctx * ctx)105 void glslopt_cleanup (glslopt_ctx* ctx)
106 {
107 delete ctx;
108 _mesa_destroy_shader_compiler();
109 }
110
glslopt_set_max_unroll_iterations(glslopt_ctx * ctx,unsigned iterations)111 void glslopt_set_max_unroll_iterations (glslopt_ctx* ctx, unsigned iterations)
112 {
113 for (int i = 0; i < MESA_SHADER_STAGES; ++i)
114 ctx->mesa_ctx.Const.ShaderCompilerOptions[i].MaxUnrollIterations = iterations;
115 }
116
117 struct glslopt_shader_var
118 {
119 const char* name;
120 glslopt_basic_type type;
121 glslopt_precision prec;
122 int vectorSize;
123 int matrixSize;
124 int arraySize;
125 int location;
126 };
127
128 struct glslopt_shader
129 {
operator newglslopt_shader130 static void* operator new(size_t size, void *ctx)
131 {
132 void *node;
133 node = ralloc_size(ctx, size);
134 assert(node != NULL);
135 return node;
136 }
operator deleteglslopt_shader137 static void operator delete(void *node)
138 {
139 ralloc_free(node);
140 }
141
glslopt_shaderglslopt_shader142 glslopt_shader ()
143 : rawOutput(0)
144 , optimizedOutput(0)
145 , status(false)
146 , uniformCount(0)
147 , uniformsSize(0)
148 , inputCount(0)
149 , textureCount(0)
150 , statsMath(0)
151 , statsTex(0)
152 , statsFlow(0)
153 {
154 infoLog = "Shader not compiled yet";
155
156 whole_program = rzalloc (NULL, struct gl_shader_program);
157 assert(whole_program != NULL);
158 whole_program->InfoLog = ralloc_strdup(whole_program, "");
159
160 whole_program->Shaders = reralloc(whole_program, whole_program->Shaders, struct gl_shader *, whole_program->NumShaders + 1);
161 assert(whole_program->Shaders != NULL);
162
163 shader = rzalloc(whole_program, gl_shader);
164 whole_program->Shaders[whole_program->NumShaders] = shader;
165 whole_program->NumShaders++;
166
167 whole_program->LinkStatus = true;
168 }
169
~glslopt_shaderglslopt_shader170 ~glslopt_shader()
171 {
172 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++)
173 ralloc_free(whole_program->_LinkedShaders[i]);
174 for(GLuint i =0;i< whole_program->NumShaders;i++)
175 ralloc_free(whole_program->Shaders[i]);
176 ralloc_free(whole_program->Shaders);
177 ralloc_free(whole_program->InfoLog);
178 ralloc_free(whole_program);
179 ralloc_free(rawOutput);
180 ralloc_free(optimizedOutput);
181 }
182
183 struct gl_shader_program* whole_program;
184 struct gl_shader* shader;
185
186 static const int kMaxShaderUniforms = 1024;
187 static const int kMaxShaderInputs = 128;
188 static const int kMaxShaderTextures = 128;
189 glslopt_shader_var uniforms[kMaxShaderUniforms];
190 glslopt_shader_var inputs[kMaxShaderInputs];
191 glslopt_shader_var textures[kMaxShaderInputs];
192 int uniformCount, uniformsSize;
193 int inputCount;
194 int textureCount;
195 int statsMath, statsTex, statsFlow;
196
197 char* rawOutput;
198 char* optimizedOutput;
199 const char* infoLog;
200 bool status;
201 };
202
debug_print_ir(const char * name,exec_list * ir,_mesa_glsl_parse_state * state,void * memctx)203 static inline void debug_print_ir (const char* name, exec_list* ir, _mesa_glsl_parse_state* state, void* memctx)
204 {
205 #if 0
206 printf("**** %s:\n", name);
207 // _mesa_print_ir (ir, state);
208 char* foobar = _mesa_print_ir_glsl(ir, state, ralloc_strdup(memctx, ""), kPrintGlslFragment);
209 printf("%s\n", foobar);
210 validate_ir_tree(ir);
211 #endif
212 }
213
214
215 struct precision_ctx
216 {
217 exec_list* root_ir;
218 bool res;
219 };
220
221
propagate_precision_deref(ir_instruction * ir,void * data)222 static void propagate_precision_deref(ir_instruction *ir, void *data)
223 {
224 // variable deref with undefined precision: take from variable itself
225 ir_dereference_variable* der = ir->as_dereference_variable();
226 if (der && der->get_precision() == glsl_precision_undefined && der->var->data.precision != glsl_precision_undefined)
227 {
228 der->set_precision ((glsl_precision)der->var->data.precision);
229 ((precision_ctx*)data)->res = true;
230 }
231
232 // array deref with undefined precision: take from array itself
233 ir_dereference_array* der_arr = ir->as_dereference_array();
234 if (der_arr && der_arr->get_precision() == glsl_precision_undefined && der_arr->array->get_precision() != glsl_precision_undefined)
235 {
236 der_arr->set_precision (der_arr->array->get_precision());
237 ((precision_ctx*)data)->res = true;
238 }
239
240 // swizzle with undefined precision: take from swizzle argument
241 ir_swizzle* swz = ir->as_swizzle();
242 if (swz && swz->get_precision() == glsl_precision_undefined && swz->val->get_precision() != glsl_precision_undefined)
243 {
244 swz->set_precision (swz->val->get_precision());
245 ((precision_ctx*)data)->res = true;
246 }
247
248 }
249
propagate_precision_expr(ir_instruction * ir,void * data)250 static void propagate_precision_expr(ir_instruction *ir, void *data)
251 {
252 ir_expression* expr = ir->as_expression();
253 if (!expr)
254 return;
255 if (expr->get_precision() != glsl_precision_undefined)
256 return;
257
258 glsl_precision prec_params_max = glsl_precision_undefined;
259 for (int i = 0; i < (int)expr->get_num_operands(); ++i)
260 {
261 ir_rvalue* op = expr->operands[i];
262 if (op && op->get_precision() != glsl_precision_undefined)
263 prec_params_max = higher_precision (prec_params_max, op->get_precision());
264 }
265 if (expr->get_precision() != prec_params_max)
266 {
267 expr->set_precision (prec_params_max);
268 ((precision_ctx*)data)->res = true;
269 }
270
271 }
272
propagate_precision_texture(ir_instruction * ir,void * data)273 static void propagate_precision_texture(ir_instruction *ir, void *data)
274 {
275 ir_texture* tex = ir->as_texture();
276 if (!tex)
277 return;
278
279 glsl_precision sampler_prec = tex->sampler->get_precision();
280 if (tex->get_precision() == sampler_prec || sampler_prec == glsl_precision_undefined)
281 return;
282
283 // set precision of ir_texture node to that of the sampler itself
284 tex->set_precision(sampler_prec);
285 ((precision_ctx*)data)->res = true;
286 }
287
propagate_precision_texture_metal(ir_instruction * ir,void * data)288 static void propagate_precision_texture_metal(ir_instruction* ir, void* data)
289 {
290 // There are no precision specifiers in Metal
291 ir_texture* tex = ir->as_texture();
292 if (tex)
293 tex->set_precision(glsl_precision_undefined);
294 }
295
296 struct undefined_ass_ctx
297 {
298 ir_variable* var;
299 bool res;
300 };
301
has_only_undefined_precision_assignments(ir_instruction * ir,void * data)302 static void has_only_undefined_precision_assignments(ir_instruction *ir, void *data)
303 {
304 ir_assignment* ass = ir->as_assignment();
305 if (!ass)
306 return;
307 undefined_ass_ctx* ctx = (undefined_ass_ctx*)data;
308 if (ass->whole_variable_written() != ctx->var)
309 return;
310 glsl_precision prec = ass->rhs->get_precision();
311 if (prec == glsl_precision_undefined)
312 return;
313 ctx->res = false;
314 }
315
316
propagate_precision_assign(ir_instruction * ir,void * data)317 static void propagate_precision_assign(ir_instruction *ir, void *data)
318 {
319 ir_assignment* ass = ir->as_assignment();
320 if (!ass || !ass->lhs || !ass->rhs)
321 return;
322
323 glsl_precision lp = ass->lhs->get_precision();
324 glsl_precision rp = ass->rhs->get_precision();
325
326 // for assignments with LHS having undefined precision, take it from RHS
327 if (rp != glsl_precision_undefined)
328 {
329 ir_variable* lhs_var = ass->lhs->variable_referenced();
330 if (lp == glsl_precision_undefined)
331 {
332 if (lhs_var)
333 lhs_var->data.precision = rp;
334 ass->lhs->set_precision (rp);
335 ((precision_ctx*)data)->res = true;
336 }
337 return;
338 }
339
340 // for assignments where LHS has precision, but RHS is a temporary variable
341 // with undefined precision that's only assigned from other undefined precision
342 // sources -> make the RHS variable take LHS precision
343 if (lp != glsl_precision_undefined && rp == glsl_precision_undefined)
344 {
345 ir_dereference* deref = ass->rhs->as_dereference();
346 if (deref)
347 {
348 ir_variable* rhs_var = deref->variable_referenced();
349 if (rhs_var && rhs_var->data.mode == ir_var_temporary && rhs_var->data.precision == glsl_precision_undefined)
350 {
351 undefined_ass_ctx ctx;
352 ctx.var = rhs_var;
353 // find if we only assign to it from undefined precision sources
354 ctx.res = true;
355 exec_list* root_ir = ((precision_ctx*)data)->root_ir;
356 foreach_in_list(ir_instruction, inst, root_ir)
357 {
358 visit_tree (ir, has_only_undefined_precision_assignments, &ctx);
359 }
360 if (ctx.res)
361 {
362 rhs_var->data.precision = lp;
363 ass->rhs->set_precision(lp);
364 ((precision_ctx*)data)->res = true;
365 }
366 }
367 }
368 return;
369 }
370 }
371
372
propagate_precision_call(ir_instruction * ir,void * data)373 static void propagate_precision_call(ir_instruction *ir, void *data)
374 {
375 ir_call* call = ir->as_call();
376 if (!call)
377 return;
378 if (!call->return_deref)
379 return;
380 if (call->return_deref->get_precision() == glsl_precision_undefined /*&& call->callee->precision == glsl_precision_undefined*/)
381 {
382 glsl_precision prec_params_max = glsl_precision_undefined;
383 foreach_two_lists(formal_node, &call->callee->parameters,
384 actual_node, &call->actual_parameters) {
385 ir_variable* sig_param = (ir_variable*)formal_node;
386 ir_rvalue* param = (ir_rvalue*)actual_node;
387
388 glsl_precision p = (glsl_precision)sig_param->data.precision;
389 if (p == glsl_precision_undefined)
390 p = param->get_precision();
391
392 prec_params_max = higher_precision (prec_params_max, p);
393 }
394 if (call->return_deref->get_precision() != prec_params_max)
395 {
396 call->return_deref->set_precision (prec_params_max);
397 ((precision_ctx*)data)->res = true;
398 }
399 }
400 }
401
propagate_precision(exec_list * list,bool metal_target)402 static bool propagate_precision(exec_list* list, bool metal_target)
403 {
404 bool anyProgress = false;
405 precision_ctx ctx;
406
407 do {
408 ctx.res = false;
409 ctx.root_ir = list;
410 foreach_in_list(ir_instruction, ir, list)
411 {
412 if (metal_target)
413 visit_tree (ir, propagate_precision_texture_metal, &ctx);
414 else
415 visit_tree (ir, propagate_precision_texture, &ctx);
416
417 visit_tree (ir, propagate_precision_deref, &ctx);
418 bool hadProgress = ctx.res;
419 ctx.res = false;
420 visit_tree (ir, propagate_precision_assign, &ctx);
421 if (ctx.res)
422 {
423 // assignment precision propagation might have added precision
424 // to some variables; need to propagate dereference precision right
425 // after that too.
426 visit_tree (ir, propagate_precision_deref, &ctx);
427 }
428 ctx.res |= hadProgress;
429 visit_tree (ir, propagate_precision_call, &ctx);
430 visit_tree (ir, propagate_precision_expr, &ctx);
431 }
432 anyProgress |= ctx.res;
433 } while (ctx.res);
434 anyProgress |= ctx.res;
435
436 // for globals that have undefined precision, set it to highp
437 if (metal_target)
438 {
439 foreach_in_list(ir_instruction, ir, list)
440 {
441 ir_variable* var = ir->as_variable();
442 if (var)
443 {
444 if (var->data.precision == glsl_precision_undefined)
445 {
446 var->data.precision = glsl_precision_high;
447 anyProgress = true;
448 }
449 }
450 }
451 }
452
453 return anyProgress;
454 }
455
456
do_optimization_passes(exec_list * ir,bool linked,_mesa_glsl_parse_state * state,void * mem_ctx)457 static void do_optimization_passes(exec_list* ir, bool linked, _mesa_glsl_parse_state* state, void* mem_ctx)
458 {
459 bool progress;
460 // FIXME: Shouldn't need to bound the number of passes
461 int passes = 0,
462 kMaximumPasses = 1000;
463 do {
464 progress = false;
465 ++passes;
466 bool progress2;
467 debug_print_ir ("Initial", ir, state, mem_ctx);
468 if (linked) {
469 progress2 = do_function_inlining(ir); progress |= progress2; if (progress2) debug_print_ir ("After inlining", ir, state, mem_ctx);
470 progress2 = do_dead_functions(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead functions", ir, state, mem_ctx);
471 progress2 = do_structure_splitting(ir); progress |= progress2; if (progress2) debug_print_ir ("After struct splitting", ir, state, mem_ctx);
472 }
473 progress2 = do_if_simplification(ir); progress |= progress2; if (progress2) debug_print_ir ("After if simpl", ir, state, mem_ctx);
474 progress2 = opt_flatten_nested_if_blocks(ir); progress |= progress2; if (progress2) debug_print_ir ("After if flatten", ir, state, mem_ctx);
475 progress2 = propagate_precision (ir, state->metal_target); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, mem_ctx);
476 progress2 = do_copy_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation", ir, state, mem_ctx);
477 progress2 = do_copy_propagation_elements(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation elems", ir, state, mem_ctx);
478
479 if (linked)
480 {
481 progress2 = do_vectorize(ir); progress |= progress2; if (progress2) debug_print_ir ("After vectorize", ir, state, mem_ctx);
482 }
483 if (linked) {
484 progress2 = do_dead_code(ir,false); progress |= progress2; if (progress2) debug_print_ir ("After dead code", ir, state, mem_ctx);
485 } else {
486 progress2 = do_dead_code_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code unlinked", ir, state, mem_ctx);
487 }
488 progress2 = do_dead_code_local(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code local", ir, state, mem_ctx);
489 progress2 = propagate_precision (ir, state->metal_target); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, mem_ctx);
490 progress2 = do_tree_grafting(ir); progress |= progress2; if (progress2) debug_print_ir ("After tree grafting", ir, state, mem_ctx);
491 progress2 = do_constant_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After const propagation", ir, state, mem_ctx);
492 if (linked) {
493 progress2 = do_constant_variable(ir); progress |= progress2; if (progress2) debug_print_ir ("After const variable", ir, state, mem_ctx);
494 } else {
495 progress2 = do_constant_variable_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After const variable unlinked", ir, state, mem_ctx);
496 }
497 progress2 = do_constant_folding(ir); progress |= progress2; if (progress2) debug_print_ir ("After const folding", ir, state, mem_ctx);
498 progress2 = do_minmax_prune(ir); progress |= progress2; if (progress2) debug_print_ir ("After minmax prune", ir, state, mem_ctx);
499 progress2 = do_cse(ir); progress |= progress2; if (progress2) debug_print_ir ("After CSE", ir, state, mem_ctx);
500 progress2 = do_rebalance_tree(ir); progress |= progress2; if (progress2) debug_print_ir ("After rebalance tree", ir, state, mem_ctx);
501 progress2 = do_algebraic(ir, state->ctx->Const.NativeIntegers, &state->ctx->Const.ShaderCompilerOptions[state->stage]); progress |= progress2; if (progress2) debug_print_ir ("After algebraic", ir, state, mem_ctx);
502 progress2 = do_lower_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After lower jumps", ir, state, mem_ctx);
503 progress2 = do_vec_index_to_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After vec index to swizzle", ir, state, mem_ctx);
504 progress2 = lower_vector_insert(ir, false); progress |= progress2; if (progress2) debug_print_ir ("After lower vector insert", ir, state, mem_ctx);
505 progress2 = do_swizzle_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After swizzle swizzle", ir, state, mem_ctx);
506 progress2 = do_noop_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After noop swizzle", ir, state, mem_ctx);
507 progress2 = optimize_split_arrays(ir, linked, state->metal_target && state->stage == MESA_SHADER_FRAGMENT); progress |= progress2; if (progress2) debug_print_ir ("After split arrays", ir, state, mem_ctx);
508 progress2 = optimize_redundant_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After redundant jumps", ir, state, mem_ctx);
509
510 // do loop stuff only when linked; otherwise causes duplicate loop induction variable
511 // problems (ast-in.txt test)
512 if (linked)
513 {
514 loop_state *ls = analyze_loop_variables(ir);
515 if (ls->loop_found) {
516 progress2 = set_loop_controls(ir, ls); progress |= progress2; if (progress2) debug_print_ir ("After set loop", ir, state, mem_ctx);
517 progress2 = unroll_loops(ir, ls, &state->ctx->Const.ShaderCompilerOptions[state->stage]); progress |= progress2; if (progress2) debug_print_ir ("After unroll", ir, state, mem_ctx);
518 }
519 delete ls;
520 }
521 } while (progress && passes < kMaximumPasses);
522
523 if (!state->metal_target)
524 {
525 // GLSL/ES does not have saturate, so lower it
526 lower_instructions(ir, SAT_TO_CLAMP);
527 }
528 }
529
glsl_type_to_optimizer_desc(const glsl_type * type,glsl_precision prec,glslopt_shader_var * out)530 static void glsl_type_to_optimizer_desc(const glsl_type* type, glsl_precision prec, glslopt_shader_var* out)
531 {
532 out->arraySize = type->array_size();
533
534 // type; use element type when in array
535 if (type->is_array())
536 type = type->element_type();
537
538 if (type->is_float())
539 out->type = kGlslTypeFloat;
540 else if (type->is_integer())
541 out->type = kGlslTypeInt;
542 else if (type->is_boolean())
543 out->type = kGlslTypeBool;
544 else if (type->is_sampler())
545 {
546 if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D)
547 {
548 if (type->sampler_shadow)
549 out->type = kGlslTypeTex2DShadow;
550 else if (type->sampler_array)
551 out->type = kGlslTypeTex2DArray;
552 else
553 out->type = kGlslTypeTex2D;
554 }
555 else if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_3D)
556 out->type = kGlslTypeTex3D;
557 else if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE)
558 out->type = kGlslTypeTexCube;
559 else
560 out->type = kGlslTypeOther;
561 }
562 else
563 out->type = kGlslTypeOther;
564
565 // sizes
566 out->vectorSize = type->vector_elements;
567 out->matrixSize = type->matrix_columns;
568
569 // precision
570 switch (prec)
571 {
572 case glsl_precision_high: out->prec = kGlslPrecHigh; break;
573 case glsl_precision_medium: out->prec = kGlslPrecMedium; break;
574 case glsl_precision_low: out->prec = kGlslPrecLow; break;
575 default: out->prec = kGlslPrecHigh; break;
576 }
577 }
578
find_shader_variables(glslopt_shader * sh,exec_list * ir)579 static void find_shader_variables(glslopt_shader* sh, exec_list* ir)
580 {
581 foreach_in_list(ir_instruction, node, ir)
582 {
583 ir_variable* const var = node->as_variable();
584 if (var == NULL)
585 continue;
586 if (var->data.mode == ir_var_shader_in)
587 {
588 if (sh->inputCount >= glslopt_shader::kMaxShaderInputs)
589 continue;
590
591 glslopt_shader_var& v = sh->inputs[sh->inputCount];
592 v.name = ralloc_strdup(sh, var->name);
593 glsl_type_to_optimizer_desc(var->type, (glsl_precision)var->data.precision, &v);
594 v.location = var->data.explicit_location ? var->data.location : -1;
595 ++sh->inputCount;
596 }
597 if (var->data.mode == ir_var_uniform && !var->type->is_sampler())
598 {
599 if (sh->uniformCount >= glslopt_shader::kMaxShaderUniforms)
600 continue;
601
602 glslopt_shader_var& v = sh->uniforms[sh->uniformCount];
603 v.name = ralloc_strdup(sh, var->name);
604 glsl_type_to_optimizer_desc(var->type, (glsl_precision)var->data.precision, &v);
605 v.location = var->data.explicit_location ? var->data.location : -1;
606 ++sh->uniformCount;
607 }
608 if (var->data.mode == ir_var_uniform && var->type->is_sampler())
609 {
610 if (sh->textureCount >= glslopt_shader::kMaxShaderTextures)
611 continue;
612
613 glslopt_shader_var& v = sh->textures[sh->textureCount];
614 v.name = ralloc_strdup(sh, var->name);
615 glsl_type_to_optimizer_desc(var->type, (glsl_precision)var->data.precision, &v);
616 v.location = var->data.explicit_location ? var->data.location : -1;
617 ++sh->textureCount;
618 }
619 }
620 }
621
622
glslopt_optimize(glslopt_ctx * ctx,glslopt_shader_type type,const char * shaderSource,unsigned options)623 glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, const char* shaderSource, unsigned options)
624 {
625 glslopt_shader* shader = new (ctx->mem_ctx) glslopt_shader ();
626
627 PrintGlslMode printMode = kPrintGlslVertex;
628 switch (type) {
629 case kGlslOptShaderVertex:
630 shader->shader->Type = GL_VERTEX_SHADER;
631 shader->shader->Stage = MESA_SHADER_VERTEX;
632 printMode = kPrintGlslVertex;
633 break;
634 case kGlslOptShaderFragment:
635 shader->shader->Type = GL_FRAGMENT_SHADER;
636 shader->shader->Stage = MESA_SHADER_FRAGMENT;
637 printMode = kPrintGlslFragment;
638 break;
639 case kGlslOptShaderCompute:
640 shader->shader->Type = GL_COMPUTE_SHADER;
641 shader->shader->Stage = MESA_SHADER_COMPUTE;
642 printMode = kPrintGlslFragment;
643 break;
644
645 }
646 if (!shader->shader->Type)
647 {
648 shader->infoLog = ralloc_asprintf (shader, "Unknown shader type %d", (int)type);
649 shader->status = false;
650 return shader;
651 }
652
653 _mesa_glsl_parse_state* state = new (shader) _mesa_glsl_parse_state (&ctx->mesa_ctx, shader->shader->Stage, shader);
654 if (ctx->target == kGlslTargetMetal)
655 state->metal_target = true;
656 state->error = 0;
657
658 if (!(options & kGlslOptionSkipPreprocessor))
659 {
660 state->error = !!glcpp_preprocess (state, &shaderSource, &state->info_log, state->extensions, &ctx->mesa_ctx);
661 if (state->error)
662 {
663 shader->status = !state->error;
664 shader->infoLog = state->info_log;
665 return shader;
666 }
667 }
668
669 _mesa_glsl_lexer_ctor (state, shaderSource);
670 _mesa_glsl_parse (state);
671 _mesa_glsl_lexer_dtor (state);
672
673 exec_list* ir = new (shader) exec_list();
674 shader->shader->ir = ir;
675
676 if (!state->error && !state->translation_unit.is_empty())
677 _mesa_ast_to_hir (ir, state);
678
679 // Un-optimized output
680 if (!state->error) {
681 validate_ir_tree(ir);
682 if (ctx->target == kGlslTargetMetal)
683 shader->rawOutput = _mesa_print_ir_metal(ir, state, ralloc_strdup(shader, ""), printMode, &shader->uniformsSize);
684 else
685 shader->rawOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(shader, ""), printMode);
686 }
687
688 // Link built-in functions
689 shader->shader->symbols = state->symbols;
690 shader->shader->uses_builtin_functions = state->uses_builtin_functions;
691
692 struct gl_shader* linked_shader = NULL;
693
694 if (!state->error && !ir->is_empty() && !(options & kGlslOptionNotFullShader))
695 {
696 linked_shader = link_intrastage_shaders(shader,
697 &ctx->mesa_ctx,
698 shader->whole_program,
699 shader->whole_program->Shaders,
700 shader->whole_program->NumShaders);
701 if (!linked_shader)
702 {
703 shader->status = false;
704 shader->infoLog = shader->whole_program->InfoLog;
705 return shader;
706 }
707 ir = linked_shader->ir;
708
709 debug_print_ir ("==== After link ====", ir, state, shader);
710 }
711
712 // Do optimization post-link
713 if (!state->error && !ir->is_empty())
714 {
715 const bool linked = !(options & kGlslOptionNotFullShader);
716 do_optimization_passes(ir, linked, state, shader);
717 validate_ir_tree(ir);
718 }
719
720 // Final optimized output
721 if (!state->error)
722 {
723 if (ctx->target == kGlslTargetMetal)
724 shader->optimizedOutput = _mesa_print_ir_metal(ir, state, ralloc_strdup(shader, ""), printMode, &shader->uniformsSize);
725 else
726 shader->optimizedOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(shader, ""), printMode);
727 }
728
729 shader->status = !state->error;
730 shader->infoLog = state->info_log;
731
732 find_shader_variables (shader, ir);
733 if (!state->error)
734 calculate_shader_stats (ir, &shader->statsMath, &shader->statsTex, &shader->statsFlow);
735
736 ralloc_free (ir);
737 ralloc_free (state);
738
739 if (linked_shader)
740 ralloc_free(linked_shader);
741
742 return shader;
743 }
744
glslopt_shader_delete(glslopt_shader * shader)745 void glslopt_shader_delete (glslopt_shader* shader)
746 {
747 delete shader;
748 }
749
glslopt_get_status(glslopt_shader * shader)750 bool glslopt_get_status (glslopt_shader* shader)
751 {
752 return shader->status;
753 }
754
glslopt_get_output(glslopt_shader * shader)755 const char* glslopt_get_output (glslopt_shader* shader)
756 {
757 return shader->optimizedOutput;
758 }
759
glslopt_get_raw_output(glslopt_shader * shader)760 const char* glslopt_get_raw_output (glslopt_shader* shader)
761 {
762 return shader->rawOutput;
763 }
764
glslopt_get_log(glslopt_shader * shader)765 const char* glslopt_get_log (glslopt_shader* shader)
766 {
767 return shader->infoLog;
768 }
769
glslopt_shader_get_input_count(glslopt_shader * shader)770 int glslopt_shader_get_input_count (glslopt_shader* shader)
771 {
772 return shader->inputCount;
773 }
774
glslopt_shader_get_uniform_count(glslopt_shader * shader)775 int glslopt_shader_get_uniform_count (glslopt_shader* shader)
776 {
777 return shader->uniformCount;
778 }
779
glslopt_shader_get_uniform_total_size(glslopt_shader * shader)780 int glslopt_shader_get_uniform_total_size (glslopt_shader* shader)
781 {
782 return shader->uniformsSize;
783 }
784
glslopt_shader_get_texture_count(glslopt_shader * shader)785 int glslopt_shader_get_texture_count (glslopt_shader* shader)
786 {
787 return shader->textureCount;
788 }
789
glslopt_shader_get_input_desc(glslopt_shader * shader,int index,const char ** outName,glslopt_basic_type * outType,glslopt_precision * outPrec,int * outVecSize,int * outMatSize,int * outArraySize,int * outLocation)790 void glslopt_shader_get_input_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation)
791 {
792 const glslopt_shader_var& v = shader->inputs[index];
793 *outName = v.name;
794 *outType = v.type;
795 *outPrec = v.prec;
796 *outVecSize = v.vectorSize;
797 *outMatSize = v.matrixSize;
798 *outArraySize = v.arraySize;
799 *outLocation = v.location;
800 }
801
glslopt_shader_get_uniform_desc(glslopt_shader * shader,int index,const char ** outName,glslopt_basic_type * outType,glslopt_precision * outPrec,int * outVecSize,int * outMatSize,int * outArraySize,int * outLocation)802 void glslopt_shader_get_uniform_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation)
803 {
804 const glslopt_shader_var& v = shader->uniforms[index];
805 *outName = v.name;
806 *outType = v.type;
807 *outPrec = v.prec;
808 *outVecSize = v.vectorSize;
809 *outMatSize = v.matrixSize;
810 *outArraySize = v.arraySize;
811 *outLocation = v.location;
812 }
813
glslopt_shader_get_texture_desc(glslopt_shader * shader,int index,const char ** outName,glslopt_basic_type * outType,glslopt_precision * outPrec,int * outVecSize,int * outMatSize,int * outArraySize,int * outLocation)814 void glslopt_shader_get_texture_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation)
815 {
816 const glslopt_shader_var& v = shader->textures[index];
817 *outName = v.name;
818 *outType = v.type;
819 *outPrec = v.prec;
820 *outVecSize = v.vectorSize;
821 *outMatSize = v.matrixSize;
822 *outArraySize = v.arraySize;
823 *outLocation = v.location;
824 }
825
glslopt_shader_get_stats(glslopt_shader * shader,int * approxMath,int * approxTex,int * approxFlow)826 void glslopt_shader_get_stats (glslopt_shader* shader, int* approxMath, int* approxTex, int* approxFlow)
827 {
828 *approxMath = shader->statsMath;
829 *approxTex = shader->statsTex;
830 *approxFlow = shader->statsFlow;
831 }
832