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 #pragma once
25 #ifndef GLSL_LINK_VARYINGS_H
26 #define GLSL_LINK_VARYINGS_H
27 
28 /**
29  * \file link_varyings.h
30  *
31  * Linker functions related specifically to linking varyings between shader
32  * stages.
33  */
34 
35 
36 #include "main/glheader.h"
37 
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 (counted
81     * in multiples of the size of a float).
82     */
83    unsigned offset;
84 };
85 
86 
87 /**
88  * Data structure tracking information about a transform feedback declaration
89  * during linking.
90  */
91 class tfeedback_decl
92 {
93 public:
94    void init(struct gl_context *ctx, const void *mem_ctx, const char *input);
95    static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y);
96    bool assign_location(struct gl_context *ctx,
97                         struct gl_shader_program *prog);
98    unsigned get_num_outputs() const;
99    bool store(struct gl_context *ctx, struct gl_shader_program *prog,
100               struct gl_transform_feedback_info *info, unsigned buffer,
101               unsigned buffer_index, const unsigned max_outputs,
102               bool *explicit_stride, bool has_xfb_qualifiers) const;
103    const tfeedback_candidate *find_candidate(gl_shader_program *prog,
104                                              hash_table *tfeedback_candidates);
105 
is_next_buffer_separator()106    bool is_next_buffer_separator() const
107    {
108       return this->next_buffer_separator;
109    }
110 
is_varying_written()111    bool is_varying_written() const
112    {
113       if (this->next_buffer_separator || this->skip_components)
114          return false;
115 
116       return this->matched_candidate->toplevel_var->data.assigned;
117    }
118 
is_varying()119    bool is_varying() const
120    {
121       return !this->next_buffer_separator && !this->skip_components;
122    }
123 
name()124    const char *name() const
125    {
126       return this->orig_name;
127    }
128 
get_stream_id()129    unsigned get_stream_id() const
130    {
131       return this->stream_id;
132    }
133 
get_buffer()134    unsigned get_buffer() const
135    {
136       return this->buffer;
137    }
138 
get_offset()139    unsigned get_offset() const
140    {
141       return this->offset;
142    }
143 
144    /**
145     * The total number of varying components taken up by this variable.  Only
146     * valid if assign_location() has been called.
147     */
num_components()148    unsigned num_components() const
149    {
150       if (this->lowered_builtin_array_variable)
151          return this->size;
152       else
153          return this->vector_elements * this->matrix_columns * this->size *
154             (this->is_64bit() ? 2 : 1);
155    }
156 
get_location()157    unsigned get_location() const {
158       return this->location;
159    }
160 
161 private:
162 
is_64bit()163    bool is_64bit() const
164    {
165       switch (this->type) {
166       case GL_DOUBLE:
167       case GL_DOUBLE_VEC2:
168       case GL_DOUBLE_VEC3:
169       case GL_DOUBLE_VEC4:
170       case GL_DOUBLE_MAT2:
171       case GL_DOUBLE_MAT2x3:
172       case GL_DOUBLE_MAT2x4:
173       case GL_DOUBLE_MAT3:
174       case GL_DOUBLE_MAT3x2:
175       case GL_DOUBLE_MAT3x4:
176       case GL_DOUBLE_MAT4:
177       case GL_DOUBLE_MAT4x2:
178       case GL_DOUBLE_MAT4x3:
179          return true;
180       default:
181          return false;
182       }
183    }
184 
185    /**
186     * The name that was supplied to glTransformFeedbackVaryings.  Used for
187     * error reporting and glGetTransformFeedbackVarying().
188     */
189    const char *orig_name;
190 
191    /**
192     * The name of the variable, parsed from orig_name.
193     */
194    const char *var_name;
195 
196    /**
197     * True if the declaration in orig_name represents an array.
198     */
199    bool is_subscripted;
200 
201    /**
202     * If is_subscripted is true, the subscript that was specified in orig_name.
203     */
204    unsigned array_subscript;
205 
206    /**
207     * Non-zero if the variable is gl_ClipDistance, glTessLevelOuter or
208     * gl_TessLevelInner and the driver lowers it to gl_*MESA.
209     */
210    enum {
211       none,
212       clip_distance,
213       cull_distance,
214       tess_level_outer,
215       tess_level_inner,
216    } lowered_builtin_array_variable;
217 
218    /**
219     * The vertex shader output location that the linker assigned for this
220     * variable.  -1 if a location hasn't been assigned yet.
221     */
222    int location;
223 
224    /**
225     * Used to store the buffer assigned by xfb_buffer.
226     */
227    unsigned buffer;
228 
229    /**
230     * Used to store the offset assigned by xfb_offset.
231     */
232    unsigned offset;
233 
234    /**
235     * If non-zero, then this variable may be packed along with other variables
236     * into a single varying slot, so this offset should be applied when
237     * accessing components.  For example, an offset of 1 means that the x
238     * component of this variable is actually stored in component y of the
239     * location specified by \c location.
240     *
241     * Only valid if location != -1.
242     */
243    unsigned location_frac;
244 
245    /**
246     * If location != -1, the number of vector elements in this variable, or 1
247     * if this variable is a scalar.
248     */
249    unsigned vector_elements;
250 
251    /**
252     * If location != -1, the number of matrix columns in this variable, or 1
253     * if this variable is not a matrix.
254     */
255    unsigned matrix_columns;
256 
257    /** Type of the varying returned by glGetTransformFeedbackVarying() */
258    GLenum type;
259 
260    /**
261     * If location != -1, the size that should be returned by
262     * glGetTransformFeedbackVarying().
263     */
264    unsigned size;
265 
266    /**
267     * How many components to skip. If non-zero, this is
268     * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3.
269     */
270    unsigned skip_components;
271 
272    /**
273     * Whether this is gl_NextBuffer from ARB_transform_feedback3.
274     */
275    bool next_buffer_separator;
276 
277    /**
278     * If find_candidate() has been called, pointer to the tfeedback_candidate
279     * data structure that was found.  Otherwise NULL.
280     */
281    const tfeedback_candidate *matched_candidate;
282 
283    /**
284     * StreamId assigned to this varying (defaults to 0). Can only be set to
285     * values other than 0 in geometry shaders that use the stream layout
286     * modifier. Accepted values must be in the range [0, MAX_VERTEX_STREAMS-1].
287     */
288    unsigned stream_id;
289 };
290 
291 
292 void
293 cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
294                                  gl_linked_shader *producer,
295                                  gl_linked_shader *consumer);
296 
297 bool
298 parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
299                       const void *mem_ctx, unsigned num_names,
300                       char **varying_names, tfeedback_decl *decls);
301 
302 bool
303 process_xfb_layout_qualifiers(void *mem_ctx, const gl_linked_shader *sh,
304                               unsigned *num_tfeedback_decls,
305                               char ***varying_names);
306 
307 void
308 remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
309                                         gl_linked_shader *sh,
310                                         enum ir_variable_mode mode);
311 
312 bool
313 store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
314                      unsigned num_tfeedback_decls,
315                      tfeedback_decl *tfeedback_decls,
316                      bool has_xfb_qualifiers);
317 
318 bool
319 assign_varying_locations(struct gl_context *ctx,
320 			 void *mem_ctx,
321 			 struct gl_shader_program *prog,
322                          gl_linked_shader *producer,
323                          gl_linked_shader *consumer,
324                          unsigned num_tfeedback_decls,
325                          tfeedback_decl *tfeedback_decls,
326                          const uint64_t reserved_slots);
327 
328 uint64_t
329 reserved_varying_slot(struct gl_linked_shader *stage,
330                       ir_variable_mode io_mode);
331 
332 bool
333 check_against_output_limit(struct gl_context *ctx,
334                            struct gl_shader_program *prog,
335                            gl_linked_shader *producer,
336                            unsigned num_explicit_locations);
337 
338 bool
339 check_against_input_limit(struct gl_context *ctx,
340                           struct gl_shader_program *prog,
341                           gl_linked_shader *consumer,
342                           unsigned num_explicit_locations);
343 
344 #endif /* GLSL_LINK_VARYINGS_H */
345