| /* |
| * Copyright © 2012 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #pragma once |
| #ifndef GLSL_LINK_VARYINGS_H |
| #define GLSL_LINK_VARYINGS_H |
| |
| /** |
| * \file link_varyings.h |
| * |
| * Linker functions related specifically to linking varyings between shader |
| * stages. |
| */ |
| |
| |
| #include "main/glheader.h" |
| |
| |
| struct gl_shader_program; |
| struct gl_shader; |
| class ir_variable; |
| |
| |
| /** |
| * Data structure describing a varying which is available for use in transform |
| * feedback. |
| * |
| * For example, if the vertex shader contains: |
| * |
| * struct S { |
| * vec4 foo; |
| * float[3] bar; |
| * }; |
| * |
| * varying S[2] v; |
| * |
| * Then there would be tfeedback_candidate objects corresponding to the |
| * following varyings: |
| * |
| * v[0].foo |
| * v[0].bar |
| * v[1].foo |
| * v[1].bar |
| */ |
| struct tfeedback_candidate |
| { |
| /** |
| * Toplevel variable containing this varying. In the above example, this |
| * would point to the declaration of the varying v. |
| */ |
| ir_variable *toplevel_var; |
| |
| /** |
| * Type of this varying. In the above example, this would point to the |
| * glsl_type for "vec4" or "float[3]". |
| */ |
| const glsl_type *type; |
| |
| /** |
| * Offset within the toplevel variable where this varying occurs (counted |
| * in multiples of the size of a float). |
| */ |
| unsigned offset; |
| }; |
| |
| |
| /** |
| * Data structure tracking information about a transform feedback declaration |
| * during linking. |
| */ |
| class tfeedback_decl |
| { |
| public: |
| void init(struct gl_context *ctx, const void *mem_ctx, const char *input); |
| static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y); |
| bool assign_location(struct gl_context *ctx, |
| struct gl_shader_program *prog); |
| unsigned get_num_outputs() const; |
| bool store(struct gl_context *ctx, struct gl_shader_program *prog, |
| struct gl_transform_feedback_info *info, unsigned buffer, |
| const unsigned max_outputs) const; |
| const tfeedback_candidate *find_candidate(gl_shader_program *prog, |
| hash_table *tfeedback_candidates); |
| |
| bool is_next_buffer_separator() const |
| { |
| return this->next_buffer_separator; |
| } |
| |
| bool is_varying() const |
| { |
| return !this->next_buffer_separator && !this->skip_components; |
| } |
| |
| const char *name() const |
| { |
| return this->orig_name; |
| } |
| |
| unsigned get_stream_id() const |
| { |
| return this->stream_id; |
| } |
| |
| /** |
| * The total number of varying components taken up by this variable. Only |
| * valid if assign_location() has been called. |
| */ |
| unsigned num_components() const |
| { |
| if (this->lowered_builtin_array_variable) |
| return this->size; |
| else |
| return this->vector_elements * this->matrix_columns * this->size * |
| (this->is_double() ? 2 : 1); |
| } |
| |
| unsigned get_location() const { |
| return this->location; |
| } |
| |
| private: |
| |
| bool is_double() const |
| { |
| switch (this->type) { |
| case GL_DOUBLE: |
| case GL_DOUBLE_VEC2: |
| case GL_DOUBLE_VEC3: |
| case GL_DOUBLE_VEC4: |
| case GL_DOUBLE_MAT2: |
| case GL_DOUBLE_MAT2x3: |
| case GL_DOUBLE_MAT2x4: |
| case GL_DOUBLE_MAT3: |
| case GL_DOUBLE_MAT3x2: |
| case GL_DOUBLE_MAT3x4: |
| case GL_DOUBLE_MAT4: |
| case GL_DOUBLE_MAT4x2: |
| case GL_DOUBLE_MAT4x3: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| /** |
| * The name that was supplied to glTransformFeedbackVaryings. Used for |
| * error reporting and glGetTransformFeedbackVarying(). |
| */ |
| const char *orig_name; |
| |
| /** |
| * The name of the variable, parsed from orig_name. |
| */ |
| const char *var_name; |
| |
| /** |
| * True if the declaration in orig_name represents an array. |
| */ |
| bool is_subscripted; |
| |
| /** |
| * If is_subscripted is true, the subscript that was specified in orig_name. |
| */ |
| unsigned array_subscript; |
| |
| /** |
| * Non-zero if the variable is gl_ClipDistance, glTessLevelOuter or |
| * gl_TessLevelInner and the driver lowers it to gl_*MESA. |
| */ |
| enum { |
| none, |
| clip_distance, |
| tess_level_outer, |
| tess_level_inner, |
| } lowered_builtin_array_variable; |
| |
| /** |
| * The vertex shader output location that the linker assigned for this |
| * variable. -1 if a location hasn't been assigned yet. |
| */ |
| int location; |
| |
| /** |
| * If non-zero, then this variable may be packed along with other variables |
| * into a single varying slot, so this offset should be applied when |
| * accessing components. For example, an offset of 1 means that the x |
| * component of this variable is actually stored in component y of the |
| * location specified by \c location. |
| * |
| * Only valid if location != -1. |
| */ |
| unsigned location_frac; |
| |
| /** |
| * If location != -1, the number of vector elements in this variable, or 1 |
| * if this variable is a scalar. |
| */ |
| unsigned vector_elements; |
| |
| /** |
| * If location != -1, the number of matrix columns in this variable, or 1 |
| * if this variable is not a matrix. |
| */ |
| unsigned matrix_columns; |
| |
| /** Type of the varying returned by glGetTransformFeedbackVarying() */ |
| GLenum type; |
| |
| /** |
| * If location != -1, the size that should be returned by |
| * glGetTransformFeedbackVarying(). |
| */ |
| unsigned size; |
| |
| /** |
| * How many components to skip. If non-zero, this is |
| * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3. |
| */ |
| unsigned skip_components; |
| |
| /** |
| * Whether this is gl_NextBuffer from ARB_transform_feedback3. |
| */ |
| bool next_buffer_separator; |
| |
| /** |
| * If find_candidate() has been called, pointer to the tfeedback_candidate |
| * data structure that was found. Otherwise NULL. |
| */ |
| const tfeedback_candidate *matched_candidate; |
| |
| /** |
| * StreamId assigned to this varying (defaults to 0). Can only be set to |
| * values other than 0 in geometry shaders that use the stream layout |
| * modifier. Accepted values must be in the range [0, MAX_VERTEX_STREAMS-1]. |
| */ |
| unsigned stream_id; |
| }; |
| |
| |
| void |
| cross_validate_outputs_to_inputs(struct gl_shader_program *prog, |
| gl_shader *producer, gl_shader *consumer); |
| |
| bool |
| parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, |
| const void *mem_ctx, unsigned num_names, |
| char **varying_names, tfeedback_decl *decls); |
| |
| void |
| remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object, |
| gl_shader *sh, |
| enum ir_variable_mode mode); |
| |
| bool |
| store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, |
| unsigned num_tfeedback_decls, |
| tfeedback_decl *tfeedback_decls); |
| |
| bool |
| assign_varying_locations(struct gl_context *ctx, |
| void *mem_ctx, |
| struct gl_shader_program *prog, |
| gl_shader *producer, gl_shader *consumer, |
| unsigned num_tfeedback_decls, |
| tfeedback_decl *tfeedback_decls); |
| |
| bool |
| check_against_output_limit(struct gl_context *ctx, |
| struct gl_shader_program *prog, |
| gl_shader *producer); |
| |
| bool |
| check_against_input_limit(struct gl_context *ctx, |
| struct gl_shader_program *prog, |
| gl_shader *consumer); |
| |
| #endif /* GLSL_LINK_VARYINGS_H */ |