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