main.cpp revision 127308b4be077e5bdf60f76320307550921e86bb
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright © 2008, 2009 Intel Corporation 359d709d503bab6e2b61931737e662dd293b40578ccornelius * 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Permission is hereby granted, free of charge, to any person obtaining a 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * copy of this software and associated documentation files (the "Software"), 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to deal in the Software without restriction, including without limitation 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and/or sell copies of the Software, and to permit persons to whom the 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Software is furnished to do so, subject to the following conditions: 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The above copyright notice and this permission notice (including the next 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * paragraph) shall be included in all copies or substantial portions of the 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Software. 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * DEALINGS IN THE SOFTWARE. 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <cstdlib> 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <cstdio> 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <getopt.h> 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <sys/types.h> 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <sys/stat.h> 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <fcntl.h> 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <unistd.h> 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ast.h" 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "glsl_parser_extras.h" 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "glsl_parser.h" 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ir_optimization.h" 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ir_print_visitor.h" 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "program.h" 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Returned string will have 'ctx' as its talloc owner. */ 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char * 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruload_text_file(void *ctx, const char *file_name) 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru char *text = NULL; 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru struct stat st; 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ssize_t total_read = 0; 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int fd = open(file_name, O_RDONLY); 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (fd < 0) { 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (fstat(fd, & st) == 0) { 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru text = (char *) talloc_size(ctx, st.st_size + 1); 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (text != NULL) { 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru do { 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ssize_t bytes = read(fd, text + total_read, 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru st.st_size - total_read); 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (bytes < 0) { 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru free(text); 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru text = NULL; 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (bytes == 0) { 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru total_read += bytes; 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } while (total_read < st.st_size); 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru text[total_read] = '\0'; 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru close(fd); 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return text; 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruusage_fail(const char *name) 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru printf("%s <filename.frag|filename.vert>\n", name); 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru exit(EXIT_FAILURE); 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint dump_ast = 0; 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint dump_hir = 0; 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint dump_lir = 0; 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint do_link = 0; 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst struct option compiler_opts[] = { 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { "dump-ast", 0, &dump_ast, 1 }, 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { "dump-hir", 0, &dump_hir, 1 }, 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { "dump-lir", 0, &dump_lir, 1 }, 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { "link", 0, &do_link, 1 }, 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { NULL, 0, NULL, 0 } 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querusteal_memory(ir_instruction *ir, void *new_ctx) 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru talloc_steal(new_ctx, ir); 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querucompile_shader(struct gl_shader *shader) 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru struct _mesa_glsl_parse_state *state; 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state = talloc_zero(talloc_parent(shader), struct _mesa_glsl_parse_state); 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru switch (shader->Type) { 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case GL_VERTEX_SHADER: state->target = vertex_shader; break; 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case GL_FRAGMENT_SHADER: state->target = fragment_shader; break; 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case GL_GEOMETRY_SHADER: state->target = geometry_shader; break; 11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->scanner = NULL; 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->translation_unit.make_empty(); 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->symbols = new(shader) glsl_symbol_table; 12459d709d503bab6e2b61931737e662dd293b40578ccornelius state->info_log = talloc_strdup(shader, ""); 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->error = false; 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->temp_index = 0; 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->loop_or_switch_nesting = NULL; 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->ARB_texture_rectangle_enable = true; 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->Const.MaxDrawBuffers = 2; 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->Const.MaxTextureCoords = 4; 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const char *source = shader->Source; 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state->error = preprocess(state, &source, &state->info_log); 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!state->error) { 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru _mesa_glsl_lexer_ctor(state, source); 13883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius _mesa_glsl_parse(state); 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru _mesa_glsl_lexer_dtor(state); 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 141 142 if (dump_ast) { 143 foreach_list_const(n, &state->translation_unit) { 144 ast_node *ast = exec_node_data(ast_node, n, link); 145 ast->print(); 146 } 147 printf("\n\n"); 148 } 149 150 shader->ir = new(shader) exec_list; 151 if (!state->error && !state->translation_unit.is_empty()) 152 _mesa_ast_to_hir(shader->ir, state); 153 154 validate_ir_tree(shader->ir); 155 156 /* Print out the unoptimized IR. */ 157 if (!state->error && dump_hir) { 158 _mesa_print_ir(shader->ir, state); 159 } 160 161 /* Optimization passes */ 162 if (!state->error && !shader->ir->is_empty()) { 163 bool progress; 164 do { 165 progress = false; 166 167 progress = do_function_inlining(shader->ir) || progress; 168 progress = do_if_simplification(shader->ir) || progress; 169 progress = do_copy_propagation(shader->ir) || progress; 170 progress = do_dead_code_local(shader->ir) || progress; 171 progress = do_dead_code_unlinked(state, shader->ir) || progress; 172 progress = do_constant_variable_unlinked(shader->ir) || progress; 173 progress = do_constant_folding(shader->ir) || progress; 174 progress = do_vec_index_to_swizzle(shader->ir) || progress; 175 progress = do_swizzle_swizzle(shader->ir) || progress; 176 } while (progress); 177 } 178 179 validate_ir_tree(shader->ir); 180 181 /* Print out the resulting IR */ 182 if (!state->error && dump_lir) { 183 _mesa_print_ir(shader->ir, state); 184 } 185 186 shader->symbols = state->symbols; 187 shader->CompileStatus = !state->error; 188 189 if (shader->InfoLog) 190 talloc_free(shader->InfoLog); 191 192 shader->InfoLog = state->info_log; 193 194 /* Retain any live IR, but trash the rest. */ 195 foreach_list(node, shader->ir) { 196 visit_tree((ir_instruction *) node, steal_memory, shader); 197 } 198 199 talloc_free(state); 200 201 return; 202} 203 204int 205main(int argc, char **argv) 206{ 207 int status = EXIT_SUCCESS; 208 209 int c; 210 int idx = 0; 211 while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) 212 /* empty */ ; 213 214 215 if (argc <= optind) 216 usage_fail(argv[0]); 217 218 struct gl_shader_program *whole_program; 219 220 whole_program = talloc_zero (NULL, struct gl_shader_program); 221 assert(whole_program != NULL); 222 223 for (/* empty */; argc > optind; optind++) { 224 whole_program->Shaders = (struct gl_shader **) 225 talloc_realloc(whole_program, whole_program->Shaders, 226 struct gl_shader *, whole_program->NumShaders + 1); 227 assert(whole_program->Shaders != NULL); 228 229 struct gl_shader *shader = talloc_zero(whole_program, gl_shader); 230 231 whole_program->Shaders[whole_program->NumShaders] = shader; 232 whole_program->NumShaders++; 233 234 const unsigned len = strlen(argv[optind]); 235 if (len < 6) 236 usage_fail(argv[0]); 237 238 const char *const ext = & argv[optind][len - 5]; 239 if (strncmp(".vert", ext, 5) == 0) 240 shader->Type = GL_VERTEX_SHADER; 241 else if (strncmp(".geom", ext, 5) == 0) 242 shader->Type = GL_GEOMETRY_SHADER; 243 else if (strncmp(".frag", ext, 5) == 0) 244 shader->Type = GL_FRAGMENT_SHADER; 245 else 246 usage_fail(argv[0]); 247 248 shader->Source = load_text_file(whole_program, argv[optind]); 249 if (shader->Source == NULL) { 250 printf("File \"%s\" does not exist.\n", argv[optind]); 251 exit(EXIT_FAILURE); 252 } 253 254 compile_shader(shader); 255 256 if (!shader->CompileStatus) { 257 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog); 258 status = EXIT_FAILURE; 259 break; 260 } 261 } 262 263 if ((status == EXIT_SUCCESS) && do_link) { 264 link_shaders(whole_program); 265 status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE; 266 } 267 268 talloc_free(whole_program); 269 _mesa_glsl_release_types(); 270 271 return status; 272} 273