Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2010 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. #include "ast.h"
  25.  
  26. void
  27. ast_type_specifier::print(void) const
  28. {
  29.    if (structure) {
  30.       structure->print();
  31.    } else {
  32.       printf("%s ", type_name);
  33.    }
  34.  
  35.    if (array_specifier) {
  36.       array_specifier->print();
  37.    }
  38. }
  39.  
  40. bool
  41. ast_fully_specified_type::has_qualifiers() const
  42. {
  43.    return this->qualifier.flags.i != 0;
  44. }
  45.  
  46. bool ast_type_qualifier::has_interpolation() const
  47. {
  48.    return this->flags.q.smooth
  49.           || this->flags.q.flat
  50.           || this->flags.q.noperspective;
  51. }
  52.  
  53. bool
  54. ast_type_qualifier::has_layout() const
  55. {
  56.    return this->flags.q.origin_upper_left
  57.           || this->flags.q.pixel_center_integer
  58.           || this->flags.q.depth_any
  59.           || this->flags.q.depth_greater
  60.           || this->flags.q.depth_less
  61.           || this->flags.q.depth_unchanged
  62.           || this->flags.q.std140
  63.           || this->flags.q.shared
  64.           || this->flags.q.column_major
  65.           || this->flags.q.row_major
  66.           || this->flags.q.packed
  67.           || this->flags.q.explicit_location
  68.           || this->flags.q.explicit_index
  69.           || this->flags.q.explicit_binding
  70.           || this->flags.q.explicit_offset;
  71. }
  72.  
  73. bool
  74. ast_type_qualifier::has_storage() const
  75. {
  76.    return this->flags.q.constant
  77.           || this->flags.q.attribute
  78.           || this->flags.q.varying
  79.           || this->flags.q.in
  80.           || this->flags.q.out
  81.           || this->flags.q.uniform;
  82. }
  83.  
  84. bool
  85. ast_type_qualifier::has_auxiliary_storage() const
  86. {
  87.    return this->flags.q.centroid
  88.           || this->flags.q.sample;
  89. }
  90.  
  91. const char*
  92. ast_type_qualifier::interpolation_string() const
  93. {
  94.    if (this->flags.q.smooth)
  95.       return "smooth";
  96.    else if (this->flags.q.flat)
  97.       return "flat";
  98.    else if (this->flags.q.noperspective)
  99.       return "noperspective";
  100.    else
  101.       return NULL;
  102. }
  103.  
  104. bool
  105. ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
  106.                                     _mesa_glsl_parse_state *state,
  107.                                     ast_type_qualifier q)
  108. {
  109.    ast_type_qualifier ubo_mat_mask;
  110.    ubo_mat_mask.flags.i = 0;
  111.    ubo_mat_mask.flags.q.row_major = 1;
  112.    ubo_mat_mask.flags.q.column_major = 1;
  113.  
  114.    ast_type_qualifier ubo_layout_mask;
  115.    ubo_layout_mask.flags.i = 0;
  116.    ubo_layout_mask.flags.q.std140 = 1;
  117.    ubo_layout_mask.flags.q.packed = 1;
  118.    ubo_layout_mask.flags.q.shared = 1;
  119.  
  120.    ast_type_qualifier ubo_binding_mask;
  121.    ubo_binding_mask.flags.i = 0;
  122.    ubo_binding_mask.flags.q.explicit_binding = 1;
  123.    ubo_binding_mask.flags.q.explicit_offset = 1;
  124.  
  125.    ast_type_qualifier stream_layout_mask;
  126.    stream_layout_mask.flags.i = 0;
  127.    stream_layout_mask.flags.q.stream = 1;
  128.  
  129.    /* Uniform block layout qualifiers get to overwrite each
  130.     * other (rightmost having priority), while all other
  131.     * qualifiers currently don't allow duplicates.
  132.     */
  133.    ast_type_qualifier allowed_duplicates_mask;
  134.    allowed_duplicates_mask.flags.i =
  135.       ubo_mat_mask.flags.i |
  136.       ubo_layout_mask.flags.i |
  137.       ubo_binding_mask.flags.i;
  138.  
  139.    /* Geometry shaders can have several layout qualifiers
  140.     * assigning different stream values.
  141.     */
  142.    if (state->stage == MESA_SHADER_GEOMETRY)
  143.       allowed_duplicates_mask.flags.i |=
  144.          stream_layout_mask.flags.i;
  145.  
  146.    if ((this->flags.i & q.flags.i & ~allowed_duplicates_mask.flags.i) != 0) {
  147.       _mesa_glsl_error(loc, state,
  148.                        "duplicate layout qualifiers used");
  149.       return false;
  150.    }
  151.  
  152.    if (q.flags.q.prim_type) {
  153.       if (this->flags.q.prim_type && this->prim_type != q.prim_type) {
  154.          _mesa_glsl_error(loc, state,
  155.                           "conflicting primitive type qualifiers used");
  156.          return false;
  157.       }
  158.       this->prim_type = q.prim_type;
  159.    }
  160.  
  161.    if (q.flags.q.max_vertices) {
  162.       if (this->flags.q.max_vertices && this->max_vertices != q.max_vertices) {
  163.          _mesa_glsl_error(loc, state,
  164.                           "geometry shader set conflicting max_vertices "
  165.                           "(%d and %d)", this->max_vertices, q.max_vertices);
  166.          return false;
  167.       }
  168.       this->max_vertices = q.max_vertices;
  169.    }
  170.  
  171.    if (q.flags.q.invocations) {
  172.       if (this->flags.q.invocations && this->invocations != q.invocations) {
  173.          _mesa_glsl_error(loc, state,
  174.                           "geometry shader set conflicting invocations "
  175.                           "(%d and %d)", this->invocations, q.invocations);
  176.          return false;
  177.       }
  178.       this->invocations = q.invocations;
  179.    }
  180.  
  181.    if (state->stage == MESA_SHADER_GEOMETRY &&
  182.        state->has_explicit_attrib_stream()) {
  183.       if (q.flags.q.stream && q.stream >= state->ctx->Const.MaxVertexStreams) {
  184.          _mesa_glsl_error(loc, state,
  185.                           "`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
  186.                           "(%d > %d)",
  187.                           q.stream, state->ctx->Const.MaxVertexStreams - 1);
  188.       }
  189.       if (this->flags.q.explicit_stream &&
  190.           this->stream >= state->ctx->Const.MaxVertexStreams) {
  191.          _mesa_glsl_error(loc, state,
  192.                           "`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
  193.                           "(%d > %d)",
  194.                           this->stream, state->ctx->Const.MaxVertexStreams - 1);
  195.       }
  196.  
  197.       if (!this->flags.q.explicit_stream) {
  198.          if (q.flags.q.stream) {
  199.             this->flags.q.stream = 1;
  200.             this->stream = q.stream;
  201.          } else if (!this->flags.q.stream && this->flags.q.out) {
  202.             /* Assign default global stream value */
  203.             this->flags.q.stream = 1;
  204.             this->stream = state->out_qualifier->stream;
  205.          }
  206.       } else {
  207.          if (q.flags.q.explicit_stream) {
  208.             _mesa_glsl_error(loc, state,
  209.                              "duplicate layout `stream' qualifier");
  210.          }
  211.       }
  212.    }
  213.  
  214.    if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
  215.       this->flags.i &= ~ubo_mat_mask.flags.i;
  216.    if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
  217.       this->flags.i &= ~ubo_layout_mask.flags.i;
  218.  
  219.    for (int i = 0; i < 3; i++) {
  220.       if (q.flags.q.local_size & (1 << i)) {
  221.          if ((this->flags.q.local_size & (1 << i)) &&
  222.              this->local_size[i] != q.local_size[i]) {
  223.             _mesa_glsl_error(loc, state,
  224.                              "compute shader set conflicting values for "
  225.                              "local_size_%c (%d and %d)", 'x' + i,
  226.                              this->local_size[i], q.local_size[i]);
  227.             return false;
  228.          }
  229.          this->local_size[i] = q.local_size[i];
  230.       }
  231.    }
  232.  
  233.    this->flags.i |= q.flags.i;
  234.  
  235.    if (q.flags.q.explicit_location)
  236.       this->location = q.location;
  237.  
  238.    if (q.flags.q.explicit_index)
  239.       this->index = q.index;
  240.  
  241.    if (q.flags.q.explicit_binding)
  242.       this->binding = q.binding;
  243.  
  244.    if (q.flags.q.explicit_offset)
  245.       this->offset = q.offset;
  246.  
  247.    if (q.precision != ast_precision_none)
  248.       this->precision = q.precision;
  249.  
  250.    if (q.flags.q.explicit_image_format) {
  251.       this->image_format = q.image_format;
  252.       this->image_base_type = q.image_base_type;
  253.    }
  254.  
  255.    return true;
  256. }
  257.  
  258. bool
  259. ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
  260.                                        _mesa_glsl_parse_state *state,
  261.                                        ast_type_qualifier q,
  262.                                        ast_node* &node)
  263. {
  264.    void *mem_ctx = state;
  265.    bool create_gs_ast = false;
  266.    bool create_cs_ast = false;
  267.    ast_type_qualifier valid_in_mask;
  268.    valid_in_mask.flags.i = 0;
  269.  
  270.    switch (state->stage) {
  271.    case MESA_SHADER_GEOMETRY:
  272.       if (q.flags.q.prim_type) {
  273.          /* Make sure this is a valid input primitive type. */
  274.          switch (q.prim_type) {
  275.          case GL_POINTS:
  276.          case GL_LINES:
  277.          case GL_LINES_ADJACENCY:
  278.          case GL_TRIANGLES:
  279.          case GL_TRIANGLES_ADJACENCY:
  280.             break;
  281.          default:
  282.             _mesa_glsl_error(loc, state,
  283.                              "invalid geometry shader input primitive type");
  284.             break;
  285.          }
  286.       }
  287.  
  288.       create_gs_ast |=
  289.          q.flags.q.prim_type &&
  290.          !state->in_qualifier->flags.q.prim_type;
  291.  
  292.       valid_in_mask.flags.q.prim_type = 1;
  293.       valid_in_mask.flags.q.invocations = 1;
  294.       break;
  295.    case MESA_SHADER_FRAGMENT:
  296.       valid_in_mask.flags.q.early_fragment_tests = 1;
  297.       break;
  298.    case MESA_SHADER_COMPUTE:
  299.       create_cs_ast |=
  300.          q.flags.q.local_size != 0 &&
  301.          state->in_qualifier->flags.q.local_size == 0;
  302.  
  303.       valid_in_mask.flags.q.local_size = 7;
  304.       break;
  305.    default:
  306.       _mesa_glsl_error(loc, state,
  307.                        "input layout qualifiers only valid in "
  308.                        "geometry, fragment and compute shaders");
  309.       break;
  310.    }
  311.  
  312.    /* Generate an error when invalid input layout qualifiers are used. */
  313.    if ((q.flags.i & ~valid_in_mask.flags.i) != 0) {
  314.       _mesa_glsl_error(loc, state,
  315.                        "invalid input layout qualifiers used");
  316.       return false;
  317.    }
  318.  
  319.    /* Input layout qualifiers can be specified multiple
  320.     * times in separate declarations, as long as they match.
  321.     */
  322.    if (this->flags.q.prim_type) {
  323.       if (q.flags.q.prim_type &&
  324.           this->prim_type != q.prim_type) {
  325.          _mesa_glsl_error(loc, state,
  326.                           "conflicting input primitive types specified");
  327.       }
  328.    } else if (q.flags.q.prim_type) {
  329.       state->in_qualifier->flags.q.prim_type = 1;
  330.       state->in_qualifier->prim_type = q.prim_type;
  331.    }
  332.  
  333.    if (this->flags.q.invocations &&
  334.        q.flags.q.invocations &&
  335.        this->invocations != q.invocations) {
  336.       _mesa_glsl_error(loc, state,
  337.                        "conflicting invocations counts specified");
  338.       return false;
  339.    } else if (q.flags.q.invocations) {
  340.       this->flags.q.invocations = 1;
  341.       this->invocations = q.invocations;
  342.    }
  343.  
  344.    if (q.flags.q.early_fragment_tests) {
  345.       state->fs_early_fragment_tests = true;
  346.    }
  347.  
  348.    if (create_gs_ast) {
  349.       node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type);
  350.    } else if (create_cs_ast) {
  351.       /* Infer a local_size of 1 for every unspecified dimension */
  352.       unsigned local_size[3];
  353.       for (int i = 0; i < 3; i++) {
  354.          if (q.flags.q.local_size & (1 << i))
  355.             local_size[i] = q.local_size[i];
  356.          else
  357.             local_size[i] = 1;
  358.       }
  359.       node = new(mem_ctx) ast_cs_input_layout(*loc, local_size);
  360.    }
  361.  
  362.    return true;
  363. }
  364.