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