Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /* |
2 | * Copyright © 2008, 2009 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 | #include |
||
24 | #include |
||
25 | #include |
||
26 | |||
27 | #include |
||
28 | #include |
||
29 | #include |
||
30 | #include |
||
31 | |||
32 | #include "ast.h" |
||
33 | #include "glsl_parser_extras.h" |
||
34 | #include "glsl_parser.h" |
||
35 | #include "ir_optimization.h" |
||
36 | #include "ir_print_visitor.h" |
||
37 | #include "program.h" |
||
38 | #include "loop_analysis.h" |
||
39 | |||
40 | extern "C" struct gl_shader * |
||
41 | _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type); |
||
42 | |||
43 | extern "C" void |
||
44 | _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, |
||
45 | struct gl_shader *sh); |
||
46 | |||
47 | /* Copied from shader_api.c for the stand-alone compiler. |
||
48 | */ |
||
49 | void |
||
50 | _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, |
||
51 | struct gl_shader *sh) |
||
52 | { |
||
53 | *ptr = sh; |
||
54 | } |
||
55 | |||
56 | struct gl_shader * |
||
57 | _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type) |
||
58 | { |
||
59 | struct gl_shader *shader; |
||
60 | |||
61 | (void) ctx; |
||
62 | |||
63 | assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER); |
||
64 | shader = rzalloc(NULL, struct gl_shader); |
||
65 | if (shader) { |
||
66 | shader->Type = type; |
||
67 | shader->Name = name; |
||
68 | shader->RefCount = 1; |
||
69 | } |
||
70 | return shader; |
||
71 | } |
||
72 | |||
73 | static void |
||
74 | initialize_context(struct gl_context *ctx, gl_api api) |
||
75 | { |
||
76 | memset(ctx, 0, sizeof(*ctx)); |
||
77 | |||
78 | ctx->API = api; |
||
79 | |||
80 | ctx->Extensions.ARB_ES2_compatibility = GL_TRUE; |
||
81 | ctx->Extensions.ARB_draw_buffers = GL_TRUE; |
||
82 | ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; |
||
83 | ctx->Extensions.EXT_texture_array = GL_TRUE; |
||
84 | ctx->Extensions.NV_texture_rectangle = GL_TRUE; |
||
85 | |||
86 | /* GLSL 1.30 isn't fully supported, but we need to advertise 1.30 so that |
||
87 | * the built-in functions for 1.30 can be built. |
||
88 | */ |
||
89 | ctx->Const.GLSLVersion = 130; |
||
90 | |||
91 | /* 1.10 minimums. */ |
||
92 | ctx->Const.MaxLights = 8; |
||
93 | ctx->Const.MaxClipPlanes = 8; |
||
94 | ctx->Const.MaxTextureUnits = 2; |
||
95 | |||
96 | /* More than the 1.10 minimum to appease parser tests taken from |
||
97 | * apps that (hopefully) already checked the number of coords. |
||
98 | */ |
||
99 | ctx->Const.MaxTextureCoordUnits = 4; |
||
100 | |||
101 | ctx->Const.VertexProgram.MaxAttribs = 16; |
||
102 | ctx->Const.VertexProgram.MaxUniformComponents = 512; |
||
103 | ctx->Const.MaxVarying = 8; |
||
104 | ctx->Const.MaxVertexTextureImageUnits = 0; |
||
105 | ctx->Const.MaxCombinedTextureImageUnits = 2; |
||
106 | ctx->Const.MaxTextureImageUnits = 2; |
||
107 | ctx->Const.FragmentProgram.MaxUniformComponents = 64; |
||
108 | |||
109 | ctx->Const.MaxDrawBuffers = 2; |
||
110 | |||
111 | ctx->Driver.NewShader = _mesa_new_shader; |
||
112 | } |
||
113 | |||
114 | /* Returned string will have 'ctx' as its ralloc owner. */ |
||
115 | static char * |
||
116 | load_text_file(void *ctx, const char *file_name) |
||
117 | { |
||
118 | char *text = NULL; |
||
119 | struct stat st; |
||
120 | ssize_t total_read = 0; |
||
121 | int fd = open(file_name, O_RDONLY); |
||
122 | |||
123 | if (fd < 0) { |
||
124 | return NULL; |
||
125 | } |
||
126 | |||
127 | if (fstat(fd, & st) == 0) { |
||
128 | text = (char *) ralloc_size(ctx, st.st_size + 1); |
||
129 | if (text != NULL) { |
||
130 | do { |
||
131 | ssize_t bytes = read(fd, text + total_read, |
||
132 | st.st_size - total_read); |
||
133 | if (bytes < 0) { |
||
134 | free(text); |
||
135 | text = NULL; |
||
136 | break; |
||
137 | } |
||
138 | |||
139 | if (bytes == 0) { |
||
140 | break; |
||
141 | } |
||
142 | |||
143 | total_read += bytes; |
||
144 | } while (total_read < st.st_size); |
||
145 | |||
146 | text[total_read] = '\0'; |
||
147 | } |
||
148 | } |
||
149 | |||
150 | close(fd); |
||
151 | |||
152 | return text; |
||
153 | } |
||
154 | |||
155 | int glsl_es = 0; |
||
156 | int dump_ast = 0; |
||
157 | int dump_hir = 0; |
||
158 | int dump_lir = 0; |
||
159 | int do_link = 0; |
||
160 | |||
161 | const struct option compiler_opts[] = { |
||
162 | { "glsl-es", 0, &glsl_es, 1 }, |
||
163 | { "dump-ast", 0, &dump_ast, 1 }, |
||
164 | { "dump-hir", 0, &dump_hir, 1 }, |
||
165 | { "dump-lir", 0, &dump_lir, 1 }, |
||
166 | { "link", 0, &do_link, 1 }, |
||
167 | { NULL, 0, NULL, 0 } |
||
168 | }; |
||
169 | |||
170 | /** |
||
171 | * \brief Print proper usage and exit with failure. |
||
172 | */ |
||
173 | void |
||
174 | usage_fail(const char *name) |
||
175 | { |
||
176 | |||
177 | const char *header = |
||
178 | "usage: %s [options] |
||
179 | "\n" |
||
180 | "Possible options are:\n"; |
||
181 | printf(header, name, name); |
||
182 | for (const struct option *o = compiler_opts; o->name != 0; ++o) { |
||
183 | printf(" --%s\n", o->name); |
||
184 | } |
||
185 | exit(EXIT_FAILURE); |
||
186 | } |
||
187 | |||
188 | |||
189 | void |
||
190 | compile_shader(struct gl_context *ctx, struct gl_shader *shader) |
||
191 | { |
||
192 | struct _mesa_glsl_parse_state *state = |
||
193 | new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); |
||
194 | |||
195 | const char *source = shader->Source; |
||
196 | state->error = preprocess(state, &source, &state->info_log, |
||
197 | state->extensions, ctx->API); |
||
198 | |||
199 | if (!state->error) { |
||
200 | _mesa_glsl_lexer_ctor(state, source); |
||
201 | _mesa_glsl_parse(state); |
||
202 | _mesa_glsl_lexer_dtor(state); |
||
203 | } |
||
204 | |||
205 | if (dump_ast) { |
||
206 | foreach_list_const(n, &state->translation_unit) { |
||
207 | ast_node *ast = exec_node_data(ast_node, n, link); |
||
208 | ast->print(); |
||
209 | } |
||
210 | printf("\n\n"); |
||
211 | } |
||
212 | |||
213 | shader->ir = new(shader) exec_list; |
||
214 | if (!state->error && !state->translation_unit.is_empty()) |
||
215 | _mesa_ast_to_hir(shader->ir, state); |
||
216 | |||
217 | /* Print out the unoptimized IR. */ |
||
218 | if (!state->error && dump_hir) { |
||
219 | validate_ir_tree(shader->ir); |
||
220 | _mesa_print_ir(shader->ir, state); |
||
221 | } |
||
222 | |||
223 | /* Optimization passes */ |
||
224 | if (!state->error && !shader->ir->is_empty()) { |
||
225 | bool progress; |
||
226 | do { |
||
227 | progress = do_common_optimization(shader->ir, false, 32); |
||
228 | } while (progress); |
||
229 | |||
230 | validate_ir_tree(shader->ir); |
||
231 | } |
||
232 | |||
233 | |||
234 | /* Print out the resulting IR */ |
||
235 | if (!state->error && dump_lir) { |
||
236 | _mesa_print_ir(shader->ir, state); |
||
237 | } |
||
238 | |||
239 | shader->symbols = state->symbols; |
||
240 | shader->CompileStatus = !state->error; |
||
241 | shader->Version = state->language_version; |
||
242 | memcpy(shader->builtins_to_link, state->builtins_to_link, |
||
243 | sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); |
||
244 | shader->num_builtins_to_link = state->num_builtins_to_link; |
||
245 | |||
246 | if (shader->InfoLog) |
||
247 | ralloc_free(shader->InfoLog); |
||
248 | |||
249 | shader->InfoLog = state->info_log; |
||
250 | |||
251 | /* Retain any live IR, but trash the rest. */ |
||
252 | reparent_ir(shader->ir, shader); |
||
253 | |||
254 | ralloc_free(state); |
||
255 | |||
256 | return; |
||
257 | } |
||
258 | |||
259 | int |
||
260 | main(int argc, char **argv) |
||
261 | { |
||
262 | int status = EXIT_SUCCESS; |
||
263 | struct gl_context local_ctx; |
||
264 | struct gl_context *ctx = &local_ctx; |
||
265 | |||
266 | int c; |
||
267 | int idx = 0; |
||
268 | while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) |
||
269 | /* empty */ ; |
||
270 | |||
271 | |||
272 | if (argc <= optind) |
||
273 | usage_fail(argv[0]); |
||
274 | |||
275 | initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL); |
||
276 | |||
277 | struct gl_shader_program *whole_program; |
||
278 | |||
279 | whole_program = rzalloc (NULL, struct gl_shader_program); |
||
280 | assert(whole_program != NULL); |
||
281 | |||
282 | for (/* empty */; argc > optind; optind++) { |
||
283 | whole_program->Shaders = |
||
284 | reralloc(whole_program, whole_program->Shaders, |
||
285 | struct gl_shader *, whole_program->NumShaders + 1); |
||
286 | assert(whole_program->Shaders != NULL); |
||
287 | |||
288 | struct gl_shader *shader = rzalloc(whole_program, gl_shader); |
||
289 | |||
290 | whole_program->Shaders[whole_program->NumShaders] = shader; |
||
291 | whole_program->NumShaders++; |
||
292 | |||
293 | const unsigned len = strlen(argv[optind]); |
||
294 | if (len < 6) |
||
295 | usage_fail(argv[0]); |
||
296 | |||
297 | const char *const ext = & argv[optind][len - 5]; |
||
298 | if (strncmp(".vert", ext, 5) == 0) |
||
299 | shader->Type = GL_VERTEX_SHADER; |
||
300 | else if (strncmp(".geom", ext, 5) == 0) |
||
301 | shader->Type = GL_GEOMETRY_SHADER; |
||
302 | else if (strncmp(".frag", ext, 5) == 0) |
||
303 | shader->Type = GL_FRAGMENT_SHADER; |
||
304 | else |
||
305 | usage_fail(argv[0]); |
||
306 | |||
307 | shader->Source = load_text_file(whole_program, argv[optind]); |
||
308 | if (shader->Source == NULL) { |
||
309 | printf("File \"%s\" does not exist.\n", argv[optind]); |
||
310 | exit(EXIT_FAILURE); |
||
311 | } |
||
312 | |||
313 | compile_shader(ctx, shader); |
||
314 | |||
315 | if (!shader->CompileStatus) { |
||
316 | printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog); |
||
317 | status = EXIT_FAILURE; |
||
318 | break; |
||
319 | } |
||
320 | } |
||
321 | |||
322 | if ((status == EXIT_SUCCESS) && do_link) { |
||
323 | link_shaders(ctx, whole_program); |
||
324 | status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE; |
||
325 | |||
326 | if (strlen(whole_program->InfoLog) > 0) |
||
327 | printf("Info log for linking:\n%s\n", whole_program->InfoLog); |
||
328 | } |
||
329 | |||
330 | for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) |
||
331 | ralloc_free(whole_program->_LinkedShaders[i]); |
||
332 | |||
333 | ralloc_free(whole_program); |
||
334 | _mesa_glsl_release_types(); |
||
335 | _mesa_glsl_release_functions(); |
||
336 | |||
337 | return status; |
||
338 | }>>=>>>> |