blob: c8fc2676253095c05a466f5d3d63b22f3e6c3566 [file] [log] [blame]
Ian Romanick61d4aa02010-06-14 14:46:09 -07001/*
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 <cstdlib>
24#include <cstdio>
Ian Romanick7babbdb2010-06-15 12:47:07 -070025#include <getopt.h>
Ian Romanick61d4aa02010-06-14 14:46:09 -070026
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <fcntl.h>
30#include <unistd.h>
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"
Ian Romanick8ce55db2010-06-17 12:01:18 -070037#include "program.h"
Ian Romanick8df2dbf2010-08-26 16:45:22 -070038#include "loop_analysis.h"
Ian Romanick61d4aa02010-06-14 14:46:09 -070039
Ian Romanick3fb87872010-07-09 14:09:34 -070040extern "C" struct gl_shader *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -040041_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
Ian Romanick3fb87872010-07-09 14:09:34 -070042
Ian Romanick3322fba2010-10-14 13:28:42 -070043extern "C" void
44_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
45 struct gl_shader *sh);
46
Ian Romanick3fb87872010-07-09 14:09:34 -070047/* Copied from shader_api.c for the stand-alone compiler.
48 */
Ian Romanick3322fba2010-10-14 13:28:42 -070049void
50_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
51 struct gl_shader *sh)
52{
53 *ptr = sh;
54}
55
Ian Romanick3fb87872010-07-09 14:09:34 -070056struct gl_shader *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -040057_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
Ian Romanick3fb87872010-07-09 14:09:34 -070058{
59 struct gl_shader *shader;
Ian Romanick7ffe4052010-08-02 11:46:22 -070060
61 (void) ctx;
62
Ian Romanick3fb87872010-07-09 14:09:34 -070063 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
64 shader = talloc_zero(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
Chia-I Wudc754582010-09-08 18:48:12 +080073static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -040074initialize_context(struct gl_context *ctx, gl_api api)
Chia-I Wudc754582010-09-08 18:48:12 +080075{
76 memset(ctx, 0, sizeof(*ctx));
77
78 ctx->API = api;
79
80 ctx->Extensions.ARB_draw_buffers = GL_TRUE;
81 ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
82 ctx->Extensions.EXT_texture_array = GL_TRUE;
83 ctx->Extensions.NV_texture_rectangle = GL_TRUE;
84
85 /* 1.10 minimums. */
86 ctx->Const.MaxLights = 8;
87 ctx->Const.MaxClipPlanes = 8;
88 ctx->Const.MaxTextureUnits = 2;
89
90 /* More than the 1.10 minimum to appease parser tests taken from
91 * apps that (hopefully) already checked the number of coords.
92 */
93 ctx->Const.MaxTextureCoordUnits = 4;
94
95 ctx->Const.VertexProgram.MaxAttribs = 16;
96 ctx->Const.VertexProgram.MaxUniformComponents = 512;
97 ctx->Const.MaxVarying = 8;
98 ctx->Const.MaxVertexTextureImageUnits = 0;
99 ctx->Const.MaxCombinedTextureImageUnits = 2;
100 ctx->Const.MaxTextureImageUnits = 2;
101 ctx->Const.FragmentProgram.MaxUniformComponents = 64;
102
103 ctx->Const.MaxDrawBuffers = 2;
104
105 ctx->Driver.NewShader = _mesa_new_shader;
106}
107
Carl Wortha9696e72010-06-18 17:37:02 -0700108/* Returned string will have 'ctx' as its talloc owner. */
Ian Romanick61d4aa02010-06-14 14:46:09 -0700109static char *
Eric Anholt16b68b12010-06-30 11:05:43 -0700110load_text_file(void *ctx, const char *file_name)
Ian Romanick61d4aa02010-06-14 14:46:09 -0700111{
112 char *text = NULL;
113 struct stat st;
114 ssize_t total_read = 0;
115 int fd = open(file_name, O_RDONLY);
116
Ian Romanick61d4aa02010-06-14 14:46:09 -0700117 if (fd < 0) {
118 return NULL;
119 }
120
121 if (fstat(fd, & st) == 0) {
Carl Wortha9696e72010-06-18 17:37:02 -0700122 text = (char *) talloc_size(ctx, st.st_size + 1);
Ian Romanick61d4aa02010-06-14 14:46:09 -0700123 if (text != NULL) {
124 do {
125 ssize_t bytes = read(fd, text + total_read,
126 st.st_size - total_read);
127 if (bytes < 0) {
128 free(text);
129 text = NULL;
130 break;
131 }
132
133 if (bytes == 0) {
134 break;
135 }
136
137 total_read += bytes;
138 } while (total_read < st.st_size);
139
140 text[total_read] = '\0';
Ian Romanick61d4aa02010-06-14 14:46:09 -0700141 }
142 }
143
144 close(fd);
145
146 return text;
147}
148
Chia-I Wu1a5b32c2010-09-08 18:52:27 +0800149int glsl_es = 0;
Ian Romanick7babbdb2010-06-15 12:47:07 -0700150int dump_ast = 0;
Ian Romanick22c23de2010-06-25 15:27:47 -0700151int dump_hir = 0;
Ian Romanick81e17472010-06-15 12:51:38 -0700152int dump_lir = 0;
Ian Romanickc648a122010-06-17 19:51:48 -0700153int do_link = 0;
Ian Romanick7babbdb2010-06-15 12:47:07 -0700154
155const struct option compiler_opts[] = {
Chia-I Wu1a5b32c2010-09-08 18:52:27 +0800156 { "glsl-es", 0, &glsl_es, 1 },
Ian Romanick7babbdb2010-06-15 12:47:07 -0700157 { "dump-ast", 0, &dump_ast, 1 },
Ian Romanick22c23de2010-06-25 15:27:47 -0700158 { "dump-hir", 0, &dump_hir, 1 },
Ian Romanick81e17472010-06-15 12:51:38 -0700159 { "dump-lir", 0, &dump_lir, 1 },
Ian Romanickc648a122010-06-17 19:51:48 -0700160 { "link", 0, &do_link, 1 },
Ian Romanick7babbdb2010-06-15 12:47:07 -0700161 { NULL, 0, NULL, 0 }
162};
163
Chad Versace78194352010-11-17 15:28:36 -0800164/**
165 * \brief Print proper usage and exit with failure.
166 */
167void
168usage_fail(const char *name)
169{
170
171 const char *header =
172 "usage: %s [options] <file.vert | file.geom | file.frag>\n"
173 "\n"
174 "Possible options are:\n";
175 printf(header, name, name);
176 for (const struct option *o = compiler_opts; o->name != 0; ++o) {
177 printf(" --%s\n", o->name);
178 }
179 exit(EXIT_FAILURE);
180}
181
182
Ian Romanick8ce55db2010-06-17 12:01:18 -0700183void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400184compile_shader(struct gl_context *ctx, struct gl_shader *shader)
Ian Romanick61d4aa02010-06-14 14:46:09 -0700185{
Kenneth Graunkeaa9f86a2010-07-22 16:20:36 -0700186 struct _mesa_glsl_parse_state *state =
Chia-I Wudc754582010-09-08 18:48:12 +0800187 new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
Eric Anholtf8946692010-07-20 14:03:35 -0700188
Kenneth Graunke04ba86a2010-06-16 12:18:00 -0700189 const char *source = shader->Source;
Kenneth Graunkeaa9f86a2010-07-22 16:20:36 -0700190 state->error = preprocess(state, &source, &state->info_log,
Chia-I Wudc754582010-09-08 18:48:12 +0800191 state->extensions, ctx->API);
Kenneth Graunke04ba86a2010-06-16 12:18:00 -0700192
Carl Worth2d2561e2010-06-23 15:43:38 -0700193 if (!state->error) {
194 _mesa_glsl_lexer_ctor(state, source);
195 _mesa_glsl_parse(state);
196 _mesa_glsl_lexer_dtor(state);
Kenneth Graunke04ba86a2010-06-16 12:18:00 -0700197 }
Ian Romanick61d4aa02010-06-14 14:46:09 -0700198
Ian Romanick7babbdb2010-06-15 12:47:07 -0700199 if (dump_ast) {
Carl Worth2d2561e2010-06-23 15:43:38 -0700200 foreach_list_const(n, &state->translation_unit) {
Ian Romanick7babbdb2010-06-15 12:47:07 -0700201 ast_node *ast = exec_node_data(ast_node, n, link);
202 ast->print();
203 }
204 printf("\n\n");
Ian Romanick61d4aa02010-06-14 14:46:09 -0700205 }
206
Eric Anholt16b68b12010-06-30 11:05:43 -0700207 shader->ir = new(shader) exec_list;
Carl Worth2d2561e2010-06-23 15:43:38 -0700208 if (!state->error && !state->translation_unit.is_empty())
Eric Anholt16b68b12010-06-30 11:05:43 -0700209 _mesa_ast_to_hir(shader->ir, state);
Ian Romanick54992c32010-06-14 14:47:26 -0700210
Ian Romanick22c23de2010-06-25 15:27:47 -0700211 /* Print out the unoptimized IR. */
212 if (!state->error && dump_hir) {
Ian Romanick5a2e0b82010-07-20 11:37:45 -0700213 validate_ir_tree(shader->ir);
Eric Anholt16b68b12010-06-30 11:05:43 -0700214 _mesa_print_ir(shader->ir, state);
Ian Romanick22c23de2010-06-25 15:27:47 -0700215 }
216
Ian Romanick61d4aa02010-06-14 14:46:09 -0700217 /* Optimization passes */
Eric Anholt16b68b12010-06-30 11:05:43 -0700218 if (!state->error && !shader->ir->is_empty()) {
Ian Romanick61d4aa02010-06-14 14:46:09 -0700219 bool progress;
220 do {
Kenneth Graunkea82592d2010-11-24 23:54:03 -0800221 progress = do_common_optimization(shader->ir, false, 32);
Ian Romanick61d4aa02010-06-14 14:46:09 -0700222 } while (progress);
Ian Romanick5a2e0b82010-07-20 11:37:45 -0700223
224 validate_ir_tree(shader->ir);
Ian Romanick61d4aa02010-06-14 14:46:09 -0700225 }
226
Eric Anholt53cdb7e2010-06-22 12:07:21 -0700227
Ian Romanick61d4aa02010-06-14 14:46:09 -0700228 /* Print out the resulting IR */
Carl Worth2d2561e2010-06-23 15:43:38 -0700229 if (!state->error && dump_lir) {
Eric Anholt16b68b12010-06-30 11:05:43 -0700230 _mesa_print_ir(shader->ir, state);
Ian Romanick61d4aa02010-06-14 14:46:09 -0700231 }
232
Carl Worth2d2561e2010-06-23 15:43:38 -0700233 shader->symbols = state->symbols;
234 shader->CompileStatus = !state->error;
Ian Romanick25f51d32010-07-16 15:51:50 -0700235 shader->Version = state->language_version;
Ian Romanickd5be2ac2010-07-20 11:29:46 -0700236 memcpy(shader->builtins_to_link, state->builtins_to_link,
237 sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
238 shader->num_builtins_to_link = state->num_builtins_to_link;
Ian Romanickca97bd32010-06-19 01:39:14 -0700239
240 if (shader->InfoLog)
241 talloc_free(shader->InfoLog);
242
Carl Worth2d2561e2010-06-23 15:43:38 -0700243 shader->InfoLog = state->info_log;
244
Kenneth Graunke116f1d42010-06-25 14:10:01 -0700245 /* Retain any live IR, but trash the rest. */
Ian Romanick60e2d062010-07-20 11:27:38 -0700246 reparent_ir(shader->ir, shader);
Kenneth Graunke116f1d42010-06-25 14:10:01 -0700247
Carl Worth2d2561e2010-06-23 15:43:38 -0700248 talloc_free(state);
Ian Romanickca97bd32010-06-19 01:39:14 -0700249
Ian Romanick8ce55db2010-06-17 12:01:18 -0700250 return;
251}
Ian Romanick61d4aa02010-06-14 14:46:09 -0700252
Ian Romanick8ce55db2010-06-17 12:01:18 -0700253int
254main(int argc, char **argv)
255{
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700256 int status = EXIT_SUCCESS;
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400257 struct gl_context local_ctx;
258 struct gl_context *ctx = &local_ctx;
Eric Anholt5d0f4302010-08-18 12:02:35 -0700259
Ian Romanick8ce55db2010-06-17 12:01:18 -0700260 int c;
261 int idx = 0;
262 while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
263 /* empty */ ;
264
265
266 if (argc <= optind)
267 usage_fail(argv[0]);
268
Chia-I Wu1a5b32c2010-09-08 18:52:27 +0800269 initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL);
Chia-I Wudc754582010-09-08 18:48:12 +0800270
Eric Anholt849e1812010-06-30 11:49:17 -0700271 struct gl_shader_program *whole_program;
Carl Worthbe83eb82010-06-23 13:34:05 -0700272
Eric Anholt849e1812010-06-30 11:49:17 -0700273 whole_program = talloc_zero (NULL, struct gl_shader_program);
Carl Worthbe83eb82010-06-23 13:34:05 -0700274 assert(whole_program != NULL);
Ian Romanick8ce55db2010-06-17 12:01:18 -0700275
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700276 for (/* empty */; argc > optind; optind++) {
Eric Anholt16b68b12010-06-30 11:05:43 -0700277 whole_program->Shaders = (struct gl_shader **)
Carl Worth26bbfb72010-06-23 19:09:56 -0700278 talloc_realloc(whole_program, whole_program->Shaders,
Eric Anholt16b68b12010-06-30 11:05:43 -0700279 struct gl_shader *, whole_program->NumShaders + 1);
Carl Worthbe83eb82010-06-23 13:34:05 -0700280 assert(whole_program->Shaders != NULL);
Ian Romanick8ce55db2010-06-17 12:01:18 -0700281
Eric Anholt16b68b12010-06-30 11:05:43 -0700282 struct gl_shader *shader = talloc_zero(whole_program, gl_shader);
Ian Romanick8ce55db2010-06-17 12:01:18 -0700283
Carl Worthbe83eb82010-06-23 13:34:05 -0700284 whole_program->Shaders[whole_program->NumShaders] = shader;
285 whole_program->NumShaders++;
Ian Romanick8ce55db2010-06-17 12:01:18 -0700286
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700287 const unsigned len = strlen(argv[optind]);
288 if (len < 6)
289 usage_fail(argv[0]);
Ian Romanick8ce55db2010-06-17 12:01:18 -0700290
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700291 const char *const ext = & argv[optind][len - 5];
292 if (strncmp(".vert", ext, 5) == 0)
Kenneth Graunke29e60872010-06-17 15:28:34 -0700293 shader->Type = GL_VERTEX_SHADER;
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700294 else if (strncmp(".geom", ext, 5) == 0)
Kenneth Graunke29e60872010-06-17 15:28:34 -0700295 shader->Type = GL_GEOMETRY_SHADER;
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700296 else if (strncmp(".frag", ext, 5) == 0)
Kenneth Graunke29e60872010-06-17 15:28:34 -0700297 shader->Type = GL_FRAGMENT_SHADER;
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700298 else
299 usage_fail(argv[0]);
300
Eric Anholt16b68b12010-06-30 11:05:43 -0700301 shader->Source = load_text_file(whole_program, argv[optind]);
Kenneth Graunke2848c4c2010-06-16 12:10:55 -0700302 if (shader->Source == NULL) {
303 printf("File \"%s\" does not exist.\n", argv[optind]);
304 exit(EXIT_FAILURE);
305 }
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700306
Chia-I Wudc754582010-09-08 18:48:12 +0800307 compile_shader(ctx, shader);
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700308
Kenneth Graunke29e60872010-06-17 15:28:34 -0700309 if (!shader->CompileStatus) {
Kenneth Graunkef3eb42d2010-06-19 11:31:01 -0700310 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700311 status = EXIT_FAILURE;
312 break;
313 }
314 }
315
Ian Romanickc648a122010-06-17 19:51:48 -0700316 if ((status == EXIT_SUCCESS) && do_link) {
Eric Anholt5d0f4302010-08-18 12:02:35 -0700317 link_shaders(ctx, whole_program);
Carl Worthbe83eb82010-06-23 13:34:05 -0700318 status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
Ian Romanick4d962e62010-07-02 14:43:01 -0700319
320 if (strlen(whole_program->InfoLog) > 0)
321 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
Ian Romanick832dfa52010-06-17 15:04:20 -0700322 }
323
Ian Romanick3322fba2010-10-14 13:28:42 -0700324 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
Ian Romanick3fb87872010-07-09 14:09:34 -0700325 talloc_free(whole_program->_LinkedShaders[i]);
326
Carl Worthbe83eb82010-06-23 13:34:05 -0700327 talloc_free(whole_program);
Ian Romanickefc15f82010-06-28 13:17:18 -0700328 _mesa_glsl_release_types();
Ian Romanickd5be2ac2010-07-20 11:29:46 -0700329 _mesa_glsl_release_functions();
Carl Worthbe83eb82010-06-23 13:34:05 -0700330
Ian Romanick6fd9fb22010-06-17 12:22:16 -0700331 return status;
Ian Romanick61d4aa02010-06-14 14:46:09 -0700332}