"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/compiler/glsl/lower_xfb_varying.cpp" (16 Sep 2020, 6646 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "lower_xfb_varying.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright ©2019 Collabora Ltd.
    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 lower_xfb_varying.cpp
   26  *
   27  */
   28 
   29 #include "ir.h"
   30 #include "main/mtypes.h"
   31 #include "glsl_symbol_table.h"
   32 #include "util/strndup.h"
   33 
   34 namespace {
   35 
   36 /**
   37  * Visitor that splices varying packing code before every return.
   38  */
   39 class lower_xfb_var_splicer : public ir_hierarchical_visitor
   40 {
   41 public:
   42    explicit lower_xfb_var_splicer(void *mem_ctx,
   43                                   const exec_list *instructions);
   44 
   45    virtual ir_visitor_status visit_leave(ir_return *ret);
   46    virtual ir_visitor_status visit_leave(ir_function_signature *sig);
   47 
   48 private:
   49    /**
   50     * Memory context used to allocate new instructions for the shader.
   51     */
   52    void * const mem_ctx;
   53 
   54    /**
   55     * Instructions that should be spliced into place before each return.
   56     */
   57    const exec_list *instructions;
   58 };
   59 
   60 } /* anonymous namespace */
   61 
   62 
   63 lower_xfb_var_splicer::lower_xfb_var_splicer(void *mem_ctx, const exec_list *instructions)
   64    : mem_ctx(mem_ctx), instructions(instructions)
   65 {
   66 }
   67 
   68 ir_visitor_status
   69 lower_xfb_var_splicer::visit_leave(ir_return *ret)
   70 {
   71    foreach_in_list(ir_instruction, ir, this->instructions) {
   72       ret->insert_before(ir->clone(this->mem_ctx, NULL));
   73    }
   74    return visit_continue;
   75 }
   76 
   77 /** Insert a copy-back assignment at the end of the main() function */
   78 ir_visitor_status
   79 lower_xfb_var_splicer::visit_leave(ir_function_signature *sig)
   80 {
   81    if (strcmp(sig->function_name(), "main") != 0)
   82       return visit_continue;
   83 
   84    if (((ir_instruction*)sig->body.get_tail())->ir_type == ir_type_return)
   85       return visit_continue;
   86 
   87    foreach_in_list(ir_instruction, ir, this->instructions) {
   88       sig->body.push_tail(ir->clone(this->mem_ctx, NULL));
   89    }
   90 
   91    return visit_continue;
   92 }
   93 
   94 static char*
   95 get_field_name(const char *name)
   96 {
   97    const char *first_dot = strchr(name, '.');
   98    const char *first_square_bracket = strchr(name, '[');
   99    int name_size = 0;
  100 
  101    if (!first_square_bracket && !first_dot)
  102       name_size = strlen(name);
  103    else if ((!first_square_bracket ||
  104             (first_dot && first_dot < first_square_bracket)))
  105       name_size = first_dot - name;
  106    else
  107       name_size = first_square_bracket - name;
  108 
  109    return strndup(name, name_size);
  110 }
  111 
  112 /* Generate a new name given the old xfb declaration string by replacing dots
  113  * with '_', brackets with '@' and appending "-xfb" */
  114 static char *
  115 generate_new_name(void *mem_ctx, const char *name)
  116 {
  117    char *new_name;
  118    unsigned i = 0;
  119 
  120    new_name = ralloc_strdup(mem_ctx, name);
  121    while (new_name[i]) {
  122       if (new_name[i] == '.') {
  123          new_name[i] = '_';
  124       } else if (new_name[i] == '[' || new_name[i] == ']') {
  125          new_name[i] = '@';
  126       }
  127       i++;
  128    }
  129 
  130    if (!ralloc_strcat(&new_name, "-xfb")) {
  131       ralloc_free(new_name);
  132       return NULL;
  133    }
  134 
  135    return new_name;
  136 }
  137 
  138 /* Get the dereference for the given variable name. The method is called
  139  * recursively to parse array indices and struct members. */
  140 static bool
  141 get_deref(void *ctx,
  142           const char *name,
  143           struct gl_linked_shader *shader,
  144           ir_dereference **deref,
  145           const glsl_type **type)
  146 {
  147    if (name[0] == '\0') {
  148       /* End */
  149       return (*deref != NULL);
  150    } else if (name[0] == '[') {
  151       /* Array index */
  152       char *endptr = NULL;
  153       unsigned index;
  154 
  155       index = strtol(name + 1, &endptr, 10);
  156       assert(*type != NULL && (*type)->is_array() && endptr[0] == ']');
  157       *deref = new(ctx) ir_dereference_array(*deref, new(ctx) ir_constant(index));
  158       *type = (*type)->without_array();
  159       return get_deref(ctx, endptr + 1, shader, deref, type);
  160    } else if (name[0] == '.') {
  161       /* Struct member */
  162       char *field = get_field_name(name + 1);
  163 
  164       assert(*type != NULL && (*type)->is_struct() && field != NULL);
  165       *deref = new(ctx) ir_dereference_record(*deref, field);
  166       *type = (*type)->field_type(field);
  167       assert(*type != glsl_type::error_type);
  168       name += 1 + strlen(field);
  169       free(field);
  170       return get_deref(ctx, name, shader, deref, type);
  171    } else {
  172       /* Top level variable */
  173       char *field = get_field_name(name);
  174       ir_variable *toplevel_var;
  175 
  176       toplevel_var = shader->symbols->get_variable(field);
  177       name += strlen(field);
  178       free(field);
  179       if (toplevel_var == NULL) {
  180          return false;
  181       }
  182 
  183       *deref = new (ctx) ir_dereference_variable(toplevel_var);
  184       *type = toplevel_var->type;
  185       return get_deref(ctx, name, shader, deref, type);
  186    }
  187 }
  188 
  189 ir_variable *
  190 lower_xfb_varying(void *mem_ctx,
  191                   struct gl_linked_shader *shader,
  192                   const char *old_var_name)
  193 {
  194    exec_list new_instructions;
  195    char *new_var_name;
  196    ir_dereference *deref = NULL;
  197    const glsl_type *type = NULL;
  198 
  199    if (!get_deref(mem_ctx, old_var_name, shader, &deref, &type)) {
  200       if (deref) {
  201          delete deref;
  202       }
  203       return NULL;
  204    }
  205 
  206    new_var_name = generate_new_name(mem_ctx, old_var_name);
  207    ir_variable *new_variable
  208       = new(mem_ctx) ir_variable(type, new_var_name, ir_var_shader_out);
  209    new_variable->data.assigned = true;
  210    new_variable->data.used = true;
  211    shader->ir->push_head(new_variable);
  212    ralloc_free(new_var_name);
  213 
  214    ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(new_variable);
  215    ir_assignment *new_assignment = new(mem_ctx) ir_assignment(lhs, deref);
  216    new_instructions.push_tail(new_assignment);
  217 
  218    lower_xfb_var_splicer splicer(mem_ctx, &new_instructions);
  219    visit_list_elements(&splicer, shader->ir);
  220 
  221    return new_variable;
  222 }