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 "ir_print_visitor.h"
     43 #include "program.h"
     44 #include "ir_reader.h"
     45 #include "standalone_scaffolding.h"
     46 
     47 using namespace std;
     48 
     49 static string read_stdin_to_eof()
     50 {
     51    stringbuf sb;
     52    cin.get(sb, '\0');
     53    return sb.str();
     54 }
     55 
     56 static GLboolean
     57 do_optimization(struct exec_list *ir, const char *optimization)
     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 , %d ) ",
     66               &int_0, &int_1) == 2) {
     67       return do_common_optimization(ir, int_0 != 0, false, int_1);
     68    } else if (strcmp(optimization, "do_algebraic") == 0) {
     69       return do_algebraic(ir);
     70    } else if (strcmp(optimization, "do_constant_folding") == 0) {
     71       return do_constant_folding(ir);
     72    } else if (strcmp(optimization, "do_constant_variable") == 0) {
     73       return do_constant_variable(ir);
     74    } else if (strcmp(optimization, "do_constant_variable_unlinked") == 0) {
     75       return do_constant_variable_unlinked(ir);
     76    } else if (strcmp(optimization, "do_copy_propagation") == 0) {
     77       return do_copy_propagation(ir);
     78    } else if (strcmp(optimization, "do_copy_propagation_elements") == 0) {
     79       return do_copy_propagation_elements(ir);
     80    } else if (strcmp(optimization, "do_constant_propagation") == 0) {
     81       return do_constant_propagation(ir);
     82    } else if (strcmp(optimization, "do_dead_code") == 0) {
     83       return do_dead_code(ir, false);
     84    } else if (strcmp(optimization, "do_dead_code_local") == 0) {
     85       return do_dead_code_local(ir);
     86    } else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
     87       return do_dead_code_unlinked(ir);
     88    } else if (strcmp(optimization, "do_dead_functions") == 0) {
     89       return do_dead_functions(ir);
     90    } else if (strcmp(optimization, "do_function_inlining") == 0) {
     91       return do_function_inlining(ir);
     92    } else if (sscanf(optimization,
     93                      "do_lower_jumps ( %d , %d , %d , %d , %d ) ",
     94                      &int_0, &int_1, &int_2, &int_3, &int_4) == 5) {
     95       return do_lower_jumps(ir, int_0 != 0, int_1 != 0, int_2 != 0,
     96                             int_3 != 0, int_4 != 0);
     97    } else if (strcmp(optimization, "do_lower_texture_projection") == 0) {
     98       return do_lower_texture_projection(ir);
     99    } else if (strcmp(optimization, "do_if_simplification") == 0) {
    100       return do_if_simplification(ir);
    101    } else if (sscanf(optimization, "lower_if_to_cond_assign ( %d ) ",
    102                      &int_0) == 1) {
    103       return lower_if_to_cond_assign(ir, int_0);
    104    } else if (strcmp(optimization, "do_mat_op_to_vec") == 0) {
    105       return do_mat_op_to_vec(ir);
    106    } else if (strcmp(optimization, "do_noop_swizzle") == 0) {
    107       return do_noop_swizzle(ir);
    108    } else if (strcmp(optimization, "do_structure_splitting") == 0) {
    109       return do_structure_splitting(ir);
    110    } else if (strcmp(optimization, "do_swizzle_swizzle") == 0) {
    111       return do_swizzle_swizzle(ir);
    112    } else if (strcmp(optimization, "do_tree_grafting") == 0) {
    113       return do_tree_grafting(ir);
    114    } else if (strcmp(optimization, "do_vec_index_to_cond_assign") == 0) {
    115       return do_vec_index_to_cond_assign(ir);
    116    } else if (strcmp(optimization, "do_vec_index_to_swizzle") == 0) {
    117       return do_vec_index_to_swizzle(ir);
    118    } else if (strcmp(optimization, "lower_discard") == 0) {
    119       return lower_discard(ir);
    120    } else if (sscanf(optimization, "lower_instructions ( %d ) ",
    121                      &int_0) == 1) {
    122       return lower_instructions(ir, int_0);
    123    } else if (strcmp(optimization, "lower_noise") == 0) {
    124       return lower_noise(ir);
    125    } else if (sscanf(optimization, "lower_variable_index_to_cond_assign "
    126                      "( %d , %d , %d , %d ) ", &int_0, &int_1, &int_2,
    127                      &int_3) == 4) {
    128       return lower_variable_index_to_cond_assign(ir, 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 {
    146    GLboolean overall_progress = false;
    147 
    148    for (int i = 0; i < num_optimizations; ++i) {
    149       const char *optimization = optimizations[i];
    150       if (!quiet) {
    151          printf("*** Running optimization %s...", optimization);
    152       }
    153       GLboolean progress = do_optimization(ir, optimization);
    154       if (!quiet) {
    155          printf("%s\n", progress ? "progress" : "no progress");
    156       }
    157       validate_ir_tree(ir);
    158 
    159       overall_progress = overall_progress || progress;
    160    }
    161 
    162    return overall_progress;
    163 }
    164 
    165 int test_optpass(int argc, char **argv)
    166 {
    167    int input_format_ir = 0; /* 0=glsl, 1=ir */
    168    int loop = 0;
    169    int shader_type = GL_VERTEX_SHADER;
    170    int quiet = 0;
    171 
    172    const struct option optpass_opts[] = {
    173       { "input-ir", no_argument, &input_format_ir, 1 },
    174       { "input-glsl", no_argument, &input_format_ir, 0 },
    175       { "loop", no_argument, &loop, 1 },
    176       { "vertex-shader", no_argument, &shader_type, GL_VERTEX_SHADER },
    177       { "fragment-shader", no_argument, &shader_type, GL_FRAGMENT_SHADER },
    178       { "quiet", no_argument, &quiet, 1 },
    179       { NULL, 0, NULL, 0 }
    180    };
    181 
    182    int idx = 0;
    183    int c;
    184    while ((c = getopt_long(argc, argv, "", optpass_opts, &idx)) != -1) {
    185       if (c != 0) {
    186          printf("*** usage: %s optpass <optimizations> <options>\n", argv[0]);
    187          printf("\n");
    188          printf("Possible options are:\n");
    189          printf("  --input-ir: input format is IR\n");
    190          printf("  --input-glsl: input format is GLSL (the default)\n");
    191          printf("  --loop: run optimizations repeatedly until no progress\n");
    192          printf("  --vertex-shader: test with a vertex shader (the default)\n");
    193          printf("  --fragment-shader: test with a fragment shader\n");
    194          exit(EXIT_FAILURE);
    195       }
    196    }
    197 
    198    struct gl_context local_ctx;
    199    struct gl_context *ctx = &local_ctx;
    200    initialize_context_to_defaults(ctx, API_OPENGL);
    201 
    202    ctx->Driver.NewShader = _mesa_new_shader;
    203 
    204    struct gl_shader *shader = rzalloc(NULL, struct gl_shader);
    205    shader->Type = shader_type;
    206 
    207    string input = read_stdin_to_eof();
    208 
    209    struct _mesa_glsl_parse_state *state
    210       = new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
    211 
    212    if (input_format_ir) {
    213       shader->ir = new(shader) exec_list;
    214       _mesa_glsl_initialize_types(state);
    215       _mesa_glsl_read_ir(state, shader->ir, input.c_str(), true);
    216    } else {
    217       shader->Source = input.c_str();
    218       const char *source = shader->Source;
    219       state->error = glcpp_preprocess(state, &source, &state->info_log,
    220                                 state->extensions, ctx->API) != 0;
    221 
    222       if (!state->error) {
    223          _mesa_glsl_lexer_ctor(state, source);
    224          _mesa_glsl_parse(state);
    225          _mesa_glsl_lexer_dtor(state);
    226       }
    227 
    228       shader->ir = new(shader) exec_list;
    229       if (!state->error && !state->translation_unit.is_empty())
    230          _mesa_ast_to_hir(shader->ir, state);
    231    }
    232 
    233    /* Print out the initial IR */
    234    if (!state->error && !quiet) {
    235       printf("*** pre-optimization IR:\n");
    236       _mesa_print_ir(shader->ir, state);
    237       printf("\n--\n");
    238    }
    239 
    240    /* Optimization passes */
    241    if (!state->error) {
    242       GLboolean progress;
    243       do {
    244          progress = do_optimization_passes(shader->ir, &argv[optind],
    245                                            argc - optind, quiet != 0);
    246       } while (loop && progress);
    247    }
    248 
    249    /* Print out the resulting IR */
    250    if (!state->error) {
    251       if (!quiet) {
    252          printf("*** resulting IR:\n");
    253       }
    254       _mesa_print_ir(shader->ir, state);
    255       if (!quiet) {
    256          printf("\n--\n");
    257       }
    258    }
    259 
    260    if (state->error) {
    261       printf("*** error(s) occurred:\n");
    262       printf("%s\n", state->info_log);
    263       printf("--\n");
    264    }
    265 
    266    ralloc_free(state);
    267    ralloc_free(shader);
    268 
    269    return state->error;
    270 }
    271 
    272