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.
26 #include "glsl_parser_extras.h"
27 #include "glsl_parser.h"
28 #include "ir_optimization.h"
29 #include "ir_print_visitor.h"
31 #include "loop_analysis.h"
33 extern "C" struct gl_shader
*
34 _mesa_new_shader(struct gl_context
*ctx
, GLuint name
, GLenum type
);
37 _mesa_reference_shader(struct gl_context
*ctx
, struct gl_shader
**ptr
,
38 struct gl_shader
*sh
);
40 /* Copied from shader_api.c for the stand-alone compiler.
43 _mesa_reference_shader(struct gl_context
*ctx
, struct gl_shader
**ptr
,
50 _mesa_new_shader(struct gl_context
*ctx
, GLuint name
, GLenum type
)
52 struct gl_shader
*shader
;
56 assert(type
== GL_FRAGMENT_SHADER
|| type
== GL_VERTEX_SHADER
);
57 shader
= rzalloc(NULL
, struct gl_shader
);
67 initialize_context(struct gl_context
*ctx
, gl_api api
)
69 memset(ctx
, 0, sizeof(*ctx
));
73 ctx
->Extensions
.ARB_ES2_compatibility
= GL_TRUE
;
74 ctx
->Extensions
.ARB_draw_buffers
= GL_TRUE
;
75 ctx
->Extensions
.ARB_draw_instanced
= GL_TRUE
;
76 ctx
->Extensions
.ARB_fragment_coord_conventions
= GL_TRUE
;
77 ctx
->Extensions
.EXT_texture_array
= GL_TRUE
;
78 ctx
->Extensions
.NV_texture_rectangle
= GL_TRUE
;
79 ctx
->Extensions
.EXT_texture3D
= GL_TRUE
;
81 /* GLSL 1.30 isn't fully supported, but we need to advertise 1.30 so that
82 * the built-in functions for 1.30 can be built.
84 ctx
->Const
.GLSLVersion
= 130;
87 ctx
->Const
.MaxLights
= 8;
88 ctx
->Const
.MaxClipPlanes
= 8;
89 ctx
->Const
.MaxTextureUnits
= 2;
91 /* More than the 1.10 minimum to appease parser tests taken from
92 * apps that (hopefully) already checked the number of coords.
94 ctx
->Const
.MaxTextureCoordUnits
= 4;
96 ctx
->Const
.VertexProgram
.MaxAttribs
= 16;
97 ctx
->Const
.VertexProgram
.MaxUniformComponents
= 512;
98 ctx
->Const
.MaxVarying
= 8;
99 ctx
->Const
.MaxVertexTextureImageUnits
= 0;
100 ctx
->Const
.MaxCombinedTextureImageUnits
= 2;
101 ctx
->Const
.MaxTextureImageUnits
= 2;
102 ctx
->Const
.FragmentProgram
.MaxUniformComponents
= 64;
104 ctx
->Const
.MaxDrawBuffers
= 2;
106 ctx
->Driver
.NewShader
= _mesa_new_shader
;
109 /* Returned string will have 'ctx' as its ralloc owner. */
111 load_text_file(void *ctx
, const char *file_name
)
115 size_t total_read
= 0;
116 FILE *fp
= fopen(file_name
, "rb");
122 fseek(fp
, 0L, SEEK_END
);
124 fseek(fp
, 0L, SEEK_SET
);
126 text
= (char *) ralloc_size(ctx
, size
+ 1);
129 size_t bytes
= fread(text
+ total_read
,
130 1, size
- total_read
, fp
);
131 if (bytes
< size
- total_read
) {
142 } while (total_read
< size
);
144 text
[total_read
] = '\0';
158 const struct option compiler_opts
[] = {
159 { "glsl-es", 0, &glsl_es
, 1 },
160 { "dump-ast", 0, &dump_ast
, 1 },
161 { "dump-hir", 0, &dump_hir
, 1 },
162 { "dump-lir", 0, &dump_lir
, 1 },
163 { "link", 0, &do_link
, 1 },
168 * \brief Print proper usage and exit with failure.
171 usage_fail(const char *name
)
175 "usage: %s [options] <file.vert | file.geom | file.frag>\n"
177 "Possible options are:\n";
178 printf(header
, name
, name
);
179 for (const struct option
*o
= compiler_opts
; o
->name
!= 0; ++o
) {
180 printf(" --%s\n", o
->name
);
187 compile_shader(struct gl_context
*ctx
, struct gl_shader
*shader
)
189 struct _mesa_glsl_parse_state
*state
=
190 new(shader
) _mesa_glsl_parse_state(ctx
, shader
->Type
, shader
);
192 const char *source
= shader
->Source
;
193 state
->error
= preprocess(state
, &source
, &state
->info_log
,
194 state
->extensions
, ctx
->API
) != 0;
197 _mesa_glsl_lexer_ctor(state
, source
);
198 _mesa_glsl_parse(state
);
199 _mesa_glsl_lexer_dtor(state
);
203 foreach_list_const(n
, &state
->translation_unit
) {
204 ast_node
*ast
= exec_node_data(ast_node
, n
, link
);
210 shader
->ir
= new(shader
) exec_list
;
211 if (!state
->error
&& !state
->translation_unit
.is_empty())
212 _mesa_ast_to_hir(shader
->ir
, state
);
214 /* Print out the unoptimized IR. */
215 if (!state
->error
&& dump_hir
) {
216 validate_ir_tree(shader
->ir
);
217 _mesa_print_ir(shader
->ir
, state
);
220 /* Optimization passes */
221 if (!state
->error
&& !shader
->ir
->is_empty()) {
224 progress
= do_common_optimization(shader
->ir
, false, 32);
227 validate_ir_tree(shader
->ir
);
231 /* Print out the resulting IR */
232 if (!state
->error
&& dump_lir
) {
233 _mesa_print_ir(shader
->ir
, state
);
236 shader
->symbols
= state
->symbols
;
237 shader
->CompileStatus
= !state
->error
;
238 shader
->Version
= state
->language_version
;
239 memcpy(shader
->builtins_to_link
, state
->builtins_to_link
,
240 sizeof(shader
->builtins_to_link
[0]) * state
->num_builtins_to_link
);
241 shader
->num_builtins_to_link
= state
->num_builtins_to_link
;
244 ralloc_free(shader
->InfoLog
);
246 shader
->InfoLog
= state
->info_log
;
248 /* Retain any live IR, but trash the rest. */
249 reparent_ir(shader
->ir
, shader
);
257 main(int argc
, char **argv
)
259 int status
= EXIT_SUCCESS
;
260 struct gl_context local_ctx
;
261 struct gl_context
*ctx
= &local_ctx
;
265 while ((c
= getopt_long(argc
, argv
, "", compiler_opts
, &idx
)) != -1)
272 initialize_context(ctx
, (glsl_es
) ? API_OPENGLES2
: API_OPENGL
);
274 struct gl_shader_program
*whole_program
;
276 whole_program
= rzalloc (NULL
, struct gl_shader_program
);
277 assert(whole_program
!= NULL
);
279 for (/* empty */; argc
> optind
; optind
++) {
280 whole_program
->Shaders
=
281 reralloc(whole_program
, whole_program
->Shaders
,
282 struct gl_shader
*, whole_program
->NumShaders
+ 1);
283 assert(whole_program
->Shaders
!= NULL
);
285 struct gl_shader
*shader
= rzalloc(whole_program
, gl_shader
);
287 whole_program
->Shaders
[whole_program
->NumShaders
] = shader
;
288 whole_program
->NumShaders
++;
290 const unsigned len
= strlen(argv
[optind
]);
294 const char *const ext
= & argv
[optind
][len
- 5];
295 if (strncmp(".vert", ext
, 5) == 0)
296 shader
->Type
= GL_VERTEX_SHADER
;
297 else if (strncmp(".geom", ext
, 5) == 0)
298 shader
->Type
= GL_GEOMETRY_SHADER
;
299 else if (strncmp(".frag", ext
, 5) == 0)
300 shader
->Type
= GL_FRAGMENT_SHADER
;
304 shader
->Source
= load_text_file(whole_program
, argv
[optind
]);
305 if (shader
->Source
== NULL
) {
306 printf("File \"%s\" does not exist.\n", argv
[optind
]);
310 compile_shader(ctx
, shader
);
312 if (!shader
->CompileStatus
) {
313 printf("Info log for %s:\n%s\n", argv
[optind
], shader
->InfoLog
);
314 status
= EXIT_FAILURE
;
319 if ((status
== EXIT_SUCCESS
) && do_link
) {
320 link_shaders(ctx
, whole_program
);
321 status
= (whole_program
->LinkStatus
) ? EXIT_SUCCESS
: EXIT_FAILURE
;
323 if (strlen(whole_program
->InfoLog
) > 0)
324 printf("Info log for linking:\n%s\n", whole_program
->InfoLog
);
327 for (unsigned i
= 0; i
< MESA_SHADER_TYPES
; i
++)
328 ralloc_free(whole_program
->_LinkedShaders
[i
]);
330 ralloc_free(whole_program
);
331 _mesa_glsl_release_types();
332 _mesa_glsl_release_functions();