File: | root/firefox-clang/third_party/rust/glslopt/glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.cpp |
Warning: | line 309, column 51 Access to field 'es_shader' results in a dereference of a null pointer (loaded from variable 'state') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright © 2010 Intel Corporation | |||
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 | |||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
21 | * DEALINGS IN THE SOFTWARE. | |||
22 | */ | |||
23 | ||||
24 | #include "ir_print_glsl_visitor.h" | |||
25 | #include "ir_visitor.h" | |||
26 | #include "glsl_types.h" | |||
27 | #include "glsl_parser_extras.h" | |||
28 | #include "ir_unused_structs.h" | |||
29 | #include "loop_analysis.h" | |||
30 | #include "util/hash_table.h" | |||
31 | #include <math.h> | |||
32 | #include <limits> | |||
33 | ||||
34 | ||||
35 | static void print_type(string_buffer& buffer, const glsl_type *t, bool arraySize); | |||
36 | static void print_type_post(string_buffer& buffer, const glsl_type *t, bool arraySize); | |||
37 | ||||
38 | // FIXME: precision | |||
39 | static inline const char* get_precision_string (unsigned p) | |||
40 | { | |||
41 | switch (p) { | |||
42 | case GLSL_PRECISION_HIGH: | |||
43 | return "highp "; | |||
44 | case GLSL_PRECISION_MEDIUM: | |||
45 | return "mediump "; | |||
46 | case GLSL_PRECISION_LOW: | |||
47 | return "lowp "; | |||
48 | case GLSL_PRECISION_NONE: | |||
49 | return ""; | |||
50 | } | |||
51 | assert(!"Should not get here.")(static_cast <bool> (!"Should not get here.") ? void (0 ) : __assert_fail ("!\"Should not get here.\"", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); | |||
52 | return ""; | |||
53 | } | |||
54 | ||||
55 | static const int tex_sampler_type_count = 7; | |||
56 | // [glsl_sampler_dim] | |||
57 | static const char* tex_sampler_dim_name[tex_sampler_type_count] = { | |||
58 | "1D", "2D", "3D", "Cube", "Rect", "Buf", "2D", /* samplerExternal uses texture2D */ | |||
59 | }; | |||
60 | static int tex_sampler_dim_size[tex_sampler_type_count] = { | |||
61 | 1, 2, 3, 3, 2, 2, 2, | |||
62 | }; | |||
63 | ||||
64 | struct ga_entry : public exec_node | |||
65 | { | |||
66 | ga_entry(ir_instruction* ir) | |||
67 | { | |||
68 | assert(ir)(static_cast <bool> (ir) ? void (0) : __assert_fail ("ir" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | |||
69 | this->ir = ir; | |||
70 | } | |||
71 | ir_instruction* ir; | |||
72 | }; | |||
73 | ||||
74 | ||||
75 | struct global_print_tracker { | |||
76 | global_print_tracker () { | |||
77 | mem_ctx = ralloc_context(0); | |||
78 | var_counter = 0; | |||
79 | var_hash = _mesa_hash_table_create(nullptr, _mesa_hash_pointer, _mesa_key_pointer_equal); | |||
80 | main_function_done = false; | |||
81 | } | |||
82 | ||||
83 | ~global_print_tracker() { | |||
84 | _mesa_hash_table_destroy (var_hash, nullptr); | |||
85 | ralloc_free(mem_ctx); | |||
86 | } | |||
87 | ||||
88 | unsigned var_counter; | |||
89 | hash_table* var_hash; | |||
90 | exec_list global_assignements; | |||
91 | void* mem_ctx; | |||
92 | bool main_function_done; | |||
93 | }; | |||
94 | ||||
95 | class ir_print_glsl_visitor : public ir_visitor { | |||
96 | public: | |||
97 | ir_print_glsl_visitor(string_buffer& buf, global_print_tracker* globals_, PrintGlslMode mode_, bool use_precision_, const _mesa_glsl_parse_state* state_) | |||
98 | : buffer(buf) | |||
99 | , loopstate(NULL__null) | |||
100 | , inside_loop_body(false) | |||
101 | , skipped_this_ir(false) | |||
102 | , previous_skipped(false) | |||
103 | , uses_texlod_impl(0) | |||
104 | , uses_texlodproj_impl(0) | |||
105 | { | |||
106 | indentation = 0; | |||
107 | expression_depth = 0; | |||
108 | globals = globals_; | |||
109 | mode = mode_; | |||
110 | use_precision = use_precision_; | |||
111 | state = state_; | |||
112 | } | |||
113 | ||||
114 | virtual ~ir_print_glsl_visitor() | |||
115 | { | |||
116 | } | |||
117 | ||||
118 | ||||
119 | void indent(void); | |||
120 | void newline_indent(); | |||
121 | void end_statement_line(); | |||
122 | void newline_deindent(); | |||
123 | void print_var_name (ir_variable* v); | |||
124 | void print_precision (ir_instruction* ir, const glsl_type* type); | |||
125 | ||||
126 | virtual void visit(ir_variable *); | |||
127 | virtual void visit(ir_function_signature *); | |||
128 | virtual void visit(ir_function *); | |||
129 | virtual void visit(ir_expression *); | |||
130 | virtual void visit(ir_texture *); | |||
131 | virtual void visit(ir_swizzle *); | |||
132 | virtual void visit(ir_dereference_variable *); | |||
133 | virtual void visit(ir_dereference_array *); | |||
134 | virtual void visit(ir_dereference_record *); | |||
135 | virtual void visit(ir_assignment *); | |||
136 | virtual void visit(ir_constant *); | |||
137 | virtual void visit(ir_call *); | |||
138 | virtual void visit(ir_return *); | |||
139 | virtual void visit(ir_discard *); | |||
140 | virtual void visit(class ir_demote *); | |||
141 | virtual void visit(ir_if *); | |||
142 | virtual void visit(ir_loop *); | |||
143 | virtual void visit(ir_loop_jump *); | |||
144 | virtual void visit(ir_precision_statement *); | |||
145 | virtual void visit(ir_typedecl_statement *); | |||
146 | virtual void visit(ir_emit_vertex *); | |||
147 | virtual void visit(ir_end_primitive *); | |||
148 | virtual void visit(class ir_barrier *); | |||
149 | ||||
150 | void emit_assignment_part (ir_dereference* lhs, ir_rvalue* rhs, unsigned write_mask, ir_rvalue* dstIndex); | |||
151 | bool can_emit_canonical_for (loop_variable_state *ls); | |||
152 | bool emit_canonical_for (ir_loop* ir); | |||
153 | bool try_print_array_assignment (ir_dereference* lhs, ir_rvalue* rhs); | |||
154 | ||||
155 | int indentation; | |||
156 | int expression_depth; | |||
157 | string_buffer& buffer; | |||
158 | global_print_tracker* globals; | |||
159 | const _mesa_glsl_parse_state* state; | |||
160 | PrintGlslMode mode; | |||
161 | loop_state* loopstate; | |||
162 | bool use_precision; | |||
163 | bool inside_loop_body; | |||
164 | bool skipped_this_ir; | |||
165 | bool previous_skipped; | |||
166 | int uses_texlod_impl; // 3 bits per tex_dimension, bit set for each precision if any texture sampler needs the GLES2 lod workaround. | |||
167 | int uses_texlodproj_impl; // 3 bits per tex_dimension, bit set for each precision if any texture sampler needs the GLES2 lod workaround. | |||
168 | }; | |||
169 | ||||
170 | static void print_texlod_workarounds(int usage_bitfield, int usage_proj_bitfield, string_buffer &str) | |||
171 | { | |||
172 | static const char *precStrings[3] = {"lowp", "mediump", "highp"}; | |||
173 | static const char *precNameStrings[3] = { "low_", "medium_", "high_" }; | |||
174 | // Print out the texlod workarounds | |||
175 | for (int prec = 0; prec < 3; prec++) | |||
176 | { | |||
177 | const char *precString = precStrings[prec]; | |||
178 | const char *precName = precNameStrings[prec]; | |||
179 | ||||
180 | for (int dim = 0; dim < tex_sampler_type_count; dim++) | |||
181 | { | |||
182 | int mask = 1 << (dim + (prec * 8)); | |||
183 | if (usage_bitfield & mask) | |||
184 | { | |||
185 | str.asprintf_append("%s vec4 impl_%stexture%sLodEXT(%s sampler%s sampler, highp vec%d coord, mediump float lod)\n", precString, precName, tex_sampler_dim_name[dim], precString, tex_sampler_dim_name[dim], tex_sampler_dim_size[dim]); | |||
186 | str.asprintf_append("{\n"); | |||
187 | str.asprintf_append("#if defined(GL_EXT_shader_texture_lod)\n"); | |||
188 | str.asprintf_append("\treturn texture%sLodEXT(sampler, coord, lod);\n", tex_sampler_dim_name[dim]); | |||
189 | str.asprintf_append("#else\n"); | |||
190 | str.asprintf_append("\treturn texture%s(sampler, coord, lod);\n", tex_sampler_dim_name[dim]); | |||
191 | str.asprintf_append("#endif\n"); | |||
192 | str.asprintf_append("}\n\n"); | |||
193 | } | |||
194 | if (usage_proj_bitfield & mask) | |||
195 | { | |||
196 | // 2D projected read also has a vec4 UV variant | |||
197 | if (dim == GLSL_SAMPLER_DIM_2D) | |||
198 | { | |||
199 | str.asprintf_append("%s vec4 impl_%stexture2DProjLodEXT(%s sampler2D sampler, highp vec4 coord, mediump float lod)\n", precString, precName, precString); | |||
200 | str.asprintf_append("{\n"); | |||
201 | str.asprintf_append("#if defined(GL_EXT_shader_texture_lod)\n"); | |||
202 | str.asprintf_append("\treturn texture%sProjLodEXT(sampler, coord, lod);\n", tex_sampler_dim_name[dim]); | |||
203 | str.asprintf_append("#else\n"); | |||
204 | str.asprintf_append("\treturn texture%sProj(sampler, coord, lod);\n", tex_sampler_dim_name[dim]); | |||
205 | str.asprintf_append("#endif\n"); | |||
206 | str.asprintf_append("}\n\n"); | |||
207 | } | |||
208 | str.asprintf_append("%s vec4 impl_%stexture%sProjLodEXT(%s sampler%s sampler, highp vec%d coord, mediump float lod)\n", precString, precName, tex_sampler_dim_name[dim], precString, tex_sampler_dim_name[dim], tex_sampler_dim_size[dim] + 1); | |||
209 | str.asprintf_append("{\n"); | |||
210 | str.asprintf_append("#if defined(GL_EXT_shader_texture_lod)\n"); | |||
211 | str.asprintf_append("\treturn texture%sProjLodEXT(sampler, coord, lod);\n", tex_sampler_dim_name[dim]); | |||
212 | str.asprintf_append("#else\n"); | |||
213 | str.asprintf_append("\treturn texture%sProj(sampler, coord, lod);\n", tex_sampler_dim_name[dim]); | |||
214 | str.asprintf_append("#endif\n"); | |||
215 | str.asprintf_append("}\n\n"); | |||
216 | } | |||
217 | } | |||
218 | } | |||
219 | } | |||
220 | ||||
221 | ||||
222 | char* | |||
223 | _mesa_print_ir_glsl(exec_list *instructions, | |||
224 | struct _mesa_glsl_parse_state *state, | |||
225 | char* buffer, PrintGlslMode mode) | |||
226 | { | |||
227 | string_buffer str(buffer); | |||
228 | string_buffer body(buffer); | |||
229 | ||||
230 | // print version & extensions | |||
231 | if (state) { | |||
| ||||
232 | if (state->had_version_string) | |||
233 | { | |||
234 | str.asprintf_append ("#version %i", state->language_version); | |||
235 | if (state->es_shader && state->language_version >= 300) | |||
236 | str.asprintf_append (" es"); | |||
237 | str.asprintf_append ("\n"); | |||
238 | } | |||
239 | if (state->ARB_shader_texture_lod_enable) | |||
240 | str.asprintf_append ("#extension GL_ARB_shader_texture_lod : enable\n"); | |||
241 | if (state->ARB_draw_instanced_enable) | |||
242 | str.asprintf_append ("#extension GL_ARB_draw_instanced : enable\n"); | |||
243 | if (state->ARB_explicit_attrib_location_enable) | |||
244 | str.asprintf_append ("#extension GL_ARB_explicit_attrib_location : enable\n"); | |||
245 | if (state->EXT_gpu_shader4_enable) | |||
246 | str.asprintf_append ("#extension GL_EXT_gpu_shader4 : enable\n"); | |||
247 | // FIXME | |||
248 | // if (state->EXT_shader_texture_lod_enable) | |||
249 | // str.asprintf_append ("#extension GL_EXT_shader_texture_lod : enable\n"); | |||
250 | if (state->OES_standard_derivatives_enable) | |||
251 | str.asprintf_append ("#extension GL_OES_standard_derivatives : enable\n"); | |||
252 | // FIXME | |||
253 | // if (state->EXT_shadow_samplers_enable) | |||
254 | // str.asprintf_append ("#extension GL_EXT_shadow_samplers : enable\n"); | |||
255 | if (state->EXT_frag_depth_enable) | |||
256 | str.asprintf_append ("#extension GL_EXT_frag_depth : enable\n"); | |||
257 | if (state->es_shader && state->language_version < 300) | |||
258 | { | |||
259 | if (state->EXT_draw_buffers_enable) | |||
260 | str.asprintf_append ("#extension GL_EXT_draw_buffers : enable\n"); | |||
261 | // FIXME | |||
262 | // if (state->EXT_draw_instanced_enable) | |||
263 | // str.asprintf_append ("#extension GL_EXT_draw_instanced : enable\n"); | |||
264 | } | |||
265 | if (state->EXT_shader_framebuffer_fetch_enable) | |||
266 | str.asprintf_append ("#extension GL_EXT_shader_framebuffer_fetch : enable\n"); | |||
267 | if (state->ARB_shader_bit_encoding_enable) | |||
268 | str.asprintf_append("#extension GL_ARB_shader_bit_encoding : enable\n"); | |||
269 | if (state->EXT_texture_array_enable) | |||
270 | str.asprintf_append ("#extension GL_EXT_texture_array : enable\n"); | |||
271 | if (state->KHR_blend_equation_advanced_enable) | |||
272 | str.asprintf_append ("#extension GL_KHR_blend_equation_advanced : enable\n"); | |||
273 | if (state->EXT_blend_func_extended_enable) | |||
274 | str.asprintf_append ("#extension GL_EXT_blend_func_extended : enable\n"); | |||
275 | if (state->OES_EGL_image_external_enable) | |||
276 | str.asprintf_append ("#extension GL_OES_EGL_image_external : enable\n"); | |||
277 | if (state->OES_EGL_image_external_essl3_enable) | |||
278 | str.asprintf_append ("#extension GL_OES_EGL_image_external_essl3 : enable\n"); | |||
279 | if (state->ARB_shader_storage_buffer_object_enable) | |||
280 | str.asprintf_append ("#extension GL_ARB_shader_storage_buffer_object : enable\n"); | |||
281 | ||||
282 | ||||
283 | // TODO: support other blend specifiers besides "all" | |||
284 | if (state->fs_blend_support == BLEND_ALL) | |||
285 | str.asprintf_append ("layout(blend_support_all_equations) out;\n"); | |||
286 | } | |||
287 | ||||
288 | // remove unused struct declarations | |||
289 | do_remove_unused_typedecls(instructions); | |||
290 | ||||
291 | global_print_tracker gtracker; | |||
292 | int uses_texlod_impl = 0; | |||
293 | int uses_texlodproj_impl = 0; | |||
294 | ||||
295 | loop_state* ls = analyze_loop_variables(instructions); | |||
296 | // FIXME: set_loop_controls has been merged in to unroll_loops | |||
297 | // if (ls->loop_found) | |||
298 | // set_loop_controls(instructions, ls); | |||
299 | ||||
300 | foreach_in_list(ir_instruction, ir, instructions)for (ir_instruction *ir = (!exec_node_is_tail_sentinel((instructions )->head_sentinel.next) ? (ir_instruction *) ((instructions )->head_sentinel.next) : __null); (ir) != __null; (ir) = ( !exec_node_is_tail_sentinel((ir)->next) ? (ir_instruction * ) ((ir)->next) : __null)) | |||
301 | { | |||
302 | if (ir->ir_type == ir_type_variable) { | |||
303 | ir_variable *var = static_cast<ir_variable*>(ir); | |||
304 | if ((strstr(var->name, "gl_") == var->name) | |||
305 | && !var->data.invariant) | |||
306 | continue; | |||
307 | } | |||
308 | ||||
309 | ir_print_glsl_visitor v (body, >racker, mode, state->es_shader, state); | |||
| ||||
310 | v.loopstate = ls; | |||
311 | ||||
312 | ir->accept(&v); | |||
313 | if (ir->ir_type != ir_type_function && !v.skipped_this_ir) | |||
314 | body.asprintf_append (";\n"); | |||
315 | ||||
316 | uses_texlod_impl |= v.uses_texlod_impl; | |||
317 | uses_texlodproj_impl |= v.uses_texlodproj_impl; | |||
318 | } | |||
319 | ||||
320 | delete ls; | |||
321 | ||||
322 | print_texlod_workarounds(uses_texlod_impl, uses_texlodproj_impl, str); | |||
323 | ||||
324 | // Add the optimized glsl code | |||
325 | str.asprintf_append("%s", body.c_str()); | |||
326 | ||||
327 | return ralloc_strdup(buffer, str.c_str()); | |||
328 | } | |||
329 | ||||
330 | ||||
331 | void ir_print_glsl_visitor::indent(void) | |||
332 | { | |||
333 | if (previous_skipped) | |||
334 | return; | |||
335 | previous_skipped = false; | |||
336 | for (int i = 0; i < indentation; i++) | |||
337 | buffer.asprintf_append (" "); | |||
338 | } | |||
339 | ||||
340 | void ir_print_glsl_visitor::end_statement_line() | |||
341 | { | |||
342 | if (!skipped_this_ir) | |||
343 | buffer.asprintf_append(";\n"); | |||
344 | previous_skipped = skipped_this_ir; | |||
345 | skipped_this_ir = false; | |||
346 | } | |||
347 | ||||
348 | void ir_print_glsl_visitor::newline_indent() | |||
349 | { | |||
350 | if (expression_depth % 4 == 0) | |||
351 | { | |||
352 | ++indentation; | |||
353 | buffer.asprintf_append ("\n"); | |||
354 | indent(); | |||
355 | } | |||
356 | } | |||
357 | void ir_print_glsl_visitor::newline_deindent() | |||
358 | { | |||
359 | if (expression_depth % 4 == 0) | |||
360 | { | |||
361 | --indentation; | |||
362 | buffer.asprintf_append ("\n"); | |||
363 | indent(); | |||
364 | } | |||
365 | } | |||
366 | ||||
367 | ||||
368 | void ir_print_glsl_visitor::print_var_name (ir_variable* v) | |||
369 | { | |||
370 | long id = 0; | |||
371 | const hash_entry *entry = _mesa_hash_table_search(globals->var_hash, v); | |||
372 | if (entry) | |||
373 | { | |||
374 | id = (long)entry->data; | |||
375 | } | |||
376 | else if (v->data.mode == ir_var_temporary) | |||
377 | { | |||
378 | id = ++globals->var_counter; | |||
379 | _mesa_hash_table_insert (globals->var_hash, v, (void*)id); | |||
380 | } | |||
381 | if (id) | |||
382 | { | |||
383 | if (v->data.mode == ir_var_temporary) | |||
384 | buffer.asprintf_append ("tmpvar_%d", (int)id); | |||
385 | else | |||
386 | buffer.asprintf_append ("%s_%d", v->name, (int)id); | |||
387 | } | |||
388 | else | |||
389 | { | |||
390 | buffer.asprintf_append ("%s", v->name); | |||
391 | } | |||
392 | } | |||
393 | ||||
394 | void ir_print_glsl_visitor::print_precision (ir_instruction* ir, const glsl_type* type) | |||
395 | { | |||
396 | if (!this->use_precision) | |||
397 | return; | |||
398 | if (type && | |||
399 | !type->is_float() && | |||
400 | !type->is_sampler() && | |||
401 | !type->is_integer() && | |||
402 | (!type->is_array() || !type->without_array()->is_float()) && | |||
403 | (!type->is_array() || !type->without_array()->is_integer()) | |||
404 | ) | |||
405 | { | |||
406 | return; | |||
407 | } | |||
408 | ||||
409 | ir_variable* var = ir->as_variable(); | |||
410 | if (var) { | |||
411 | buffer.asprintf_append ("%s", get_precision_string(var->data.precision)); | |||
412 | } | |||
413 | ||||
414 | // FIXME | |||
415 | // glsl_precision prec = precision_from_ir(ir); | |||
416 | ||||
417 | // // In fragment shader, default float precision is undefined. | |||
418 | // // We must thus always print it, when there was no default precision | |||
419 | // // and for whatever reason our type ended up having undefined precision. | |||
420 | // if (prec == glsl_precision_undefined && | |||
421 | // type && type->is_float() && | |||
422 | // this->state->stage == MESA_SHADER_FRAGMENT && | |||
423 | // !this->state->had_float_precision) | |||
424 | // { | |||
425 | // prec = glsl_precision_high; | |||
426 | // } | |||
427 | // if (type && type->is_integer()) | |||
428 | // { | |||
429 | // if (prec == glsl_precision_undefined && type && type->is_integer()) | |||
430 | // { | |||
431 | // // Default to highp on integers | |||
432 | // prec = glsl_precision_high; | |||
433 | // } | |||
434 | // } | |||
435 | ||||
436 | // // skip precision for samplers that end up being lowp (default anyway) or undefined; | |||
437 | // // except always emit it for shadowmap samplers (some drivers don't implement | |||
438 | // // default EXT_shadow_samplers precision) and 3D textures (they always require precision) | |||
439 | // if (type && type->is_sampler() && !type->sampler_shadow && !(type->sampler_dimensionality > GLSL_SAMPLER_DIM_2D)) | |||
440 | // { | |||
441 | // if (prec == glsl_precision_low || prec == glsl_precision_undefined) | |||
442 | // return; | |||
443 | // } | |||
444 | ||||
445 | // if (prec == glsl_precision_high || prec == glsl_precision_undefined) | |||
446 | // { | |||
447 | // if (ir->ir_type == ir_type_function_signature) | |||
448 | // return; | |||
449 | // } | |||
450 | // buffer.asprintf_append ("%s", get_precision_string(prec)); | |||
451 | } | |||
452 | ||||
453 | ||||
454 | static void print_type(string_buffer& buffer, const glsl_type *t, bool arraySize) | |||
455 | { | |||
456 | if (t->base_type == GLSL_TYPE_ARRAY) { | |||
457 | print_type(buffer, t->fields.array, true); | |||
458 | if (arraySize) | |||
459 | buffer.asprintf_append ("[%u]", t->length); | |||
460 | } else if ((t->base_type == GLSL_TYPE_STRUCT) | |||
461 | && (strncmp("gl_", t->name, 3) != 0)) { | |||
462 | buffer.asprintf_append ("%s", t->name); | |||
463 | } else { | |||
464 | buffer.asprintf_append ("%s", t->name); | |||
465 | } | |||
466 | } | |||
467 | ||||
468 | static void print_type_post(string_buffer& buffer, const glsl_type *t, bool arraySize) | |||
469 | { | |||
470 | if (t->base_type == GLSL_TYPE_ARRAY) { | |||
471 | if (!arraySize) { | |||
472 | if (t->length) { | |||
473 | buffer.asprintf_append ("[%u]", t->length); | |||
474 | } else { | |||
475 | buffer.asprintf_append ("[]"); | |||
476 | } | |||
477 | } | |||
478 | } | |||
479 | } | |||
480 | ||||
481 | ||||
482 | void ir_print_glsl_visitor::visit(ir_variable *ir) | |||
483 | { | |||
484 | // Variables that are declared as or part of interface blocks will be printed by the block declaration. | |||
485 | if (ir->is_in_buffer_block()) { | |||
486 | skipped_this_ir = true; | |||
487 | return; | |||
488 | } | |||
489 | ||||
490 | const char *const cent = (ir->data.centroid) ? "centroid " : ""; | |||
491 | const char *const inv = (ir->data.invariant) ? "invariant " : ""; | |||
492 | const char *const mode[3][ir_var_mode_count] = | |||
493 | { | |||
494 | { "", "uniform ", "", "", "in ", "out ", "in ", "out ", "inout ", "", "", "" }, | |||
495 | { "", "uniform ", "", "", "attribute ", "varying ", "in ", "out ", "inout ", "", "", "" }, | |||
496 | { "", "uniform ", "", "", "varying ", "out ", "in ", "out ", "inout ", "", "", "" }, | |||
497 | }; | |||
498 | ||||
499 | const char *const interp[] = { "", "smooth ", "flat ", "noperspective " }; | |||
500 | ||||
501 | bool supports_explicit_location = this->state->language_version >= 300 || | |||
502 | this->state->ARB_explicit_attrib_location_enable; | |||
503 | if (supports_explicit_location && ir->data.explicit_location) | |||
504 | { | |||
505 | const int binding_base = (this->state->stage == MESA_SHADER_VERTEX ? (int)VERT_ATTRIB_GENERIC0 : (int)FRAG_RESULT_DATA0); | |||
506 | const int location = ir->data.location - binding_base; | |||
507 | if (ir->data.explicit_index) { | |||
508 | const int index = ir->data.index; | |||
509 | buffer.asprintf_append ("layout(location=%d, index=%d) ", location, index); | |||
510 | } else { | |||
511 | buffer.asprintf_append ("layout(location=%d) ", location); | |||
512 | } | |||
513 | } | |||
514 | ||||
515 | int decormode = this->mode; | |||
516 | // GLSL 1.30 and up use "in" and "out" for everything | |||
517 | if (this->state->language_version >= 130) | |||
518 | { | |||
519 | decormode = 0; | |||
520 | } | |||
521 | ||||
522 | // give an id to any variable defined in a function that is not an uniform | |||
523 | if ((this->mode == kPrintGlslNone && ir->data.mode != ir_var_uniform)) | |||
524 | { | |||
525 | const hash_entry *entry = _mesa_hash_table_search (globals->var_hash, ir); | |||
526 | if (!entry) | |||
527 | { | |||
528 | long id = ++globals->var_counter; | |||
529 | _mesa_hash_table_insert (globals->var_hash, ir, (void*)id); | |||
530 | } | |||
531 | } | |||
532 | ||||
533 | // if this is a loop induction variable, do not print it | |||
534 | // (will be printed inside loop body) | |||
535 | if (!inside_loop_body) | |||
536 | { | |||
537 | // FIXME | |||
538 | // loop_variable_state* inductor_state = loopstate->get_for_inductor(ir); | |||
539 | // if (inductor_state && inductor_state->private_induction_variable_count == 1 && | |||
540 | // can_emit_canonical_for(inductor_state)) | |||
541 | // { | |||
542 | // skipped_this_ir = true; | |||
543 | // return; | |||
544 | // } | |||
545 | } | |||
546 | ||||
547 | // keep invariant declaration for builtin variables | |||
548 | if (strstr(ir->name, "gl_") == ir->name) { | |||
549 | buffer.asprintf_append ("%s", inv); | |||
550 | print_var_name (ir); | |||
551 | return; | |||
552 | } | |||
553 | ||||
554 | buffer.asprintf_append ("%s%s%s%s", | |||
555 | cent, inv, interp[ir->data.interpolation], mode[decormode][ir->data.mode]); | |||
556 | print_precision (ir, ir->type); | |||
557 | print_type(buffer, ir->type, false); | |||
558 | buffer.asprintf_append (" "); | |||
559 | print_var_name (ir); | |||
560 | print_type_post(buffer, ir->type, false); | |||
561 | ||||
562 | // FIXME: inout is a metal thing? | |||
563 | if (ir->constant_value && | |||
564 | ir->data.mode != ir_var_shader_in && | |||
565 | ir->data.mode != ir_var_shader_out && | |||
566 | // ir->data.mode != ir_var_shader_inout && | |||
567 | ir->data.mode != ir_var_function_in && | |||
568 | ir->data.mode != ir_var_function_out) // && | |||
569 | // ir->data.mode != ir_var_function_inout) | |||
570 | { | |||
571 | buffer.asprintf_append (" = "); | |||
572 | visit (ir->constant_value); | |||
573 | } | |||
574 | } | |||
575 | ||||
576 | ||||
577 | void ir_print_glsl_visitor::visit(ir_function_signature *ir) | |||
578 | { | |||
579 | print_precision (ir, ir->return_type); | |||
580 | print_type(buffer, ir->return_type, true); | |||
581 | buffer.asprintf_append (" %s (", ir->function_name()); | |||
582 | ||||
583 | if (!ir->parameters.is_empty()) | |||
584 | { | |||
585 | buffer.asprintf_append ("\n"); | |||
586 | ||||
587 | indentation++; previous_skipped = false; | |||
588 | bool first = true; | |||
589 | foreach_in_list(ir_variable, inst, &ir->parameters)for (ir_variable *inst = (!exec_node_is_tail_sentinel((&ir ->parameters)->head_sentinel.next) ? (ir_variable *) (( &ir->parameters)->head_sentinel.next) : __null); (inst ) != __null; (inst) = (!exec_node_is_tail_sentinel((inst)-> next) ? (ir_variable *) ((inst)->next) : __null)) { | |||
590 | if (!first) | |||
591 | buffer.asprintf_append (",\n"); | |||
592 | indent(); | |||
593 | inst->accept(this); | |||
594 | first = false; | |||
595 | } | |||
596 | indentation--; | |||
597 | ||||
598 | buffer.asprintf_append ("\n"); | |||
599 | indent(); | |||
600 | } | |||
601 | ||||
602 | if (ir->body.is_empty()) | |||
603 | { | |||
604 | buffer.asprintf_append (");\n"); | |||
605 | return; | |||
606 | } | |||
607 | ||||
608 | buffer.asprintf_append (")\n"); | |||
609 | ||||
610 | indent(); | |||
611 | buffer.asprintf_append ("{\n"); | |||
612 | indentation++; previous_skipped = false; | |||
613 | ||||
614 | // insert postponed global assigments | |||
615 | if (strcmp(ir->function()->name, "main") == 0) | |||
616 | { | |||
617 | assert (!globals->main_function_done)(static_cast <bool> (!globals->main_function_done) ? void (0) : __assert_fail ("!globals->main_function_done", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | |||
618 | globals->main_function_done = true; | |||
619 | foreach_in_list(ga_entry, node, &globals->global_assignements)for (ga_entry *node = (!exec_node_is_tail_sentinel((&globals ->global_assignements)->head_sentinel.next) ? (ga_entry *) ((&globals->global_assignements)->head_sentinel .next) : __null); (node) != __null; (node) = (!exec_node_is_tail_sentinel ((node)->next) ? (ga_entry *) ((node)->next) : __null)) | |||
620 | { | |||
621 | ir_instruction* as = node->ir; | |||
622 | as->accept(this); | |||
623 | buffer.asprintf_append(";\n"); | |||
624 | } | |||
625 | } | |||
626 | ||||
627 | foreach_in_list(ir_instruction, inst, &ir->body)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((& ir->body)->head_sentinel.next) ? (ir_instruction *) ((& ir->body)->head_sentinel.next) : __null); (inst) != __null ; (inst) = (!exec_node_is_tail_sentinel((inst)->next) ? (ir_instruction *) ((inst)->next) : __null)) { | |||
628 | indent(); | |||
629 | inst->accept(this); | |||
630 | end_statement_line(); | |||
631 | } | |||
632 | indentation--; | |||
633 | indent(); | |||
634 | buffer.asprintf_append ("}\n"); | |||
635 | } | |||
636 | ||||
637 | void ir_print_glsl_visitor::visit(ir_function *ir) | |||
638 | { | |||
639 | bool found_non_builtin_proto = false; | |||
640 | ||||
641 | foreach_in_list(ir_function_signature, sig, &ir->signatures)for (ir_function_signature *sig = (!exec_node_is_tail_sentinel ((&ir->signatures)->head_sentinel.next) ? (ir_function_signature *) ((&ir->signatures)->head_sentinel.next) : __null ); (sig) != __null; (sig) = (!exec_node_is_tail_sentinel((sig )->next) ? (ir_function_signature *) ((sig)->next) : __null )) { | |||
642 | if (!sig->is_builtin()) | |||
643 | found_non_builtin_proto = true; | |||
644 | } | |||
645 | if (!found_non_builtin_proto) | |||
646 | return; | |||
647 | ||||
648 | PrintGlslMode oldMode = this->mode; | |||
649 | this->mode = kPrintGlslNone; | |||
650 | ||||
651 | foreach_in_list(ir_function_signature, sig, &ir->signatures)for (ir_function_signature *sig = (!exec_node_is_tail_sentinel ((&ir->signatures)->head_sentinel.next) ? (ir_function_signature *) ((&ir->signatures)->head_sentinel.next) : __null ); (sig) != __null; (sig) = (!exec_node_is_tail_sentinel((sig )->next) ? (ir_function_signature *) ((sig)->next) : __null )) { | |||
652 | indent(); | |||
653 | sig->accept(this); | |||
654 | buffer.asprintf_append ("\n"); | |||
655 | } | |||
656 | ||||
657 | this->mode = oldMode; | |||
658 | ||||
659 | indent(); | |||
660 | } | |||
661 | ||||
662 | static const char* operator_glsl_str(ir_expression_operation op, const glsl_type* type) { | |||
663 | switch (op) { | |||
664 | case ir_unop_bit_not: | |||
665 | return "~"; | |||
666 | case ir_unop_logic_not: | |||
667 | return "!"; | |||
668 | case ir_unop_neg: | |||
669 | return "-"; | |||
670 | case ir_unop_abs: | |||
671 | return "abs"; | |||
672 | case ir_unop_sign: | |||
673 | return "sign"; | |||
674 | case ir_unop_rsq: | |||
675 | return "inversesqrt"; | |||
676 | case ir_unop_sqrt: | |||
677 | return "sqrt"; | |||
678 | case ir_unop_exp: | |||
679 | return "exp"; | |||
680 | case ir_unop_log: | |||
681 | return "log"; | |||
682 | case ir_unop_exp2: | |||
683 | return "exp2"; | |||
684 | case ir_unop_log2: | |||
685 | return "log2"; | |||
686 | case ir_unop_trunc: | |||
687 | return "trunc"; | |||
688 | case ir_unop_ceil: | |||
689 | return "ceil"; | |||
690 | case ir_unop_floor: | |||
691 | return "floor"; | |||
692 | case ir_unop_fract: | |||
693 | return "fract"; | |||
694 | case ir_unop_round_even: | |||
695 | return "roundEven"; | |||
696 | case ir_unop_sin: | |||
697 | return "sin"; | |||
698 | case ir_unop_cos: | |||
699 | return "cos"; | |||
700 | case ir_unop_atan: | |||
701 | return "atan"; | |||
702 | case ir_unop_dFdx: | |||
703 | return "dFdx"; | |||
704 | case ir_unop_dFdx_coarse: | |||
705 | return "dFdxCoarse"; | |||
706 | case ir_unop_dFdx_fine: | |||
707 | return "dFdxFine"; | |||
708 | case ir_unop_dFdy: | |||
709 | return "dFdy"; | |||
710 | case ir_unop_dFdy_coarse: | |||
711 | return "dFdyCoarse"; | |||
712 | case ir_unop_dFdy_fine: | |||
713 | return "dFdyFine"; | |||
714 | case ir_unop_pack_snorm_2x16: | |||
715 | return "packSnorm2x16"; | |||
716 | case ir_unop_pack_snorm_4x8: | |||
717 | return "packSnorm4x8"; | |||
718 | case ir_unop_pack_unorm_2x16: | |||
719 | return "packUnorm2x16"; | |||
720 | case ir_unop_pack_unorm_4x8: | |||
721 | return "packUnorm4x8"; | |||
722 | case ir_unop_pack_half_2x16: | |||
723 | return "packHalf2x16"; | |||
724 | case ir_unop_unpack_snorm_2x16: | |||
725 | return "unpackSnorm2x16"; | |||
726 | case ir_unop_unpack_snorm_4x8: | |||
727 | return "unpackSnorm4x8"; | |||
728 | case ir_unop_unpack_unorm_2x16: | |||
729 | return "unpackUnorm2x16"; | |||
730 | case ir_unop_unpack_unorm_4x8: | |||
731 | return "unpackUnorm4x8"; | |||
732 | case ir_unop_unpack_half_2x16: | |||
733 | return "unpackHalf2x16"; | |||
734 | case ir_unop_bitfield_reverse: | |||
735 | return "bitfieldReverse"; | |||
736 | case ir_unop_bit_count: | |||
737 | return "bitCount"; | |||
738 | case ir_unop_find_msb: | |||
739 | return "findMSB"; | |||
740 | case ir_unop_find_lsb: | |||
741 | return "findLSB"; | |||
742 | case ir_unop_saturate: | |||
743 | return "saturate"; | |||
744 | case ir_unop_pack_double_2x32: | |||
745 | return "packDouble2x32"; | |||
746 | case ir_unop_unpack_double_2x32: | |||
747 | return "unpackDouble2x32"; | |||
748 | case ir_unop_pack_sampler_2x32: | |||
749 | return "packSampler2x32"; | |||
750 | case ir_unop_pack_image_2x32: | |||
751 | return "packImage2x32"; | |||
752 | case ir_unop_unpack_sampler_2x32: | |||
753 | return "unpackSampler2x32"; | |||
754 | case ir_unop_unpack_image_2x32: | |||
755 | return "unpackImage2x32"; | |||
756 | case ir_unop_interpolate_at_centroid: | |||
757 | return "interpolateAtCentroid"; | |||
758 | case ir_unop_pack_int_2x32: | |||
759 | return "packInt2x32"; | |||
760 | case ir_unop_pack_uint_2x32: | |||
761 | return "packUint2x32"; | |||
762 | case ir_unop_unpack_int_2x32: | |||
763 | return "unpackInt2x32"; | |||
764 | case ir_unop_unpack_uint_2x32: | |||
765 | return "unpackUint2x32"; | |||
766 | case ir_binop_add: | |||
767 | return "+"; | |||
768 | case ir_binop_sub: | |||
769 | return "-"; | |||
770 | case ir_binop_mul: | |||
771 | return "*"; | |||
772 | case ir_binop_div: | |||
773 | return "/"; | |||
774 | case ir_binop_mod: | |||
775 | if (type->is_integer()) | |||
776 | return "%"; | |||
777 | else | |||
778 | return "mod"; | |||
779 | case ir_binop_less: | |||
780 | if (type->is_vector()) | |||
781 | return "lessThan"; | |||
782 | else | |||
783 | return "<"; | |||
784 | case ir_binop_gequal: | |||
785 | if (type->is_vector()) | |||
786 | return "greaterThanEqual"; | |||
787 | else | |||
788 | return ">="; | |||
789 | case ir_binop_equal: | |||
790 | if (type->is_vector()) | |||
791 | return "equal"; | |||
792 | else | |||
793 | return "=="; | |||
794 | case ir_binop_nequal: | |||
795 | if (type->is_vector()) | |||
796 | return "notEqual"; | |||
797 | else | |||
798 | return "!="; | |||
799 | case ir_binop_all_equal: | |||
800 | return "=="; | |||
801 | case ir_binop_any_nequal: | |||
802 | return "!="; | |||
803 | case ir_binop_lshift: | |||
804 | return "<<"; | |||
805 | case ir_binop_rshift: | |||
806 | return ">>"; | |||
807 | case ir_binop_bit_and: | |||
808 | return "&"; | |||
809 | case ir_binop_bit_xor: | |||
810 | return "^"; | |||
811 | case ir_binop_bit_or: | |||
812 | return "|"; | |||
813 | case ir_binop_logic_and: | |||
814 | return "&&"; | |||
815 | case ir_binop_logic_xor: | |||
816 | return "^^"; | |||
817 | case ir_binop_logic_or: | |||
818 | return "||"; | |||
819 | case ir_binop_dot: | |||
820 | return "dot"; | |||
821 | case ir_binop_min: | |||
822 | return "min"; | |||
823 | case ir_binop_max: | |||
824 | return "max"; | |||
825 | case ir_binop_pow: | |||
826 | return "pow"; | |||
827 | case ir_binop_interpolate_at_offset: | |||
828 | return "interpolateAtOffset"; | |||
829 | case ir_binop_interpolate_at_sample: | |||
830 | return "interpolateAtSample"; | |||
831 | case ir_binop_atan2: | |||
832 | return "atan"; | |||
833 | case ir_triop_fma: | |||
834 | return "fma"; | |||
835 | case ir_triop_lrp: | |||
836 | return "mix"; | |||
837 | default: | |||
838 | unreachable("Unexpected operator in operator_glsl_str")do { (static_cast <bool> (!"Unexpected operator in operator_glsl_str" ) ? void (0) : __assert_fail ("!\"Unexpected operator in operator_glsl_str\"" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); __builtin_unreachable(); } while (0); | |||
839 | return "UNIMPLEMENTED"; | |||
840 | } | |||
841 | } | |||
842 | ||||
843 | static bool is_binop_func_like(ir_expression_operation op, const glsl_type* type) | |||
844 | { | |||
845 | if (op == ir_binop_mod && !type->is_integer()) { | |||
846 | return true; | |||
847 | } else if ((op >= ir_binop_dot && op <= ir_binop_pow) || op == ir_binop_atan2) { | |||
848 | return true; | |||
849 | } else if (type->is_vector() && (op >= ir_binop_less && op <= ir_binop_nequal)) { | |||
850 | return true; | |||
851 | } | |||
852 | return false; | |||
853 | } | |||
854 | ||||
855 | void ir_print_glsl_visitor::visit(ir_expression *ir) | |||
856 | { | |||
857 | ++this->expression_depth; | |||
858 | newline_indent(); | |||
859 | ||||
860 | if (ir->num_operands == 1) { | |||
861 | if (ir->operation >= ir_unop_f2i && ir->operation <= ir_unop_u2i) { | |||
862 | print_type(buffer, ir->type, true); | |||
863 | buffer.asprintf_append ("("); | |||
864 | } else if (ir->operation == ir_unop_rcp) { | |||
865 | buffer.asprintf_append ("(1.0/("); | |||
866 | } else { | |||
867 | buffer.asprintf_append ("%s(", operator_glsl_str(ir->operation, ir->type)); | |||
868 | } | |||
869 | if (ir->operands[0]) | |||
870 | ir->operands[0]->accept(this); | |||
871 | buffer.asprintf_append (")"); | |||
872 | if (ir->operation == ir_unop_rcp) { | |||
873 | buffer.asprintf_append (")"); | |||
874 | } | |||
875 | } | |||
876 | else if (ir->operation == ir_triop_csel) | |||
877 | { | |||
878 | buffer.asprintf_append ("mix("); | |||
879 | ir->operands[2]->accept(this); | |||
880 | buffer.asprintf_append (", "); | |||
881 | ir->operands[1]->accept(this); | |||
882 | if (ir->operands[1]->type->is_scalar()) | |||
883 | buffer.asprintf_append (", bool("); | |||
884 | else | |||
885 | buffer.asprintf_append (", bvec%d(", ir->operands[1]->type->vector_elements); | |||
886 | ir->operands[0]->accept(this); | |||
887 | buffer.asprintf_append ("))"); | |||
888 | } | |||
889 | else if (ir->operation == ir_binop_vector_extract) | |||
890 | { | |||
891 | // a[b] | |||
892 | ||||
893 | if (ir->operands[0]) | |||
894 | ir->operands[0]->accept(this); | |||
895 | buffer.asprintf_append ("["); | |||
896 | if (ir->operands[1]) | |||
897 | ir->operands[1]->accept(this); | |||
898 | buffer.asprintf_append ("]"); | |||
899 | } | |||
900 | else if (is_binop_func_like(ir->operation, ir->type)) | |||
901 | { | |||
902 | if (ir->operation == ir_binop_mod) | |||
903 | { | |||
904 | buffer.asprintf_append ("("); | |||
905 | print_type(buffer, ir->type, true); | |||
906 | buffer.asprintf_append ("("); | |||
907 | } | |||
908 | buffer.asprintf_append ("%s (", operator_glsl_str(ir->operation, ir->type)); | |||
909 | ||||
910 | if (ir->operands[0]) | |||
911 | ir->operands[0]->accept(this); | |||
912 | buffer.asprintf_append (", "); | |||
913 | if (ir->operands[1]) | |||
914 | ir->operands[1]->accept(this); | |||
915 | buffer.asprintf_append (")"); | |||
916 | if (ir->operation == ir_binop_mod) | |||
917 | buffer.asprintf_append ("))"); | |||
918 | } | |||
919 | else if (ir->num_operands == 2) | |||
920 | { | |||
921 | buffer.asprintf_append ("("); | |||
922 | if (ir->operands[0]) | |||
923 | ir->operands[0]->accept(this); | |||
924 | ||||
925 | buffer.asprintf_append (" %s ", operator_glsl_str(ir->operation, ir->type)); | |||
926 | ||||
927 | if (ir->operands[1]) | |||
928 | ir->operands[1]->accept(this); | |||
929 | buffer.asprintf_append (")"); | |||
930 | } | |||
931 | else | |||
932 | { | |||
933 | // ternary op | |||
934 | buffer.asprintf_append ("%s (", operator_glsl_str(ir->operation, ir->type)); | |||
935 | if (ir->operands[0]) | |||
936 | ir->operands[0]->accept(this); | |||
937 | buffer.asprintf_append (", "); | |||
938 | if (ir->operands[1]) | |||
939 | ir->operands[1]->accept(this); | |||
940 | buffer.asprintf_append (", "); | |||
941 | if (ir->operands[2]) | |||
942 | ir->operands[2]->accept(this); | |||
943 | buffer.asprintf_append (")"); | |||
944 | } | |||
945 | ||||
946 | newline_deindent(); | |||
947 | --this->expression_depth; | |||
948 | } | |||
949 | ||||
950 | void ir_print_glsl_visitor::visit(ir_texture *ir) | |||
951 | { | |||
952 | glsl_sampler_dim sampler_dim = (glsl_sampler_dim)ir->sampler->type->sampler_dimensionality; | |||
953 | const bool is_shadow = ir->sampler->type->sampler_shadow; | |||
954 | const bool is_array = ir->sampler->type->sampler_array; | |||
955 | ||||
956 | if (ir->op == ir_txs) | |||
957 | { | |||
958 | buffer.asprintf_append("textureSize ("); | |||
959 | ir->sampler->accept(this); | |||
960 | if (ir_texture::has_lod(ir->sampler->type)) | |||
961 | { | |||
962 | buffer.asprintf_append(", "); | |||
963 | ir->lod_info.lod->accept(this); | |||
964 | } | |||
965 | buffer.asprintf_append(")"); | |||
966 | return; | |||
967 | } | |||
968 | ||||
969 | const glsl_type* uv_type = ir->coordinate->type; | |||
970 | const int uv_dim = uv_type->vector_elements; | |||
971 | int sampler_uv_dim = tex_sampler_dim_size[sampler_dim]; | |||
972 | if (is_shadow) | |||
973 | sampler_uv_dim += 1; | |||
974 | if (is_array) | |||
975 | sampler_uv_dim += 1; | |||
976 | const bool is_proj = ((ir->op == ir_tex || ir->op == ir_txb || ir->op == ir_txl || ir->op == ir_txd) && uv_dim > sampler_uv_dim); | |||
977 | const bool is_lod = (ir->op == ir_txl); | |||
978 | ||||
979 | // FIXME precision/lod | |||
980 | // if (is_lod && state->es_shader && state->language_version < 300 && state->stage == MESA_SHADER_FRAGMENT) | |||
981 | // { | |||
982 | // // Special workaround for GLES 2.0 LOD samplers to prevent a lot of debug spew. | |||
983 | // const glsl_precision prec = ir->sampler->get_precision(); | |||
984 | // const char *precString = ""; | |||
985 | // // Sampler bitfield is 7 bits, so use 0-7 for lowp, 8-15 for mediump and 16-23 for highp. | |||
986 | // int position = (int)sampler_dim; | |||
987 | // switch (prec) | |||
988 | // { | |||
989 | // case glsl_precision_high: | |||
990 | // position += 16; | |||
991 | // precString = "_high_"; | |||
992 | // break; | |||
993 | // case glsl_precision_medium: | |||
994 | // position += 8; | |||
995 | // precString = "_medium_"; | |||
996 | // break; | |||
997 | // case glsl_precision_low: | |||
998 | // default: | |||
999 | // precString = "_low_"; | |||
1000 | // break; | |||
1001 | // } | |||
1002 | // buffer.asprintf_append("impl%s", precString); | |||
1003 | // if (is_proj) | |||
1004 | // uses_texlodproj_impl |= (1 << position); | |||
1005 | // else | |||
1006 | // uses_texlod_impl |= (1 << position); | |||
1007 | // } | |||
1008 | ||||
1009 | ||||
1010 | // texture function name | |||
1011 | //ACS: shadow lookups and lookups with dimensionality included in the name were deprecated in 130 | |||
1012 | if(state->language_version<130) | |||
1013 | { | |||
1014 | buffer.asprintf_append ("%s", is_shadow ? "shadow" : "texture"); | |||
1015 | buffer.asprintf_append ("%s", tex_sampler_dim_name[sampler_dim]); | |||
1016 | } | |||
1017 | else | |||
1018 | { | |||
1019 | if (ir->op == ir_txf || ir->op == ir_txf_ms) | |||
1020 | buffer.asprintf_append ("texelFetch"); | |||
1021 | else | |||
1022 | buffer.asprintf_append ("texture"); | |||
1023 | } | |||
1024 | ||||
1025 | if (is_array && state->EXT_texture_array_enable) | |||
1026 | buffer.asprintf_append ("Array"); | |||
1027 | ||||
1028 | if (is_proj) | |||
1029 | buffer.asprintf_append ("Proj"); | |||
1030 | if (ir->op == ir_txl) | |||
1031 | buffer.asprintf_append ("Lod"); | |||
1032 | if (ir->op == ir_txd) | |||
1033 | buffer.asprintf_append ("Grad"); | |||
1034 | if (ir->offset != NULL__null) | |||
1035 | buffer.asprintf_append ("Offset"); | |||
1036 | ||||
1037 | if (state->es_shader) | |||
1038 | { | |||
1039 | // FIXME extension | |||
1040 | // if ( (is_shadow && state->EXT_shadow_samplers_enable) || | |||
1041 | // (ir->op == ir_txl && state->EXT_shader_texture_lod_enable) ) | |||
1042 | // { | |||
1043 | // buffer.asprintf_append ("EXT"); | |||
1044 | // } | |||
1045 | } | |||
1046 | ||||
1047 | if(ir->op == ir_txd) | |||
1048 | { | |||
1049 | // FIXME extension | |||
1050 | // if(state->es_shader && state->EXT_shader_texture_lod_enable) | |||
1051 | // buffer.asprintf_append ("EXT"); | |||
1052 | // else if(!state->es_shader && state->ARB_shader_texture_lod_enable) | |||
1053 | // buffer.asprintf_append ("ARB"); | |||
1054 | } | |||
1055 | ||||
1056 | buffer.asprintf_append (" ("); | |||
1057 | ||||
1058 | // sampler | |||
1059 | ir->sampler->accept(this); | |||
1060 | buffer.asprintf_append (", "); | |||
1061 | ||||
1062 | // texture coordinate | |||
1063 | ir->coordinate->accept(this); | |||
1064 | ||||
1065 | // lod | |||
1066 | if (ir->op == ir_txl || ir->op == ir_txf) | |||
1067 | { | |||
1068 | buffer.asprintf_append (", "); | |||
1069 | ir->lod_info.lod->accept(this); | |||
1070 | } | |||
1071 | ||||
1072 | // sample index | |||
1073 | if (ir->op == ir_txf_ms) | |||
1074 | { | |||
1075 | buffer.asprintf_append (", "); | |||
1076 | ir->lod_info.sample_index->accept(this); | |||
1077 | } | |||
1078 | ||||
1079 | // grad | |||
1080 | if (ir->op == ir_txd) | |||
1081 | { | |||
1082 | buffer.asprintf_append (", "); | |||
1083 | ir->lod_info.grad.dPdx->accept(this); | |||
1084 | buffer.asprintf_append (", "); | |||
1085 | ir->lod_info.grad.dPdy->accept(this); | |||
1086 | } | |||
1087 | ||||
1088 | // texel offset | |||
1089 | if (ir->offset != NULL__null) | |||
1090 | { | |||
1091 | buffer.asprintf_append (", "); | |||
1092 | ir->offset->accept(this); | |||
1093 | } | |||
1094 | ||||
1095 | // lod bias | |||
1096 | if (ir->op == ir_txb) | |||
1097 | { | |||
1098 | buffer.asprintf_append (", "); | |||
1099 | ir->lod_info.bias->accept(this); | |||
1100 | } | |||
1101 | ||||
1102 | /* | |||
1103 | ||||
1104 | ||||
1105 | if (ir->op != ir_txf) { | |||
1106 | if (ir->projector) | |||
1107 | ir->projector->accept(this); | |||
1108 | else | |||
1109 | buffer.asprintf_append ("1"); | |||
1110 | ||||
1111 | if (ir->shadow_comparitor) { | |||
1112 | buffer.asprintf_append (" "); | |||
1113 | ir->shadow_comparitor->accept(this); | |||
1114 | } else { | |||
1115 | buffer.asprintf_append (" ()"); | |||
1116 | } | |||
1117 | } | |||
1118 | ||||
1119 | buffer.asprintf_append (" "); | |||
1120 | switch (ir->op) | |||
1121 | { | |||
1122 | case ir_tex: | |||
1123 | break; | |||
1124 | case ir_txb: | |||
1125 | ir->lod_info.bias->accept(this); | |||
1126 | break; | |||
1127 | case ir_txl: | |||
1128 | case ir_txf: | |||
1129 | ir->lod_info.lod->accept(this); | |||
1130 | break; | |||
1131 | case ir_txd: | |||
1132 | buffer.asprintf_append ("("); | |||
1133 | ir->lod_info.grad.dPdx->accept(this); | |||
1134 | buffer.asprintf_append (" "); | |||
1135 | ir->lod_info.grad.dPdy->accept(this); | |||
1136 | buffer.asprintf_append (")"); | |||
1137 | break; | |||
1138 | }; | |||
1139 | */ | |||
1140 | buffer.asprintf_append (")"); | |||
1141 | } | |||
1142 | ||||
1143 | ||||
1144 | void ir_print_glsl_visitor::visit(ir_swizzle *ir) | |||
1145 | { | |||
1146 | const unsigned swiz[4] = { | |||
1147 | ir->mask.x, | |||
1148 | ir->mask.y, | |||
1149 | ir->mask.z, | |||
1150 | ir->mask.w, | |||
1151 | }; | |||
1152 | ||||
1153 | if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type || ir->val->type == glsl_type::uint_type) | |||
1154 | { | |||
1155 | if (ir->mask.num_components != 1) | |||
1156 | { | |||
1157 | print_type(buffer, ir->type, true); | |||
1158 | buffer.asprintf_append ("("); | |||
1159 | } | |||
1160 | } | |||
1161 | ||||
1162 | ir->val->accept(this); | |||
1163 | ||||
1164 | if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type || ir->val->type == glsl_type::uint_type) | |||
1165 | { | |||
1166 | if (ir->mask.num_components != 1) | |||
1167 | { | |||
1168 | buffer.asprintf_append (")"); | |||
1169 | } | |||
1170 | return; | |||
1171 | } | |||
1172 | ||||
1173 | // Swizzling scalar types is not allowed so just return now. | |||
1174 | if (ir->val->type->vector_elements == 1) | |||
1175 | return; | |||
1176 | ||||
1177 | buffer.asprintf_append ("."); | |||
1178 | for (unsigned i = 0; i < ir->mask.num_components; i++) { | |||
1179 | buffer.asprintf_append ("%c", "xyzw"[swiz[i]]); | |||
1180 | } | |||
1181 | } | |||
1182 | ||||
1183 | ||||
1184 | void ir_print_glsl_visitor::visit(ir_dereference_variable *ir) | |||
1185 | { | |||
1186 | ir_variable *var = ir->variable_referenced(); | |||
1187 | print_var_name (var); | |||
1188 | } | |||
1189 | ||||
1190 | ||||
1191 | void ir_print_glsl_visitor::visit(ir_dereference_array *ir) | |||
1192 | { | |||
1193 | ir->array->accept(this); | |||
1194 | buffer.asprintf_append ("["); | |||
1195 | ir->array_index->accept(this); | |||
1196 | buffer.asprintf_append ("]"); | |||
1197 | } | |||
1198 | ||||
1199 | ||||
1200 | void ir_print_glsl_visitor::visit(ir_dereference_record *ir) | |||
1201 | { | |||
1202 | ir->record->accept(this); | |||
1203 | const char *field_name = ir->record->type->fields.structure[ir->field_idx].name; | |||
1204 | buffer.asprintf_append (".%s", field_name); | |||
1205 | } | |||
1206 | ||||
1207 | ||||
1208 | bool ir_print_glsl_visitor::try_print_array_assignment (ir_dereference* lhs, ir_rvalue* rhs) | |||
1209 | { | |||
1210 | if (this->state->language_version >= 120) | |||
1211 | return false; | |||
1212 | ir_dereference_variable* rhsarr = rhs->as_dereference_variable(); | |||
1213 | if (rhsarr == NULL__null) | |||
1214 | return false; | |||
1215 | const glsl_type* lhstype = lhs->type; | |||
1216 | const glsl_type* rhstype = rhsarr->type; | |||
1217 | if (!lhstype->is_array() || !rhstype->is_array()) | |||
1218 | return false; | |||
1219 | if (lhstype->array_size() != rhstype->array_size()) | |||
1220 | return false; | |||
1221 | if (lhstype->base_type != rhstype->base_type) | |||
1222 | return false; | |||
1223 | ||||
1224 | const unsigned size = rhstype->array_size(); | |||
1225 | for (unsigned i = 0; i < size; i++) | |||
1226 | { | |||
1227 | lhs->accept(this); | |||
1228 | buffer.asprintf_append ("[%d]=", i); | |||
1229 | rhs->accept(this); | |||
1230 | buffer.asprintf_append ("[%d]", i); | |||
1231 | if (i != size-1) | |||
1232 | buffer.asprintf_append (";"); | |||
1233 | } | |||
1234 | return true; | |||
1235 | } | |||
1236 | ||||
1237 | void ir_print_glsl_visitor::emit_assignment_part (ir_dereference* lhs, ir_rvalue* rhs, unsigned write_mask, ir_rvalue* dstIndex) | |||
1238 | { | |||
1239 | lhs->accept(this); | |||
1240 | ||||
1241 | if (dstIndex) | |||
1242 | { | |||
1243 | // if dst index is a constant, then emit a swizzle | |||
1244 | ir_constant* dstConst = dstIndex->as_constant(); | |||
1245 | if (dstConst) | |||
1246 | { | |||
1247 | const char* comps = "xyzw"; | |||
1248 | char comp = comps[dstConst->get_int_component(0)]; | |||
1249 | buffer.asprintf_append (".%c", comp); | |||
1250 | } | |||
1251 | else | |||
1252 | { | |||
1253 | buffer.asprintf_append ("["); | |||
1254 | dstIndex->accept(this); | |||
1255 | buffer.asprintf_append ("]"); | |||
1256 | } | |||
1257 | } | |||
1258 | ||||
1259 | char mask[5]; | |||
1260 | unsigned j = 0; | |||
1261 | const glsl_type* lhsType = lhs->type; | |||
1262 | const glsl_type* rhsType = rhs->type; | |||
1263 | if (!dstIndex && lhsType->matrix_columns <= 1 && lhsType->vector_elements > 1 && write_mask != (1<<lhsType->vector_elements)-1) | |||
1264 | { | |||
1265 | for (unsigned i = 0; i < 4; i++) { | |||
1266 | if ((write_mask & (1 << i)) != 0) { | |||
1267 | mask[j] = "xyzw"[i]; | |||
1268 | j++; | |||
1269 | } | |||
1270 | } | |||
1271 | lhsType = glsl_type::get_instance(lhsType->base_type, j, 1); | |||
1272 | } | |||
1273 | mask[j] = '\0'; | |||
1274 | bool hasWriteMask = false; | |||
1275 | if (mask[0]) | |||
1276 | { | |||
1277 | buffer.asprintf_append (".%s", mask); | |||
1278 | hasWriteMask = true; | |||
1279 | } | |||
1280 | ||||
1281 | buffer.asprintf_append (" = "); | |||
1282 | ||||
1283 | bool typeMismatch = !dstIndex && (lhsType != rhsType); | |||
1284 | const bool addSwizzle = hasWriteMask && typeMismatch; | |||
1285 | if (typeMismatch) | |||
1286 | { | |||
1287 | if (!addSwizzle) | |||
1288 | print_type(buffer, lhsType, true); | |||
1289 | buffer.asprintf_append ("("); | |||
1290 | } | |||
1291 | ||||
1292 | rhs->accept(this); | |||
1293 | ||||
1294 | if (typeMismatch) | |||
1295 | { | |||
1296 | buffer.asprintf_append (")"); | |||
1297 | if (addSwizzle) | |||
1298 | buffer.asprintf_append (".%s", mask); | |||
1299 | } | |||
1300 | } | |||
1301 | ||||
1302 | ||||
1303 | // Try to print (X = X + const) as (X += const), mostly to satisfy | |||
1304 | // OpenGL ES 2.0 loop syntax restrictions. | |||
1305 | static bool try_print_increment (ir_print_glsl_visitor* vis, ir_assignment* ir) | |||
1306 | { | |||
1307 | if (ir->condition) | |||
1308 | return false; | |||
1309 | ||||
1310 | // Needs to be + on rhs | |||
1311 | ir_expression* rhsOp = ir->rhs->as_expression(); | |||
1312 | if (!rhsOp || rhsOp->operation != ir_binop_add) | |||
1313 | return false; | |||
1314 | ||||
1315 | // Needs to write to whole variable | |||
1316 | ir_variable* lhsVar = ir->whole_variable_written(); | |||
1317 | if (lhsVar == NULL__null) | |||
1318 | return false; | |||
1319 | ||||
1320 | // Types must match | |||
1321 | if (ir->lhs->type != ir->rhs->type) | |||
1322 | return false; | |||
1323 | ||||
1324 | // Type must be scalar | |||
1325 | if (!ir->lhs->type->is_scalar()) | |||
1326 | return false; | |||
1327 | ||||
1328 | // rhs0 must be variable deref, same one as lhs | |||
1329 | ir_dereference_variable* rhsDeref = rhsOp->operands[0]->as_dereference_variable(); | |||
1330 | if (rhsDeref == NULL__null) | |||
1331 | return false; | |||
1332 | if (lhsVar != rhsDeref->var) | |||
1333 | return false; | |||
1334 | ||||
1335 | // rhs1 must be a constant | |||
1336 | ir_constant* rhsConst = rhsOp->operands[1]->as_constant(); | |||
1337 | if (!rhsConst) | |||
1338 | return false; | |||
1339 | ||||
1340 | // print variable name | |||
1341 | ir->lhs->accept (vis); | |||
1342 | ||||
1343 | // print ++ or +=const | |||
1344 | if (ir->lhs->type->base_type <= GLSL_TYPE_INT && rhsConst->is_one()) | |||
1345 | { | |||
1346 | vis->buffer.asprintf_append ("++"); | |||
1347 | } | |||
1348 | else | |||
1349 | { | |||
1350 | vis->buffer.asprintf_append(" += "); | |||
1351 | rhsConst->accept (vis); | |||
1352 | } | |||
1353 | ||||
1354 | return true; | |||
1355 | } | |||
1356 | ||||
1357 | ||||
1358 | void ir_print_glsl_visitor::visit(ir_assignment *ir) | |||
1359 | { | |||
1360 | // if this is a loop induction variable initial assignment, and we aren't inside loop body: | |||
1361 | // do not print it (will be printed when inside loop body) | |||
1362 | if (!inside_loop_body) | |||
1363 | { | |||
1364 | ir_variable* whole_var = ir->whole_variable_written(); | |||
1365 | if (!ir->condition && whole_var) | |||
1366 | { | |||
1367 | // FIXME | |||
1368 | // loop_variable_state* inductor_state = loopstate->get_for_inductor(whole_var); | |||
1369 | // if (inductor_state && inductor_state->private_induction_variable_count == 1 && | |||
1370 | // can_emit_canonical_for(inductor_state)) | |||
1371 | // { | |||
1372 | // skipped_this_ir = true; | |||
1373 | // return; | |||
1374 | // } | |||
1375 | } | |||
1376 | } | |||
1377 | ||||
1378 | // assignments in global scope are postponed to main function | |||
1379 | if (this->mode != kPrintGlslNone) | |||
1380 | { | |||
1381 | // FIXME: This assertion gets tripped when encountering const variable | |||
1382 | // initializations which occur after the main() function definition. | |||
1383 | // assert (!this->globals->main_function_done); | |||
1384 | this->globals->global_assignements.push_tail (new(this->globals->mem_ctx) ga_entry(ir)); | |||
1385 | buffer.asprintf_append ("//"); // for the ; that will follow (ugly, I know) | |||
1386 | return; | |||
1387 | } | |||
1388 | ||||
1389 | // if RHS is ir_triop_vector_insert, then we have to do some special dance. If source expression is: | |||
1390 | // dst = vector_insert (a, b, idx) | |||
1391 | // then emit it like: | |||
1392 | // dst = a; | |||
1393 | // dst.idx = b; | |||
1394 | ir_expression* rhsOp = ir->rhs->as_expression(); | |||
1395 | if (rhsOp && rhsOp->operation == ir_triop_vector_insert) | |||
1396 | { | |||
1397 | // skip assignment if lhs and rhs would be the same | |||
1398 | bool skip_assign = false; | |||
1399 | ir_dereference_variable* lhsDeref = ir->lhs->as_dereference_variable(); | |||
1400 | ir_dereference_variable* rhsDeref = rhsOp->operands[0]->as_dereference_variable(); | |||
1401 | if (lhsDeref && rhsDeref) | |||
1402 | { | |||
1403 | if (lhsDeref->var == rhsDeref->var) | |||
1404 | skip_assign = true; | |||
1405 | } | |||
1406 | ||||
1407 | if (!skip_assign) | |||
1408 | { | |||
1409 | emit_assignment_part(ir->lhs, rhsOp->operands[0], ir->write_mask, NULL__null); | |||
1410 | buffer.asprintf_append ("; "); | |||
1411 | } | |||
1412 | emit_assignment_part(ir->lhs, rhsOp->operands[1], ir->write_mask, rhsOp->operands[2]); | |||
1413 | return; | |||
1414 | } | |||
1415 | ||||
1416 | if (try_print_increment (this, ir)) | |||
1417 | return; | |||
1418 | ||||
1419 | if (try_print_array_assignment (ir->lhs, ir->rhs)) | |||
1420 | return; | |||
1421 | ||||
1422 | if (ir->condition) | |||
1423 | { | |||
1424 | if (ir->condition) | |||
1425 | { | |||
1426 | buffer.asprintf_append ("if ("); | |||
1427 | ir->condition->accept(this); | |||
1428 | buffer.asprintf_append (") "); | |||
1429 | } | |||
1430 | } | |||
1431 | ||||
1432 | emit_assignment_part (ir->lhs, ir->rhs, ir->write_mask, NULL__null); | |||
1433 | } | |||
1434 | ||||
1435 | ||||
1436 | #ifdef _MSC_VER | |||
1437 | #define isnan(x) _isnan(x) | |||
1438 | #define isinf(x) (!_finite(x)) | |||
1439 | #endif | |||
1440 | ||||
1441 | #define fpcheck(x)(isnan(x) || isinf(x)) (isnan(x) || isinf(x)) | |||
1442 | ||||
1443 | void print_float (string_buffer& buffer, float f) | |||
1444 | { | |||
1445 | // Kind of roundabout way, but this is to satisfy two things: | |||
1446 | // * MSVC and gcc-based compilers differ a bit in how they treat float | |||
1447 | // widht/precision specifiers. Want to match for tests. | |||
1448 | // * GLSL (early version at least) require floats to have ".0" or | |||
1449 | // exponential notation. | |||
1450 | char tmp[64]; | |||
1451 | snprintf(tmp, 64, "%.7g", f); | |||
1452 | ||||
1453 | char* posE = NULL__null; | |||
1454 | posE = strchr(tmp, 'e'); | |||
1455 | if (!posE) | |||
1456 | posE = strchr(tmp, 'E'); | |||
1457 | ||||
1458 | // snprintf formats infinity as inf.0 or -inf.0, which isn't useful here. | |||
1459 | // GLSL has no infinity constant so print an equivalent expression instead. | |||
1460 | if (f == std::numeric_limits<float>::infinity()) | |||
1461 | strcpy(tmp, "(1.0/0.0)"); | |||
1462 | ||||
1463 | if (f == -std::numeric_limits<float>::infinity()) | |||
1464 | strcpy(tmp, "(-1.0/0.0)"); | |||
1465 | ||||
1466 | // Do similar thing for NaN | |||
1467 | if (isnan(f)) | |||
1468 | strcpy(tmp, "(0.0/0.0)"); | |||
1469 | ||||
1470 | #if _MSC_VER | |||
1471 | // While gcc would print something like 1.0e+07, MSVC will print 1.0e+007 - | |||
1472 | // only for exponential notation, it seems, will add one extra useless zero. Let's try to remove | |||
1473 | // that so compiler output matches. | |||
1474 | if (posE != NULL__null) | |||
1475 | { | |||
1476 | if((posE[1] == '+' || posE[1] == '-') && posE[2] == '0') | |||
1477 | { | |||
1478 | char* p = posE+2; | |||
1479 | while (p[0]) | |||
1480 | { | |||
1481 | p[0] = p[1]; | |||
1482 | ++p; | |||
1483 | } | |||
1484 | } | |||
1485 | } | |||
1486 | #endif | |||
1487 | ||||
1488 | buffer.asprintf_append ("%s", tmp); | |||
1489 | ||||
1490 | // need to append ".0"? | |||
1491 | if (!strchr(tmp,'.') && (posE == NULL__null)) | |||
1492 | buffer.asprintf_append(".0"); | |||
1493 | } | |||
1494 | ||||
1495 | void ir_print_glsl_visitor::visit(ir_constant *ir) | |||
1496 | { | |||
1497 | const glsl_type* type = ir->type; | |||
1498 | ||||
1499 | if (type == glsl_type::float_type) | |||
1500 | { | |||
1501 | if (fpcheck(ir->value.f[0])(isnan(ir->value.f[0]) || isinf(ir->value.f[0]))) | |||
1502 | { | |||
1503 | // Non-printable float. If we have bit conversions, we're fine. otherwise do hand-wavey things in print_float(). | |||
1504 | if ((state->es_shader && (state->language_version >= 300)) | |||
1505 | || (state->language_version >= 330) | |||
1506 | || (state->ARB_shader_bit_encoding_enable)) | |||
1507 | { | |||
1508 | buffer.asprintf_append("uintBitsToFloat(%uu)", ir->value.u[0]); | |||
1509 | return; | |||
1510 | } | |||
1511 | } | |||
1512 | ||||
1513 | print_float (buffer, ir->value.f[0]); | |||
1514 | return; | |||
1515 | } | |||
1516 | else if (type == glsl_type::int_type) | |||
1517 | { | |||
1518 | // Need special handling for INT_MIN | |||
1519 | if (ir->value.u[0] == 0x80000000) | |||
1520 | buffer.asprintf_append("int(0x%X)", ir->value.i[0]); | |||
1521 | else | |||
1522 | buffer.asprintf_append ("%d", ir->value.i[0]); | |||
1523 | return; | |||
1524 | } | |||
1525 | else if (type == glsl_type::uint_type) | |||
1526 | { | |||
1527 | // ES 2.0 doesn't support uints, neither does GLSL < 130 | |||
1528 | if ((state->es_shader && (state->language_version < 300)) | |||
1529 | || (state->language_version < 130)) | |||
1530 | buffer.asprintf_append("%u", ir->value.u[0]); | |||
1531 | else | |||
1532 | { | |||
1533 | // Old Adreno drivers try to be smart with '0u' and treat that as 'const int'. Sigh. | |||
1534 | if (ir->value.u[0] == 0) | |||
1535 | buffer.asprintf_append("uint(0)"); | |||
1536 | else | |||
1537 | buffer.asprintf_append("%uu", ir->value.u[0]); | |||
1538 | } | |||
1539 | return; | |||
1540 | } | |||
1541 | ||||
1542 | const glsl_type *const base_type = ir->type->get_base_type(); | |||
1543 | ||||
1544 | print_type(buffer, type, true); | |||
1545 | buffer.asprintf_append ("("); | |||
1546 | ||||
1547 | if (ir->type->is_array()) { | |||
1548 | for (unsigned i = 0; i < ir->type->length; i++) | |||
1549 | { | |||
1550 | if (i != 0) | |||
1551 | buffer.asprintf_append (", "); | |||
1552 | ir->get_array_element(i)->accept(this); | |||
1553 | } | |||
1554 | } else if (ir->type->is_struct()) { | |||
1555 | for (unsigned i = 0; i < ir->type->length; i++) { | |||
1556 | if (i > 0) | |||
1557 | buffer.asprintf_append (", "); | |||
1558 | ir->const_elements[i]->accept(this); | |||
1559 | } | |||
1560 | ||||
1561 | }else { | |||
1562 | bool first = true; | |||
1563 | for (unsigned i = 0; i < ir->type->components(); i++) { | |||
1564 | if (!first) | |||
1565 | buffer.asprintf_append (", "); | |||
1566 | first = false; | |||
1567 | switch (base_type->base_type) { | |||
1568 | case GLSL_TYPE_UINT: | |||
1569 | { | |||
1570 | // ES 2.0 doesn't support uints, neither does GLSL < 130 | |||
1571 | if ((state->es_shader && (state->language_version < 300)) | |||
1572 | || (state->language_version < 130)) | |||
1573 | buffer.asprintf_append("%u", ir->value.u[i]); | |||
1574 | else | |||
1575 | buffer.asprintf_append("%uu", ir->value.u[i]); | |||
1576 | break; | |||
1577 | } | |||
1578 | case GLSL_TYPE_INT: | |||
1579 | { | |||
1580 | // Need special handling for INT_MIN | |||
1581 | if (ir->value.u[i] == 0x80000000) | |||
1582 | buffer.asprintf_append("int(0x%X)", ir->value.i[i]); | |||
1583 | else | |||
1584 | buffer.asprintf_append("%d", ir->value.i[i]); | |||
1585 | break; | |||
1586 | } | |||
1587 | case GLSL_TYPE_FLOAT: print_float(buffer, ir->value.f[i]); break; | |||
1588 | case GLSL_TYPE_BOOL: buffer.asprintf_append ("%d", ir->value.b[i]); break; | |||
1589 | default: assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | |||
1590 | } | |||
1591 | } | |||
1592 | } | |||
1593 | buffer.asprintf_append (")"); | |||
1594 | } | |||
1595 | ||||
1596 | ||||
1597 | void | |||
1598 | ir_print_glsl_visitor::visit(ir_call *ir) | |||
1599 | { | |||
1600 | // calls in global scope are postponed to main function | |||
1601 | if (this->mode != kPrintGlslNone) | |||
1602 | { | |||
1603 | assert (!this->globals->main_function_done)(static_cast <bool> (!this->globals->main_function_done ) ? void (0) : __assert_fail ("!this->globals->main_function_done" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | |||
1604 | this->globals->global_assignements.push_tail (new(this->globals->mem_ctx) ga_entry(ir)); | |||
1605 | buffer.asprintf_append ("//"); // for the ; that will follow (ugly, I know) | |||
1606 | return; | |||
1607 | } | |||
1608 | ||||
1609 | if (ir->return_deref) | |||
1610 | { | |||
1611 | visit(ir->return_deref); | |||
1612 | buffer.asprintf_append (" = "); | |||
1613 | } | |||
1614 | ||||
1615 | buffer.asprintf_append ("%s (", ir->callee_name()); | |||
1616 | bool first = true; | |||
1617 | foreach_in_list(ir_instruction, inst, &ir->actual_parameters)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((& ir->actual_parameters)->head_sentinel.next) ? (ir_instruction *) ((&ir->actual_parameters)->head_sentinel.next) : __null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel ((inst)->next) ? (ir_instruction *) ((inst)->next) : __null )) { | |||
1618 | if (!first) | |||
1619 | buffer.asprintf_append (", "); | |||
1620 | inst->accept(this); | |||
1621 | first = false; | |||
1622 | } | |||
1623 | buffer.asprintf_append (")"); | |||
1624 | } | |||
1625 | ||||
1626 | ||||
1627 | void | |||
1628 | ir_print_glsl_visitor::visit(ir_return *ir) | |||
1629 | { | |||
1630 | buffer.asprintf_append ("return"); | |||
1631 | ||||
1632 | ir_rvalue *const value = ir->get_value(); | |||
1633 | if (value) { | |||
1634 | buffer.asprintf_append (" "); | |||
1635 | value->accept(this); | |||
1636 | } | |||
1637 | } | |||
1638 | ||||
1639 | ||||
1640 | void | |||
1641 | ir_print_glsl_visitor::visit(ir_discard *ir) | |||
1642 | { | |||
1643 | buffer.asprintf_append ("discard"); | |||
1644 | ||||
1645 | if (ir->condition != NULL__null) { | |||
1646 | buffer.asprintf_append (" TODO "); | |||
1647 | ir->condition->accept(this); | |||
1648 | } | |||
1649 | } | |||
1650 | ||||
1651 | void | |||
1652 | ir_print_glsl_visitor::visit(ir_demote *ir) | |||
1653 | { | |||
1654 | buffer.asprintf_append ("discard-TODO"); | |||
1655 | } | |||
1656 | ||||
1657 | void | |||
1658 | ir_print_glsl_visitor::visit(ir_if *ir) | |||
1659 | { | |||
1660 | buffer.asprintf_append ("if ("); | |||
1661 | ir->condition->accept(this); | |||
1662 | ||||
1663 | buffer.asprintf_append (") {\n"); | |||
1664 | indentation++; previous_skipped = false; | |||
1665 | ||||
1666 | ||||
1667 | foreach_in_list(ir_instruction, inst, &ir->then_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((& ir->then_instructions)->head_sentinel.next) ? (ir_instruction *) ((&ir->then_instructions)->head_sentinel.next) : __null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel ((inst)->next) ? (ir_instruction *) ((inst)->next) : __null )) { | |||
1668 | indent(); | |||
1669 | inst->accept(this); | |||
1670 | end_statement_line(); | |||
1671 | } | |||
1672 | ||||
1673 | indentation--; | |||
1674 | indent(); | |||
1675 | buffer.asprintf_append ("}"); | |||
1676 | ||||
1677 | if (!ir->else_instructions.is_empty()) | |||
1678 | { | |||
1679 | buffer.asprintf_append (" else {\n"); | |||
1680 | indentation++; previous_skipped = false; | |||
1681 | ||||
1682 | foreach_in_list(ir_instruction, inst, &ir->else_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((& ir->else_instructions)->head_sentinel.next) ? (ir_instruction *) ((&ir->else_instructions)->head_sentinel.next) : __null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel ((inst)->next) ? (ir_instruction *) ((inst)->next) : __null )) { | |||
1683 | indent(); | |||
1684 | inst->accept(this); | |||
1685 | end_statement_line(); | |||
1686 | } | |||
1687 | indentation--; | |||
1688 | indent(); | |||
1689 | buffer.asprintf_append ("}"); | |||
1690 | } | |||
1691 | } | |||
1692 | ||||
1693 | bool ir_print_glsl_visitor::can_emit_canonical_for (loop_variable_state *ls) | |||
1694 | { | |||
1695 | if (ls == NULL__null) | |||
1696 | return false; | |||
1697 | ||||
1698 | if (ls->induction_variables.is_empty()) | |||
1699 | return false; | |||
1700 | ||||
1701 | if (ls->terminators.is_empty()) | |||
1702 | return false; | |||
1703 | ||||
1704 | // only support for loops with one terminator condition | |||
1705 | int terminatorCount = ls->terminators.length(); | |||
1706 | if (terminatorCount != 1) | |||
1707 | return false; | |||
1708 | ||||
1709 | return true; | |||
1710 | } | |||
1711 | ||||
1712 | bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir) | |||
1713 | { | |||
1714 | loop_variable_state* const ls = this->loopstate->get(ir); | |||
1715 | ||||
1716 | if (!can_emit_canonical_for(ls)) | |||
1717 | return false; | |||
1718 | ||||
1719 | hash_table* terminator_hash = _mesa_hash_table_create(nullptr, _mesa_hash_pointer, _mesa_key_pointer_equal); | |||
1720 | hash_table* induction_hash = _mesa_hash_table_create(nullptr, _mesa_hash_pointer, _mesa_key_pointer_equal); | |||
1721 | ||||
1722 | buffer.asprintf_append("for ("); | |||
1723 | inside_loop_body = true; | |||
1724 | ||||
1725 | // emit loop induction variable declarations. | |||
1726 | // only for loops with single induction variable, to avoid cases of different types of them | |||
1727 | // FIXME | |||
1728 | // if (ls->private_induction_variable_count == 1) | |||
1729 | // { | |||
1730 | // foreach_in_list(loop_variable, indvar, &ls->induction_variables) | |||
1731 | // { | |||
1732 | // if (!this->loopstate->get_for_inductor(indvar->var)) | |||
1733 | // continue; | |||
1734 | ||||
1735 | // ir_variable* var = indvar->var; | |||
1736 | // print_precision (var, var->type); | |||
1737 | // print_type(buffer, var->type, false); | |||
1738 | // buffer.asprintf_append (" "); | |||
1739 | // print_var_name (var); | |||
1740 | // print_type_post(buffer, var->type, false); | |||
1741 | // if (indvar->initial_value) | |||
1742 | // { | |||
1743 | // buffer.asprintf_append (" = "); | |||
1744 | // // if the var is an array add the proper initializer | |||
1745 | // if(var->type->is_vector()) | |||
1746 | // { | |||
1747 | // print_type(buffer, var->type, false); | |||
1748 | // buffer.asprintf_append ("("); | |||
1749 | // } | |||
1750 | // indvar->initial_value->accept(this); | |||
1751 | // if(var->type->is_vector()) | |||
1752 | // { | |||
1753 | // buffer.asprintf_append (")"); | |||
1754 | // } | |||
1755 | // } | |||
1756 | // } | |||
1757 | // } | |||
1758 | buffer.asprintf_append("; "); | |||
1759 | ||||
1760 | // emit loop terminating conditions | |||
1761 | foreach_in_list(loop_terminator, term, &ls->terminators)for (loop_terminator *term = (!exec_node_is_tail_sentinel((& ls->terminators)->head_sentinel.next) ? (loop_terminator *) ((&ls->terminators)->head_sentinel.next) : __null ); (term) != __null; (term) = (!exec_node_is_tail_sentinel((term )->next) ? (loop_terminator *) ((term)->next) : __null) ) | |||
1762 | { | |||
1763 | _mesa_hash_table_insert(terminator_hash, term->ir, term); | |||
1764 | ||||
1765 | // IR has conditions in the form of "if (x) break", | |||
1766 | // whereas for loop needs them negated, in the form | |||
1767 | // if "while (x) continue the loop". | |||
1768 | // See if we can print them using syntax that reads nice. | |||
1769 | bool handled = false; | |||
1770 | ir_expression* term_expr = term->ir->condition->as_expression(); | |||
1771 | if (term_expr) | |||
1772 | { | |||
1773 | // Binary comparison conditions | |||
1774 | const char* termOp = NULL__null; | |||
1775 | switch (term_expr->operation) | |||
1776 | { | |||
1777 | case ir_binop_less: termOp = ">="; break; | |||
1778 | case ir_binop_gequal: termOp = "<"; break; | |||
1779 | case ir_binop_equal: termOp = "!="; break; | |||
1780 | case ir_binop_nequal: termOp = "=="; break; | |||
1781 | default: break; | |||
1782 | } | |||
1783 | if (termOp != NULL__null) | |||
1784 | { | |||
1785 | term_expr->operands[0]->accept(this); | |||
1786 | buffer.asprintf_append(" %s ", termOp); | |||
1787 | term_expr->operands[1]->accept(this); | |||
1788 | handled = true; | |||
1789 | } | |||
1790 | ||||
1791 | // Unary logic not | |||
1792 | if (!handled && term_expr->operation == ir_unop_logic_not) | |||
1793 | { | |||
1794 | term_expr->operands[0]->accept(this); | |||
1795 | handled = true; | |||
1796 | } | |||
1797 | } | |||
1798 | ||||
1799 | // More complex condition, print as "!(x)" | |||
1800 | if (!handled) | |||
1801 | { | |||
1802 | buffer.asprintf_append("!("); | |||
1803 | term->ir->condition->accept(this); | |||
1804 | buffer.asprintf_append(")"); | |||
1805 | } | |||
1806 | } | |||
1807 | buffer.asprintf_append("; "); | |||
1808 | ||||
1809 | // emit loop induction variable updates | |||
1810 | bool first = true; | |||
1811 | foreach_in_list(loop_variable, indvar, &ls->induction_variables)for (loop_variable *indvar = (!exec_node_is_tail_sentinel((& ls->induction_variables)->head_sentinel.next) ? (loop_variable *) ((&ls->induction_variables)->head_sentinel.next ) : __null); (indvar) != __null; (indvar) = (!exec_node_is_tail_sentinel ((indvar)->next) ? (loop_variable *) ((indvar)->next) : __null)) | |||
1812 | { | |||
1813 | _mesa_hash_table_insert(induction_hash, indvar->first_assignment, indvar); | |||
1814 | if (!first) | |||
1815 | buffer.asprintf_append(", "); | |||
1816 | visit(indvar->first_assignment); | |||
1817 | first = false; | |||
1818 | } | |||
1819 | buffer.asprintf_append(") {\n"); | |||
1820 | ||||
1821 | inside_loop_body = false; | |||
1822 | ||||
1823 | // emit loop body | |||
1824 | indentation++; previous_skipped = false; | |||
1825 | foreach_in_list(ir_instruction, inst, &ir->body_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((& ir->body_instructions)->head_sentinel.next) ? (ir_instruction *) ((&ir->body_instructions)->head_sentinel.next) : __null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel ((inst)->next) ? (ir_instruction *) ((inst)->next) : __null )) { | |||
1826 | ||||
1827 | // skip termination & induction statements, | |||
1828 | // they are part of "for" clause | |||
1829 | if (_mesa_hash_table_search(terminator_hash, inst)) | |||
1830 | continue; | |||
1831 | if (_mesa_hash_table_search(induction_hash, inst)) | |||
1832 | continue; | |||
1833 | ||||
1834 | indent(); | |||
1835 | inst->accept(this); | |||
1836 | end_statement_line(); | |||
1837 | } | |||
1838 | indentation--; | |||
1839 | ||||
1840 | indent(); | |||
1841 | buffer.asprintf_append("}"); | |||
1842 | ||||
1843 | _mesa_hash_table_destroy (terminator_hash, nullptr); | |||
1844 | _mesa_hash_table_destroy (induction_hash, nullptr); | |||
1845 | ||||
1846 | return true; | |||
1847 | } | |||
1848 | ||||
1849 | ||||
1850 | void | |||
1851 | ir_print_glsl_visitor::visit(ir_loop *ir) | |||
1852 | { | |||
1853 | if (emit_canonical_for(ir)) | |||
1854 | return; | |||
1855 | ||||
1856 | buffer.asprintf_append ("while (true) {\n"); | |||
1857 | indentation++; previous_skipped = false; | |||
1858 | foreach_in_list(ir_instruction, inst, &ir->body_instructions)for (ir_instruction *inst = (!exec_node_is_tail_sentinel((& ir->body_instructions)->head_sentinel.next) ? (ir_instruction *) ((&ir->body_instructions)->head_sentinel.next) : __null); (inst) != __null; (inst) = (!exec_node_is_tail_sentinel ((inst)->next) ? (ir_instruction *) ((inst)->next) : __null )) { | |||
1859 | indent(); | |||
1860 | inst->accept(this); | |||
1861 | end_statement_line(); | |||
1862 | } | |||
1863 | indentation--; | |||
1864 | indent(); | |||
1865 | buffer.asprintf_append ("}"); | |||
1866 | } | |||
1867 | ||||
1868 | ||||
1869 | void | |||
1870 | ir_print_glsl_visitor::visit(ir_loop_jump *ir) | |||
1871 | { | |||
1872 | buffer.asprintf_append ("%s", ir->is_break() ? "break" : "continue"); | |||
1873 | } | |||
1874 | ||||
1875 | void | |||
1876 | ir_print_glsl_visitor::visit(ir_precision_statement *ir) | |||
1877 | { | |||
1878 | buffer.asprintf_append ("%s", ir->precision_statement); | |||
1879 | } | |||
1880 | ||||
1881 | static const char* | |||
1882 | interface_packing_string(enum glsl_interface_packing packing) | |||
1883 | { | |||
1884 | switch (packing) { | |||
1885 | case GLSL_INTERFACE_PACKING_STD140: | |||
1886 | return "std140"; | |||
1887 | case GLSL_INTERFACE_PACKING_SHARED: | |||
1888 | return "shared"; | |||
1889 | case GLSL_INTERFACE_PACKING_PACKED: | |||
1890 | return "packed"; | |||
1891 | case GLSL_INTERFACE_PACKING_STD430: | |||
1892 | return "std430"; | |||
1893 | default: | |||
1894 | unreachable("Unexpected interface packing")do { (static_cast <bool> (!"Unexpected interface packing" ) ? void (0) : __assert_fail ("!\"Unexpected interface packing\"" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); __builtin_unreachable(); } while (0); | |||
1895 | return "UNKNOWN"; | |||
1896 | } | |||
1897 | } | |||
1898 | ||||
1899 | static const char* | |||
1900 | interface_variable_mode_string(enum ir_variable_mode mode) | |||
1901 | { | |||
1902 | switch (mode) { | |||
1903 | case ir_var_uniform: | |||
1904 | return "uniform"; | |||
1905 | case ir_var_shader_storage: | |||
1906 | return "buffer"; | |||
1907 | default: | |||
1908 | unreachable("Unexpected interface variable mode")do { (static_cast <bool> (!"Unexpected interface variable mode" ) ? void (0) : __assert_fail ("!\"Unexpected interface variable mode\"" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); __builtin_unreachable(); } while (0); | |||
1909 | return "UNKOWN"; | |||
1910 | } | |||
1911 | } | |||
1912 | ||||
1913 | void | |||
1914 | ir_print_glsl_visitor::visit(ir_typedecl_statement *ir) | |||
1915 | { | |||
1916 | const glsl_type *const s = ir->type_decl; | |||
1917 | ||||
1918 | ir_variable* interface_var = NULL__null; | |||
1919 | ||||
1920 | if (s->is_struct()) { | |||
1921 | buffer.asprintf_append ("struct %s {\n", s->name); | |||
1922 | } else if (s->is_interface()) { | |||
1923 | const char* packing = interface_packing_string(s->get_interface_packing()); | |||
1924 | ||||
1925 | // Find a variable defined by this interface, as it holds some necessary data. | |||
1926 | exec_node* n = ir; | |||
1927 | while ((n = n->get_next())) { | |||
1928 | ir_variable* v = ((ir_instruction *)n)->as_variable(); | |||
1929 | if (v != NULL__null && v->get_interface_type() == ir->type_decl) { | |||
1930 | interface_var = v; | |||
1931 | break; | |||
1932 | } | |||
1933 | } | |||
1934 | const char* mode = interface_variable_mode_string((enum ir_variable_mode)interface_var->data.mode); | |||
1935 | if (interface_var->data.explicit_binding) { | |||
1936 | uint16_t binding = interface_var->data.binding; | |||
1937 | buffer.asprintf_append ("layout(%s, binding=%" PRIu16"u" ") %s %s {\n", packing, binding, mode, s->name); | |||
1938 | } else { | |||
1939 | buffer.asprintf_append ("layout(%s) %s %s {\n", packing, mode, s->name); | |||
1940 | } | |||
1941 | ||||
1942 | } | |||
1943 | ||||
1944 | for (unsigned j = 0; j < s->length; j++) { | |||
1945 | buffer.asprintf_append (" "); | |||
1946 | // FIXME: precision | |||
1947 | // if (state->es_shader) | |||
1948 | // buffer.asprintf_append ("%s", get_precision_string(s->fields.structure[j].precision)); | |||
1949 | print_type(buffer, s->fields.structure[j].type, false); | |||
1950 | buffer.asprintf_append (" %s", s->fields.structure[j].name); | |||
1951 | print_type_post(buffer, s->fields.structure[j].type, false); | |||
1952 | buffer.asprintf_append (";\n"); | |||
1953 | } | |||
1954 | buffer.asprintf_append ("}"); | |||
1955 | ||||
1956 | if (interface_var && interface_var->is_interface_instance()) { | |||
1957 | buffer.asprintf_append(" "); | |||
1958 | print_var_name(interface_var); | |||
1959 | } | |||
1960 | } | |||
1961 | ||||
1962 | void | |||
1963 | ir_print_glsl_visitor::visit(ir_emit_vertex *ir) | |||
1964 | { | |||
1965 | buffer.asprintf_append ("emit-vertex-TODO"); | |||
1966 | } | |||
1967 | ||||
1968 | void | |||
1969 | ir_print_glsl_visitor::visit(ir_end_primitive *ir) | |||
1970 | { | |||
1971 | buffer.asprintf_append ("end-primitive-TODO"); | |||
1972 | } | |||
1973 | ||||
1974 | void | |||
1975 | ir_print_glsl_visitor::visit(ir_barrier *ir) | |||
1976 | { | |||
1977 | buffer.asprintf_append ("discard-TODO"); | |||
1978 | } |