Merge remote-tracking branch 'public/master' into vulkan
[mesa.git] / src / compiler / glsl / link_varyings.h
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
106 bool is_next_buffer_separator() const
107 {
108 return this->next_buffer_separator;
109 }
110
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
119 bool is_varying() const
120 {
121 return !this->next_buffer_separator && !this->skip_components;
122 }
123
124 const char *name() const
125 {
126 return this->orig_name;
127 }
128
129 unsigned get_stream_id() const
130 {
131 return this->stream_id;
132 }
133
134 unsigned get_buffer() const
135 {
136 return this->buffer;
137 }
138
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 */
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_double() ? 2 : 1);
155 }
156
157 unsigned get_location() const {
158 return this->location;
159 }
160
161 private:
162
163 bool is_double() 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 tess_level_outer,
214 tess_level_inner,
215 } lowered_builtin_array_variable;
216
217 /**
218 * The vertex shader output location that the linker assigned for this
219 * variable. -1 if a location hasn't been assigned yet.
220 */
221 int location;
222
223 /**
224 * Used to store the buffer assigned by xfb_buffer.
225 */
226 unsigned buffer;
227
228 /**
229 * Used to store the offset assigned by xfb_offset.
230 */
231 unsigned offset;
232
233 /**
234 * If non-zero, then this variable may be packed along with other variables
235 * into a single varying slot, so this offset should be applied when
236 * accessing components. For example, an offset of 1 means that the x
237 * component of this variable is actually stored in component y of the
238 * location specified by \c location.
239 *
240 * Only valid if location != -1.
241 */
242 unsigned location_frac;
243
244 /**
245 * If location != -1, the number of vector elements in this variable, or 1
246 * if this variable is a scalar.
247 */
248 unsigned vector_elements;
249
250 /**
251 * If location != -1, the number of matrix columns in this variable, or 1
252 * if this variable is not a matrix.
253 */
254 unsigned matrix_columns;
255
256 /** Type of the varying returned by glGetTransformFeedbackVarying() */
257 GLenum type;
258
259 /**
260 * If location != -1, the size that should be returned by
261 * glGetTransformFeedbackVarying().
262 */
263 unsigned size;
264
265 /**
266 * How many components to skip. If non-zero, this is
267 * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3.
268 */
269 unsigned skip_components;
270
271 /**
272 * Whether this is gl_NextBuffer from ARB_transform_feedback3.
273 */
274 bool next_buffer_separator;
275
276 /**
277 * If find_candidate() has been called, pointer to the tfeedback_candidate
278 * data structure that was found. Otherwise NULL.
279 */
280 const tfeedback_candidate *matched_candidate;
281
282 /**
283 * StreamId assigned to this varying (defaults to 0). Can only be set to
284 * values other than 0 in geometry shaders that use the stream layout
285 * modifier. Accepted values must be in the range [0, MAX_VERTEX_STREAMS-1].
286 */
287 unsigned stream_id;
288 };
289
290
291 void
292 cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
293 gl_shader *producer, gl_shader *consumer);
294
295 bool
296 parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
297 const void *mem_ctx, unsigned num_names,
298 char **varying_names, tfeedback_decl *decls);
299
300 bool
301 process_xfb_layout_qualifiers(void *mem_ctx, const gl_shader *sh,
302 unsigned *num_tfeedback_decls,
303 char ***varying_names);
304
305 void
306 remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
307 gl_shader *sh,
308 enum ir_variable_mode mode);
309
310 bool
311 store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
312 unsigned num_tfeedback_decls,
313 tfeedback_decl *tfeedback_decls,
314 bool has_xfb_qualifiers);
315
316 bool
317 assign_varying_locations(struct gl_context *ctx,
318 void *mem_ctx,
319 struct gl_shader_program *prog,
320 gl_shader *producer, gl_shader *consumer,
321 unsigned num_tfeedback_decls,
322 tfeedback_decl *tfeedback_decls);
323
324 bool
325 check_against_output_limit(struct gl_context *ctx,
326 struct gl_shader_program *prog,
327 gl_shader *producer);
328
329 bool
330 check_against_input_limit(struct gl_context *ctx,
331 struct gl_shader_program *prog,
332 gl_shader *consumer);
333
334 #endif /* GLSL_LINK_VARYINGS_H */