X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fmain.cpp;h=ed6f122798aa654cc2017ed64996b3feb1baf225;hb=0d108116bd80b757fb01a84a9f1946ef870b57b8;hp=16b2cf84c53452cedb6e935540dbd04307943bd0;hpb=22c23dedad4e7f362ffbd990f1c2d5caf4cae75a;p=mesa.git diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 16b2cf84c53..ed6f122798a 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -20,80 +20,98 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include -#include #include -#include -#include -#include -#include +/** @file main.cpp + * + * This file is the main() routine and scaffolding for producing + * builtin_compiler (which doesn't include builtins itself and is used + * to generate the profile information for builtin_function.cpp), and + * for glsl_compiler (which does include builtins and can be used to + * offline compile GLSL code and examine the resulting GLSL IR. + */ #include "ast.h" #include "glsl_parser_extras.h" -#include "glsl_parser.h" #include "ir_optimization.h" #include "ir_print_visitor.h" #include "program.h" +#include "loop_analysis.h" +#include "standalone_scaffolding.h" + +static void +initialize_context(struct gl_context *ctx, gl_api api) +{ + initialize_context_to_defaults(ctx, api); -/* Returned string will have 'ctx' as its talloc owner. */ + /* The standalone compiler needs to claim support for almost + * everything in order to compile the built-in functions. + */ + ctx->Const.GLSLVersion = 140; + ctx->Extensions.ARB_ES3_compatibility = true; + + ctx->Const.MaxClipPlanes = 8; + ctx->Const.MaxDrawBuffers = 2; + + /* More than the 1.10 minimum to appease parser tests taken from + * apps that (hopefully) already checked the number of coords. + */ + ctx->Const.MaxTextureCoordUnits = 4; + + ctx->Driver.NewShader = _mesa_new_shader; +} + +/* Returned string will have 'ctx' as its ralloc owner. */ static char * -load_text_file(void *ctx, const char *file_name, size_t *size) +load_text_file(void *ctx, const char *file_name) { char *text = NULL; - struct stat st; - ssize_t total_read = 0; - int fd = open(file_name, O_RDONLY); + size_t size; + size_t total_read = 0; + FILE *fp = fopen(file_name, "rb"); - *size = 0; - if (fd < 0) { + if (!fp) { return NULL; } - if (fstat(fd, & st) == 0) { - text = (char *) talloc_size(ctx, st.st_size + 1); - if (text != NULL) { - do { - ssize_t bytes = read(fd, text + total_read, - st.st_size - total_read); - if (bytes < 0) { - free(text); - text = NULL; - break; - } - - if (bytes == 0) { - break; - } - - total_read += bytes; - } while (total_read < st.st_size); - - text[total_read] = '\0'; - *size = total_read; - } + fseek(fp, 0L, SEEK_END); + size = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + text = (char *) ralloc_size(ctx, size + 1); + if (text != NULL) { + do { + size_t bytes = fread(text + total_read, + 1, size - total_read, fp); + if (bytes < size - total_read) { + free(text); + text = NULL; + break; + } + + if (bytes == 0) { + break; + } + + total_read += bytes; + } while (total_read < size); + + text[total_read] = '\0'; } - close(fd); + fclose(fp); return text; } - -void -usage_fail(const char *name) -{ - printf("%s \n", name); - exit(EXIT_FAILURE); -} - - +int glsl_es = 0; int dump_ast = 0; int dump_hir = 0; int dump_lir = 0; int do_link = 0; const struct option compiler_opts[] = { + { "glsl-es", 0, &glsl_es, 1 }, { "dump-ast", 0, &dump_ast, 1 }, { "dump-hir", 0, &dump_hir, 1 }, { "dump-lir", 0, &dump_lir, 1 }, @@ -101,33 +119,34 @@ const struct option compiler_opts[] = { { NULL, 0, NULL, 0 } }; +/** + * \brief Print proper usage and exit with failure. + */ void -compile_shader(struct glsl_shader *shader) +usage_fail(const char *name) { - struct _mesa_glsl_parse_state *state; - - state = talloc_zero(talloc_parent(shader), struct _mesa_glsl_parse_state); - switch (shader->Type) { - case GL_VERTEX_SHADER: state->target = vertex_shader; break; - case GL_FRAGMENT_SHADER: state->target = fragment_shader; break; - case GL_GEOMETRY_SHADER: state->target = geometry_shader; break; + const char *header = + "usage: %s [options] \n" + "\n" + "Possible options are:\n"; + printf(header, name, name); + for (const struct option *o = compiler_opts; o->name != 0; ++o) { + printf(" --%s\n", o->name); } + exit(EXIT_FAILURE); +} + + +void +compile_shader(struct gl_context *ctx, struct gl_shader *shader) +{ + struct _mesa_glsl_parse_state *state = + new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); - state->scanner = NULL; - state->translation_unit.make_empty(); - state->symbols = new(shader) glsl_symbol_table; - state->info_log = talloc_strdup(shader, ""); - state->error = false; - state->temp_index = 0; - state->loop_or_switch_nesting = NULL; - state->ARB_texture_rectangle_enable = true; - - /* Create a new context for the preprocessor output. Ultimately, this - * should probably be the parser context, but there isn't one yet. - */ const char *source = shader->Source; - state->error = preprocess(shader, &source, &state->info_log); + state->error = glcpp_preprocess(state, &source, &state->info_log, + state->extensions, ctx) != 0; if (!state->error) { _mesa_glsl_lexer_ctor(state, source); @@ -143,51 +162,49 @@ compile_shader(struct glsl_shader *shader) printf("\n\n"); } - shader->ir.make_empty(); + shader->ir = new(shader) exec_list; if (!state->error && !state->translation_unit.is_empty()) - _mesa_ast_to_hir(&shader->ir, state); - - validate_ir_tree(&shader->ir); + _mesa_ast_to_hir(shader->ir, state); /* Print out the unoptimized IR. */ if (!state->error && dump_hir) { - _mesa_print_ir(&shader->ir, state); + validate_ir_tree(shader->ir); + _mesa_print_ir(shader->ir, state); } /* Optimization passes */ - if (!state->error && !shader->ir.is_empty()) { + if (!state->error && !shader->ir->is_empty()) { bool progress; do { - progress = false; - - progress = do_function_inlining(&shader->ir) || progress; - progress = do_if_simplification(&shader->ir) || progress; - progress = do_copy_propagation(&shader->ir) || progress; - progress = do_dead_code_local(&shader->ir) || progress; - progress = do_dead_code_unlinked(state, &shader->ir) || progress; - progress = do_constant_variable_unlinked(&shader->ir) || progress; - progress = do_constant_folding(&shader->ir) || progress; - progress = do_vec_index_to_swizzle(&shader->ir) || progress; - progress = do_swizzle_swizzle(&shader->ir) || progress; + progress = do_common_optimization(shader->ir, false, false, 32); } while (progress); + + validate_ir_tree(shader->ir); } - validate_ir_tree(&shader->ir); /* Print out the resulting IR */ if (!state->error && dump_lir) { - _mesa_print_ir(&shader->ir, state); + _mesa_print_ir(shader->ir, state); } shader->symbols = state->symbols; shader->CompileStatus = !state->error; + shader->Version = state->language_version; + shader->IsES = state->es_shader; + memcpy(shader->builtins_to_link, state->builtins_to_link, + sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); + shader->num_builtins_to_link = state->num_builtins_to_link; if (shader->InfoLog) - talloc_free(shader->InfoLog); + ralloc_free(shader->InfoLog); shader->InfoLog = state->info_log; - talloc_free(state); + /* Retain any live IR, but trash the rest. */ + reparent_ir(shader->ir, shader); + + ralloc_free(state); return; } @@ -196,6 +213,8 @@ int main(int argc, char **argv) { int status = EXIT_SUCCESS; + struct gl_context local_ctx; + struct gl_context *ctx = &local_ctx; int c; int idx = 0; @@ -206,18 +225,21 @@ main(int argc, char **argv) if (argc <= optind) usage_fail(argv[0]); - struct glsl_program *whole_program; + initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT); - whole_program = talloc_zero (NULL, struct glsl_program); + struct gl_shader_program *whole_program; + + whole_program = rzalloc (NULL, struct gl_shader_program); assert(whole_program != NULL); + whole_program->InfoLog = ralloc_strdup(whole_program, ""); for (/* empty */; argc > optind; optind++) { - whole_program->Shaders = (struct glsl_shader **) - talloc_realloc(whole_program, whole_program->Shaders, - struct glsl_shader *, whole_program->NumShaders + 1); + whole_program->Shaders = + reralloc(whole_program, whole_program->Shaders, + struct gl_shader *, whole_program->NumShaders + 1); assert(whole_program->Shaders != NULL); - struct glsl_shader *shader = talloc_zero(whole_program, glsl_shader); + struct gl_shader *shader = rzalloc(whole_program, gl_shader); whole_program->Shaders[whole_program->NumShaders] = shader; whole_program->NumShaders++; @@ -227,7 +249,7 @@ main(int argc, char **argv) usage_fail(argv[0]); const char *const ext = & argv[optind][len - 5]; - if (strncmp(".vert", ext, 5) == 0) + if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0) shader->Type = GL_VERTEX_SHADER; else if (strncmp(".geom", ext, 5) == 0) shader->Type = GL_GEOMETRY_SHADER; @@ -236,14 +258,13 @@ main(int argc, char **argv) else usage_fail(argv[0]); - shader->Source = load_text_file(whole_program, - argv[optind], &shader->SourceLen); + shader->Source = load_text_file(whole_program, argv[optind]); if (shader->Source == NULL) { printf("File \"%s\" does not exist.\n", argv[optind]); exit(EXIT_FAILURE); } - compile_shader(shader); + compile_shader(ctx, shader); if (!shader->CompileStatus) { printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog); @@ -253,11 +274,19 @@ main(int argc, char **argv) } if ((status == EXIT_SUCCESS) && do_link) { - link_shaders(whole_program); + link_shaders(ctx, whole_program); status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE; + + if (strlen(whole_program->InfoLog) > 0) + printf("Info log for linking:\n%s\n", whole_program->InfoLog); } - talloc_free(whole_program); + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) + ralloc_free(whole_program->_LinkedShaders[i]); + + ralloc_free(whole_program); + _mesa_glsl_release_types(); + _mesa_glsl_release_functions(); return status; }