Home | History | Annotate | Download | only in glsl
      1 /*
      2  * Copyright  2011 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 
     24 /**
     25  * \file test_optpass.cpp
     26  *
     27  * Standalone test for optimization passes.
     28  *
     29  * This file provides the "optpass" command for the standalone
     30  * glsl_test app.  It accepts either GLSL or high-level IR as input,
     31  * and performs the optimiation passes specified on the command line.
     32  * It outputs the IR, both before and after optimiations.
     33  */
     34 
     35 #include <string>
     36 #include <iostream>
     37 #include <sstream>
     38 #include <getopt.h>
     39 
     40 #include "ast.h"
     41 #include "ir_optimization.h"
     42 #include "program.h"
     43 #include "ir_reader.h"
     44 #include "standalone_scaffolding.h"
     45 
     46 using namespace std;
     47 
     48 static string read_stdin_to_eof()
     49 {
     50    stringbuf sb;
     51    cin.get(sb, '\0');
     52    return sb.str();
     53 }
     54 
     55 static GLboolean
     56 do_optimization(struct exec_list *ir, const char *optimization,
     57                 const struct gl_shader_compiler_options *options)
     58 {
     59    int int_0;
     60    int int_1;
     61    int int_2;
     62    int int_3;
     63    int int_4;
     64 
     65    if (sscanf(optimization, "do_common_optimization ( %d ) ", &int_0) == 1) {
     66       return do_common_optimization(ir, int_0 != 0, false, options, true);
     67    } else if (strcmp(optimization, "do_algebraic") == 0) {
     68       return do_algebraic(ir, true, options);
     69    } else if (strcmp(optimization, "do_constant_folding") == 0) {
     70       return do_constant_folding(ir);
     71    } else if (strcmp(optimization, "do_constant_variable") == 0) {
     72       return do_constant_variable(ir);
     73    } else if (strcmp(optimization, "do_constant_variable_unlinked") == 0) {
     74       return do_constant_variable_unlinked(ir);
     75    } else if (strcmp(optimization, "do_copy_propagation") == 0) {
     76       return do_copy_propagation(ir);
     77    } else if (strcmp(optimization, "do_copy_propagation_elements") == 0) {
     78       return do_copy_propagation_elements(ir);
     79    } else if (strcmp(optimization, "do_constant_propagation") == 0) {
     80       return do_constant_propagation(ir);
     81    } else if (strcmp(optimization, "do_dead_code") == 0) {
     82       return do_dead_code(ir, false);
     83    } else if (strcmp(optimization, "do_dead_code_local") == 0) {
     84       return do_dead_code_local(ir);
     85    } else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
     86       return do_dead_code_unlinked(ir);
     87    } else if (strcmp(optimization, "do_dead_functions") == 0) {
     88       return do_dead_functions(ir);
     89    } else if (strcmp(optimization, "do_function_inlining") == 0) {
     90       return do_function_inlining(ir);
     91    } else if (sscanf(optimization,
     92                      "do_lower_jumps ( %d , %d , %d , %d , %d ) ",
     93                      &int_0, &int_1, &int_2, &int_3, &int_4) == 5) {
     94       return do_lower_jumps(ir, int_0 != 0, int_1 != 0, int_2 != 0,
     95                             int_3 != 0, int_4 != 0);
     96    } else if (strcmp(optimization, "do_lower_texture_projection") == 0) {
     97       return do_lower_texture_projection(ir);
     98    } else if (strcmp(optimization, "do_if_simplification") == 0) {
     99       return do_if_simplification(ir);
    100    } else if (sscanf(optimization, "lower_if_to_cond_assign ( %d ) ",
    101                      &int_0) == 1) {
    102       return lower_if_to_cond_assign(MESA_SHADER_VERTEX, ir, int_0);
    103    } else if (strcmp(optimization, "do_mat_op_to_vec") == 0) {
    104       return do_mat_op_to_vec(ir);
    105    } else if (strcmp(optimization, "do_noop_swizzle") == 0) {
    106       return do_noop_swizzle(ir);
    107    } else if (strcmp(optimization, "do_structure_splitting") == 0) {
    108       return do_structure_splitting(ir);
    109    } else if (strcmp(optimization, "do_swizzle_swizzle") == 0) {
    110       return do_swizzle_swizzle(ir);
    111    } else if (strcmp(optimization, "do_tree_grafting") == 0) {
    112       return do_tree_grafting(ir);
    113    } else if (strcmp(optimization, "do_vec_index_to_cond_assign") == 0) {
    114       return do_vec_index_to_cond_assign(ir);
    115    } else if (strcmp(optimization, "do_vec_index_to_swizzle") == 0) {
    116       return do_vec_index_to_swizzle(ir);
    117    } else if (strcmp(optimization, "lower_discard") == 0) {
    118       return lower_discard(ir);
    119    } else if (sscanf(optimization, "lower_instructions ( %d ) ",
    120                      &int_0) == 1) {
    121       return lower_instructions(ir, int_0);
    122    } else if (strcmp(optimization, "lower_noise") == 0) {
    123       return lower_noise(ir);
    124    } else if (sscanf(optimization, "lower_variable_index_to_cond_assign "
    125                      "( %d , %d , %d , %d ) ", &int_0, &int_1, &int_2,
    126                      &int_3) == 4) {
    127       return lower_variable_index_to_cond_assign(MESA_SHADER_VERTEX, ir,
    128                                                  int_0 != 0, int_1 != 0,
    129                                                  int_2 != 0, int_3 != 0);
    130    } else if (sscanf(optimization, "lower_quadop_vector ( %d ) ",
    131                      &int_0) == 1) {
    132       return lower_quadop_vector(ir, int_0 != 0);
    133    } else if (strcmp(optimization, "optimize_redundant_jumps") == 0) {
    134       return optimize_redundant_jumps(ir);
    135    } else {
    136       printf("Unrecognized optimization %s\n", optimization);
    137       exit(EXIT_FAILURE);
    138       return false;
    139    }
    140 }
    141 
    142 static GLboolean
    143 do_optimization_passes(struct exec_list *ir, char **optimizations,
    144                        int num_optimizations, bool quiet,
    145                        const struct gl_shader_compiler_options *options)
    146 {
    147    GLboolean overall_progress = false;
    148 
    149    for (int i = 0; i < num_optimizations; ++i) {
    150       const char *optimization = optimizations[i];
    151       if (!quiet) {
    152          printf("*** Running optimization %s...", optimization);
    153       }
    154       GLboolean progress = do_optimization(ir, optimization, options);
    155       if (!quiet) {
    156          printf("%s\n", progress ? "progress" : "no progress");
    157       }
    158       validate_ir_tree(ir);
    159 
    160       overall_progress = overall_progress || progress;
    161    }
    162 
    163    return overall_progress;
    164 }
    165 
    166 int test_optpass(int argc, char **argv)
    167 {
    168    int input_format_ir = 0; /* 0=glsl, 1=ir */
    169    int loop = 0;
    170    int shader_type = GL_VERTEX_SHADER;
    171    int quiet = 0;
    172 
    173    const struct option optpass_opts[] = {
    174       { "input-ir", no_argument, &input_format_ir, 1 },
    175       { "input-glsl", no_argument, &input_format_ir, 0 },
    176       { "loop", no_argument, &loop, 1 },
    177       { "vertex-shader", no_argument, &shader_type, GL_VERTEX_SHADER },
    178       { "fragment-shader", no_argument, &shader_type, GL_FRAGMENT_SHADER },
    179       { "quiet", no_argument, &quiet, 1 },
    180       { NULL, 0, NULL, 0 }
    181    };
    182 
    183    int idx = 0;
    184    int c;
    185    while ((c = getopt_long(argc, argv, "", optpass_opts, &idx)) != -1) {
    186       if (c != 0) {
    187          printf("*** usage: %s optpass <optimizations> <options>\n", argv[0]);
    188          printf("\n");
    189          printf("Possible options are:\n");
    190          printf("  --input-ir: input format is IR\n");
    191          printf("  --input-glsl: input format is GLSL (the default)\n");
    192          printf("  --loop: run optimizations repeatedly until no progress\n");
    193          printf("  --vertex-shader: test with a vertex shader (the default)\n");
    194          printf("  --fragment-shader: test with a fragment shader\n");
    195          exit(EXIT_FAILURE);
    196       }
    197    }
    198 
    199    struct gl_context local_ctx;
    200    struct gl_context *ctx = &local_ctx;
    201    initialize_context_to_defaults(ctx, API_OPENGL_COMPAT);
    202 
    203    ir_variable::temporaries_allocate_names = true;
    204 
    205    struct gl_shader *shader = rzalloc(NULL, struct gl_shader);
    206    shader->Type = shader_type;
    207    shader->Stage = _mesa_shader_enum_to_shader_stage(shader_type);
    208 
    209    string input = read_stdin_to_eof();
    210 
    211    struct _mesa_glsl_parse_state *state
    212       = new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
    213 
    214    if (input_format_ir) {
    215       shader->ir = new(shader) exec_list;
    216       _mesa_glsl_initialize_types(state);
    217       _mesa_glsl_read_ir(state, shader->ir, input.c_str(), true);
    218    } else {
    219       shader->Source = input.c_str();
    220       const char *source = shader->Source;
    221       state->error = glcpp_preprocess(state, &source, &state->info_log,
    222                                       NULL, NULL, ctx) != 0;
    223 
    224       if (!state->error) {
    225          _mesa_glsl_lexer_ctor(state, source);
    226          _mesa_glsl_parse(state);
    227          _mesa_glsl_lexer_dtor(state);
    228       }
    229 
    230       shader->ir = new(shader) exec_list;
    231       if (!state->error && !state->translation_unit.is_empty())
    232          _mesa_ast_to_hir(shader->ir, state);
    233    }
    234 
    235    /* Print out the initial IR */
    236    if (!state->error && !quiet) {
    237       printf("*** pre-optimization IR:\n");
    238       _mesa_print_ir(stdout, shader->ir, state);
    239       printf("\n--\n");
    240    }
    241 
    242    /* Optimization passes */
    243    if (!state->error) {
    244       GLboolean progress;
    245       const struct gl_shader_compiler_options *options =
    246          &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader_type)];
    247       do {
    248          progress = do_optimization_passes(shader->ir, &argv[optind],
    249                                            argc - optind, quiet != 0, options);
    250       } while (loop && progress);
    251    }
    252 
    253    /* Print out the resulting IR */
    254    if (!state->error) {
    255       if (!quiet) {
    256          printf("*** resulting IR:\n");
    257       }
    258       _mesa_print_ir(stdout, shader->ir, state);
    259       if (!quiet) {
    260          printf("\n--\n");
    261       }
    262    }
    263 
    264    if (state->error) {
    265       printf("*** error(s) occurred:\n");
    266       printf("%s\n", state->info_log);
    267       printf("--\n");
    268    }
    269 
    270    ralloc_free(state);
    271    ralloc_free(shader);
    272 
    273    return state->error;
    274 }
    275 
    276