• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2012 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 #ifndef GLSL_LINK_VARYINGS_H
25 #define GLSL_LINK_VARYINGS_H
26 
27 /**
28  * \file link_varyings.h
29  *
30  * Linker functions related specifically to linking varyings between shader
31  * stages.
32  */
33 
34 
35 #include "main/glheader.h"
36 
37 
38 struct gl_shader_program;
39 struct gl_shader;
40 class ir_variable;
41 
42 
43 /**
44  * Data structure describing a varying which is available for use in transform
45  * feedback.
46  *
47  * For example, if the vertex shader contains:
48  *
49  *     struct S {
50  *       vec4 foo;
51  *       float[3] bar;
52  *     };
53  *
54  *     varying S[2] v;
55  *
56  * Then there would be tfeedback_candidate objects corresponding to the
57  * following varyings:
58  *
59  *     v[0].foo
60  *     v[0].bar
61  *     v[1].foo
62  *     v[1].bar
63  */
64 struct tfeedback_candidate
65 {
66    /**
67     * Toplevel variable containing this varying.  In the above example, this
68     * would point to the declaration of the varying v.
69     */
70    ir_variable *toplevel_var;
71 
72    /**
73     * Type of this varying.  In the above example, this would point to the
74     * glsl_type for "vec4" or "float[3]".
75     */
76    const glsl_type *type;
77 
78    /**
79     * Offset within the toplevel variable where this varying occurs (counted
80     * in multiples of the size of a float).
81     */
82    unsigned offset;
83 };
84 
85 
86 /**
87  * Data structure tracking information about a transform feedback declaration
88  * during linking.
89  */
90 class tfeedback_decl
91 {
92 public:
93    void init(struct gl_context *ctx, const void *mem_ctx, const char *input);
94    static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y);
95    bool assign_location(struct gl_context *ctx,
96                         struct gl_shader_program *prog);
97    unsigned get_num_outputs() const;
98    bool store(struct gl_context *ctx, struct gl_shader_program *prog,
99               struct gl_transform_feedback_info *info, unsigned buffer,
100               unsigned buffer_index, const unsigned max_outputs,
101               bool *explicit_stride, bool has_xfb_qualifiers) const;
102    const tfeedback_candidate *find_candidate(gl_shader_program *prog,
103                                              hash_table *tfeedback_candidates);
104 
is_next_buffer_separator()105    bool is_next_buffer_separator() const
106    {
107       return this->next_buffer_separator;
108    }
109 
is_varying_written()110    bool is_varying_written() const
111    {
112       if (this->next_buffer_separator || this->skip_components)
113          return false;
114 
115       return this->matched_candidate->toplevel_var->data.assigned;
116    }
117 
is_varying()118    bool is_varying() const
119    {
120       return !this->next_buffer_separator && !this->skip_components;
121    }
122 
name()123    const char *name() const
124    {
125       return this->orig_name;
126    }
127 
get_stream_id()128    unsigned get_stream_id() const
129    {
130       return this->stream_id;
131    }
132 
get_buffer()133    unsigned get_buffer() const
134    {
135       return this->buffer;
136    }
137 
get_offset()138    unsigned get_offset() const
139    {
140       return this->offset;
141    }
142 
143    /**
144     * The total number of varying components taken up by this variable.  Only
145     * valid if assign_location() has been called.
146     */
num_components()147    unsigned num_components() const
148    {
149       if (this->lowered_builtin_array_variable)
150          return this->size;
151       else
152          return this->vector_elements * this->matrix_columns * this->size *
153             (this->is_64bit() ? 2 : 1);
154    }
155 
get_location()156    unsigned get_location() const {
157       return this->location;
158    }
159 
160 private:
161 
is_64bit()162    bool is_64bit() const
163    {
164       switch (this->type) {
165       case GL_DOUBLE:
166       case GL_DOUBLE_VEC2:
167       case GL_DOUBLE_VEC3:
168       case GL_DOUBLE_VEC4:
169       case GL_DOUBLE_MAT2:
170       case GL_DOUBLE_MAT2x3:
171       case GL_DOUBLE_MAT2x4:
172       case GL_DOUBLE_MAT3:
173       case GL_DOUBLE_MAT3x2:
174       case GL_DOUBLE_MAT3x4:
175       case GL_DOUBLE_MAT4:
176       case GL_DOUBLE_MAT4x2:
177       case GL_DOUBLE_MAT4x3:
178       case GL_INT64_ARB:
179       case GL_INT64_VEC2_ARB:
180       case GL_INT64_VEC3_ARB:
181       case GL_INT64_VEC4_ARB:
182       case GL_UNSIGNED_INT64_ARB:
183       case GL_UNSIGNED_INT64_VEC2_ARB:
184       case GL_UNSIGNED_INT64_VEC3_ARB:
185       case GL_UNSIGNED_INT64_VEC4_ARB:
186          return true;
187       default:
188          return false;
189       }
190    }
191 
192    /**
193     * The name that was supplied to glTransformFeedbackVaryings.  Used for
194     * error reporting and glGetTransformFeedbackVarying().
195     */
196    const char *orig_name;
197 
198    /**
199     * The name of the variable, parsed from orig_name.
200     */
201    const char *var_name;
202 
203    /**
204     * True if the declaration in orig_name represents an array.
205     */
206    bool is_subscripted;
207 
208    /**
209     * If is_subscripted is true, the subscript that was specified in orig_name.
210     */
211    unsigned array_subscript;
212 
213    /**
214     * Non-zero if the variable is gl_ClipDistance, glTessLevelOuter or
215     * gl_TessLevelInner and the driver lowers it to gl_*MESA.
216     */
217    enum {
218       none,
219       clip_distance,
220       cull_distance,
221       tess_level_outer,
222       tess_level_inner,
223    } lowered_builtin_array_variable;
224 
225    /**
226     * The vertex shader output location that the linker assigned for this
227     * variable.  -1 if a location hasn't been assigned yet.
228     */
229    int location;
230 
231    /**
232     * Used to store the buffer assigned by xfb_buffer.
233     */
234    unsigned buffer;
235 
236    /**
237     * Used to store the offset assigned by xfb_offset.
238     */
239    unsigned offset;
240 
241    /**
242     * If non-zero, then this variable may be packed along with other variables
243     * into a single varying slot, so this offset should be applied when
244     * accessing components.  For example, an offset of 1 means that the x
245     * component of this variable is actually stored in component y of the
246     * location specified by \c location.
247     *
248     * Only valid if location != -1.
249     */
250    unsigned location_frac;
251 
252    /**
253     * If location != -1, the number of vector elements in this variable, or 1
254     * if this variable is a scalar.
255     */
256    unsigned vector_elements;
257 
258    /**
259     * If location != -1, the number of matrix columns in this variable, or 1
260     * if this variable is not a matrix.
261     */
262    unsigned matrix_columns;
263 
264    /** Type of the varying returned by glGetTransformFeedbackVarying() */
265    GLenum type;
266 
267    /**
268     * If location != -1, the size that should be returned by
269     * glGetTransformFeedbackVarying().
270     */
271    unsigned size;
272 
273    /**
274     * How many components to skip. If non-zero, this is
275     * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3.
276     */
277    unsigned skip_components;
278 
279    /**
280     * Whether this is gl_NextBuffer from ARB_transform_feedback3.
281     */
282    bool next_buffer_separator;
283 
284    /**
285     * If find_candidate() has been called, pointer to the tfeedback_candidate
286     * data structure that was found.  Otherwise NULL.
287     */
288    const tfeedback_candidate *matched_candidate;
289 
290    /**
291     * StreamId assigned to this varying (defaults to 0). Can only be set to
292     * values other than 0 in geometry shaders that use the stream layout
293     * modifier. Accepted values must be in the range [0, MAX_VERTEX_STREAMS-1].
294     */
295    unsigned stream_id;
296 };
297 
298 bool
299 link_varyings(struct gl_shader_program *prog, unsigned first, unsigned last,
300               struct gl_context *ctx, void *mem_ctx);
301 
302 void
303 validate_sso_explicit_locations(struct gl_context *ctx,
304                                 struct gl_shader_program *prog,
305                                 gl_shader_stage first,
306                                 gl_shader_stage last);
307 
308 void
309 cross_validate_outputs_to_inputs(struct gl_context *ctx,
310                                  struct gl_shader_program *prog,
311                                  gl_linked_shader *producer,
312                                  gl_linked_shader *consumer);
313 
314 #endif /* GLSL_LINK_VARYINGS_H */
315