2 * Copyright © 2008, 2009 Intel Corporation
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:
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
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.
27 #include <sys/types.h>
33 #include "glsl_parser_extras.h"
34 #include "glsl_parser.h"
35 #include "ir_optimization.h"
36 #include "ir_print_visitor.h"
38 #include "loop_analysis.h"
40 extern "C" struct gl_shader
*
41 _mesa_new_shader(GLcontext
*ctx
, GLuint name
, GLenum type
);
43 /* Copied from shader_api.c for the stand-alone compiler.
46 _mesa_new_shader(GLcontext
*ctx
, GLuint name
, GLenum type
)
48 struct gl_shader
*shader
;
52 assert(type
== GL_FRAGMENT_SHADER
|| type
== GL_VERTEX_SHADER
);
53 shader
= talloc_zero(NULL
, struct gl_shader
);
62 /* Returned string will have 'ctx' as its talloc owner. */
64 load_text_file(void *ctx
, const char *file_name
)
68 ssize_t total_read
= 0;
69 int fd
= open(file_name
, O_RDONLY
);
75 if (fstat(fd
, & st
) == 0) {
76 text
= (char *) talloc_size(ctx
, st
.st_size
+ 1);
79 ssize_t bytes
= read(fd
, text
+ total_read
,
80 st
.st_size
- total_read
);
92 } while (total_read
< st
.st_size
);
94 text
[total_read
] = '\0';
105 usage_fail(const char *name
)
107 printf("%s <filename.frag|filename.vert>\n", name
);
117 const struct option compiler_opts
[] = {
118 { "dump-ast", 0, &dump_ast
, 1 },
119 { "dump-hir", 0, &dump_hir
, 1 },
120 { "dump-lir", 0, &dump_lir
, 1 },
121 { "link", 0, &do_link
, 1 },
126 compile_shader(struct gl_shader
*shader
)
128 struct _mesa_glsl_parse_state
*state
=
129 new(shader
) _mesa_glsl_parse_state(NULL
, shader
->Type
, shader
);
131 const char *source
= shader
->Source
;
132 state
->error
= preprocess(state
, &source
, &state
->info_log
,
136 _mesa_glsl_lexer_ctor(state
, source
);
137 _mesa_glsl_parse(state
);
138 _mesa_glsl_lexer_dtor(state
);
142 foreach_list_const(n
, &state
->translation_unit
) {
143 ast_node
*ast
= exec_node_data(ast_node
, n
, link
);
149 shader
->ir
= new(shader
) exec_list
;
150 if (!state
->error
&& !state
->translation_unit
.is_empty())
151 _mesa_ast_to_hir(shader
->ir
, state
);
153 /* Print out the unoptimized IR. */
154 if (!state
->error
&& dump_hir
) {
155 validate_ir_tree(shader
->ir
);
156 _mesa_print_ir(shader
->ir
, state
);
159 /* Optimization passes */
160 if (!state
->error
&& !shader
->ir
->is_empty()) {
165 progress
= do_function_inlining(shader
->ir
) || progress
;
166 progress
= do_if_simplification(shader
->ir
) || progress
;
167 progress
= do_copy_propagation(shader
->ir
) || progress
;
168 progress
= do_dead_code_local(shader
->ir
) || progress
;
169 progress
= do_dead_code_unlinked(shader
->ir
) || progress
;
170 progress
= do_tree_grafting(shader
->ir
) || progress
;
171 progress
= do_constant_propagation(shader
->ir
) || progress
;
172 progress
= do_constant_variable_unlinked(shader
->ir
) || progress
;
173 progress
= do_constant_folding(shader
->ir
) || progress
;
174 progress
= do_algebraic(shader
->ir
) || progress
;
175 progress
= do_vec_index_to_swizzle(shader
->ir
) || progress
;
176 progress
= do_vec_index_to_cond_assign(shader
->ir
) || progress
;
177 progress
= do_swizzle_swizzle(shader
->ir
) || progress
;
179 loop_state
*ls
= analyze_loop_variables(shader
->ir
);
180 set_loop_controls(shader
->ir
, ls
);
184 validate_ir_tree(shader
->ir
);
188 /* Print out the resulting IR */
189 if (!state
->error
&& dump_lir
) {
190 _mesa_print_ir(shader
->ir
, state
);
193 shader
->symbols
= state
->symbols
;
194 shader
->CompileStatus
= !state
->error
;
195 shader
->Version
= state
->language_version
;
196 memcpy(shader
->builtins_to_link
, state
->builtins_to_link
,
197 sizeof(shader
->builtins_to_link
[0]) * state
->num_builtins_to_link
);
198 shader
->num_builtins_to_link
= state
->num_builtins_to_link
;
201 talloc_free(shader
->InfoLog
);
203 shader
->InfoLog
= state
->info_log
;
205 /* Retain any live IR, but trash the rest. */
206 reparent_ir(shader
->ir
, shader
);
214 main(int argc
, char **argv
)
216 int status
= EXIT_SUCCESS
;
218 GLcontext
*ctx
= &local_ctx
;
220 ctx
->Driver
.NewShader
= _mesa_new_shader
;
224 while ((c
= getopt_long(argc
, argv
, "", compiler_opts
, &idx
)) != -1)
231 struct gl_shader_program
*whole_program
;
233 whole_program
= talloc_zero (NULL
, struct gl_shader_program
);
234 assert(whole_program
!= NULL
);
236 for (/* empty */; argc
> optind
; optind
++) {
237 whole_program
->Shaders
= (struct gl_shader
**)
238 talloc_realloc(whole_program
, whole_program
->Shaders
,
239 struct gl_shader
*, whole_program
->NumShaders
+ 1);
240 assert(whole_program
->Shaders
!= NULL
);
242 struct gl_shader
*shader
= talloc_zero(whole_program
, gl_shader
);
244 whole_program
->Shaders
[whole_program
->NumShaders
] = shader
;
245 whole_program
->NumShaders
++;
247 const unsigned len
= strlen(argv
[optind
]);
251 const char *const ext
= & argv
[optind
][len
- 5];
252 if (strncmp(".vert", ext
, 5) == 0)
253 shader
->Type
= GL_VERTEX_SHADER
;
254 else if (strncmp(".geom", ext
, 5) == 0)
255 shader
->Type
= GL_GEOMETRY_SHADER
;
256 else if (strncmp(".frag", ext
, 5) == 0)
257 shader
->Type
= GL_FRAGMENT_SHADER
;
261 shader
->Source
= load_text_file(whole_program
, argv
[optind
]);
262 if (shader
->Source
== NULL
) {
263 printf("File \"%s\" does not exist.\n", argv
[optind
]);
267 compile_shader(shader
);
269 if (!shader
->CompileStatus
) {
270 printf("Info log for %s:\n%s\n", argv
[optind
], shader
->InfoLog
);
271 status
= EXIT_FAILURE
;
276 if ((status
== EXIT_SUCCESS
) && do_link
) {
277 link_shaders(ctx
, whole_program
);
278 status
= (whole_program
->LinkStatus
) ? EXIT_SUCCESS
: EXIT_FAILURE
;
280 if (strlen(whole_program
->InfoLog
) > 0)
281 printf("Info log for linking:\n%s\n", whole_program
->InfoLog
);
284 for (unsigned i
= 0; i
< whole_program
->_NumLinkedShaders
; i
++)
285 talloc_free(whole_program
->_LinkedShaders
[i
]);
287 talloc_free(whole_program
);
288 _mesa_glsl_release_types();
289 _mesa_glsl_release_functions();