1 /*
2 * Copyright © 2011 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 /**
25 * \file shader_query.cpp
26 * C-to-C++ bridge functions to query GLSL shader data
27 *
28 * \author Ian Romanick <ian.d.romanick@intel.com>
29 */
30
31 #include "main/context.h"
32 #include "main/enums.h"
33 #include "main/shaderapi.h"
34 #include "main/shaderobj.h"
35 #include "main/uniforms.h"
36 #include "compiler/glsl/glsl_symbol_table.h"
37 #include "compiler/glsl/ir.h"
38 #include "compiler/glsl/linker_util.h"
39 #include "compiler/glsl/string_to_uint_map.h"
40 #include "util/mesa-sha1.h"
41 #include "c99_alloca.h"
42 #include "api_exec_decl.h"
43
44 static GLint
45 program_resource_location(struct gl_program_resource *res,
46 unsigned array_index);
47
48 /**
49 * Declare convenience functions to return resource data in a given type.
50 * Warning! this is not type safe so be *very* careful when using these.
51 */
52 #define DECL_RESOURCE_FUNC(name, type) \
53 const type * RESOURCE_ ## name (gl_program_resource *res) { \
54 assert(res->Data); \
55 return (type *) res->Data; \
56 }
57
58 DECL_RESOURCE_FUNC(VAR, gl_shader_variable);
59 DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
60 DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
61 DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
62 DECL_RESOURCE_FUNC(XFV, gl_transform_feedback_varying_info);
63 DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_buffer);
64 DECL_RESOURCE_FUNC(SUB, gl_subroutine_function);
65
66 static GLenum
mediump_to_highp_type(GLenum type)67 mediump_to_highp_type(GLenum type)
68 {
69 switch (type) {
70 case GL_FLOAT16_NV:
71 return GL_FLOAT;
72 case GL_FLOAT16_VEC2_NV:
73 return GL_FLOAT_VEC2;
74 case GL_FLOAT16_VEC3_NV:
75 return GL_FLOAT_VEC3;
76 case GL_FLOAT16_VEC4_NV:
77 return GL_FLOAT_VEC4;
78 case GL_FLOAT16_MAT2_AMD:
79 return GL_FLOAT_MAT2;
80 case GL_FLOAT16_MAT3_AMD:
81 return GL_FLOAT_MAT3;
82 case GL_FLOAT16_MAT4_AMD:
83 return GL_FLOAT_MAT4;
84 case GL_FLOAT16_MAT2x3_AMD:
85 return GL_FLOAT_MAT2x3;
86 case GL_FLOAT16_MAT2x4_AMD:
87 return GL_FLOAT_MAT2x4;
88 case GL_FLOAT16_MAT3x2_AMD:
89 return GL_FLOAT_MAT3x2;
90 case GL_FLOAT16_MAT3x4_AMD:
91 return GL_FLOAT_MAT3x4;
92 case GL_FLOAT16_MAT4x2_AMD:
93 return GL_FLOAT_MAT4x2;
94 case GL_FLOAT16_MAT4x3_AMD:
95 return GL_FLOAT_MAT4x3;
96 default:
97 return type;
98 }
99 }
100
101 static void
bind_attrib_location(struct gl_context * ctx,struct gl_shader_program * const shProg,GLuint index,const GLchar * name,bool no_error)102 bind_attrib_location(struct gl_context *ctx,
103 struct gl_shader_program *const shProg, GLuint index,
104 const GLchar *name, bool no_error)
105 {
106 if (!name)
107 return;
108
109 if (!no_error) {
110 if (strncmp(name, "gl_", 3) == 0) {
111 _mesa_error(ctx, GL_INVALID_OPERATION,
112 "glBindAttribLocation(illegal name)");
113 return;
114 }
115
116 if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
117 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(%u >= %u)",
118 index, ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs);
119 return;
120 }
121 }
122
123 /* Replace the current value if it's already in the list. Add
124 * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
125 * between built-in attributes and user-defined attributes.
126 */
127 shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
128
129 /*
130 * Note that this attribute binding won't go into effect until
131 * glLinkProgram is called again.
132 */
133 }
134
135 void GLAPIENTRY
_mesa_BindAttribLocation_no_error(GLuint program,GLuint index,const GLchar * name)136 _mesa_BindAttribLocation_no_error(GLuint program, GLuint index,
137 const GLchar *name)
138 {
139 GET_CURRENT_CONTEXT(ctx);
140
141 struct gl_shader_program *const shProg =
142 _mesa_lookup_shader_program(ctx, program);
143 bind_attrib_location(ctx, shProg, index, name, true);
144 }
145
146 void GLAPIENTRY
_mesa_BindAttribLocation(GLuint program,GLuint index,const GLchar * name)147 _mesa_BindAttribLocation(GLuint program, GLuint index,
148 const GLchar *name)
149 {
150 GET_CURRENT_CONTEXT(ctx);
151
152 struct gl_shader_program *const shProg =
153 _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
154 if (!shProg)
155 return;
156
157 bind_attrib_location(ctx, shProg, index, name, false);
158 }
159
160 void GLAPIENTRY
_mesa_GetActiveAttrib(GLuint program,GLuint desired_index,GLsizei maxLength,GLsizei * length,GLint * size,GLenum * type,GLchar * name)161 _mesa_GetActiveAttrib(GLuint program, GLuint desired_index,
162 GLsizei maxLength, GLsizei * length, GLint * size,
163 GLenum * type, GLchar * name)
164 {
165 GET_CURRENT_CONTEXT(ctx);
166 struct gl_shader_program *shProg;
167
168 if (maxLength < 0) {
169 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
170 return;
171 }
172
173 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
174 if (!shProg)
175 return;
176
177 if (!shProg->data->LinkStatus) {
178 _mesa_error(ctx, GL_INVALID_VALUE,
179 "glGetActiveAttrib(program not linked)");
180 return;
181 }
182
183 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
184 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
185 return;
186 }
187
188 struct gl_program_resource *res =
189 _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
190 desired_index);
191
192 /* User asked for index that does not exist. */
193 if (!res) {
194 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
195 return;
196 }
197
198 const gl_shader_variable *const var = RESOURCE_VAR(res);
199
200 const char *var_name = var->name.string;
201
202 _mesa_copy_string(name, maxLength, length, var_name);
203
204 if (size)
205 _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
206 size, false, "glGetActiveAttrib");
207
208 if (type)
209 _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
210 (GLint *) type, false, "glGetActiveAttrib");
211 }
212
213 GLint GLAPIENTRY
_mesa_GetAttribLocation(GLuint program,const GLchar * name)214 _mesa_GetAttribLocation(GLuint program, const GLchar * name)
215 {
216 GET_CURRENT_CONTEXT(ctx);
217 struct gl_shader_program *const shProg =
218 _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
219
220 if (!shProg) {
221 return -1;
222 }
223
224 if (!shProg->data->LinkStatus) {
225 _mesa_error(ctx, GL_INVALID_OPERATION,
226 "glGetAttribLocation(program not linked)");
227 return -1;
228 }
229
230 if (!name)
231 return -1;
232
233 /* Not having a vertex shader is not an error.
234 */
235 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
236 return -1;
237
238 unsigned array_index = 0;
239 struct gl_program_resource *res =
240 _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name,
241 &array_index);
242
243 if (!res)
244 return -1;
245
246 return program_resource_location(res, array_index);
247 }
248
249 unsigned
_mesa_count_active_attribs(struct gl_shader_program * shProg)250 _mesa_count_active_attribs(struct gl_shader_program *shProg)
251 {
252 if (!shProg->data->LinkStatus
253 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
254 return 0;
255 }
256
257 struct gl_program_resource *res = shProg->data->ProgramResourceList;
258 unsigned count = 0;
259 for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
260 j++, res++) {
261 if (res->Type == GL_PROGRAM_INPUT &&
262 res->StageReferences & (1 << MESA_SHADER_VERTEX))
263 count++;
264 }
265 return count;
266 }
267
268
269 size_t
_mesa_longest_attribute_name_length(struct gl_shader_program * shProg)270 _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
271 {
272 if (!shProg->data->LinkStatus
273 || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
274 return 0;
275 }
276
277 struct gl_program_resource *res = shProg->data->ProgramResourceList;
278 size_t longest = 0;
279 for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
280 j++, res++) {
281 if (res->Type == GL_PROGRAM_INPUT &&
282 res->StageReferences & (1 << MESA_SHADER_VERTEX)) {
283
284 /* From the ARB_gl_spirv spec:
285 *
286 * "If pname is ACTIVE_ATTRIBUTE_MAX_LENGTH, the length of the
287 * longest active attribute name, including a null terminator, is
288 * returned. If no active attributes exist, zero is returned. If
289 * no name reflection information is available, one is returned."
290 */
291 const size_t length = RESOURCE_VAR(res)->name.length;
292
293 if (length >= longest)
294 longest = length + 1;
295 }
296 }
297
298 return longest;
299 }
300
301 void static
bind_frag_data_location(struct gl_shader_program * const shProg,const char * name,unsigned colorNumber,unsigned index)302 bind_frag_data_location(struct gl_shader_program *const shProg,
303 const char *name, unsigned colorNumber,
304 unsigned index)
305 {
306 /* Replace the current value if it's already in the list. Add
307 * FRAG_RESULT_DATA0 because that's how the linker differentiates
308 * between built-in attributes and user-defined attributes.
309 */
310 shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
311 shProg->FragDataIndexBindings->put(index, name);
312
313 /*
314 * Note that this binding won't go into effect until
315 * glLinkProgram is called again.
316 */
317 }
318
319 void GLAPIENTRY
_mesa_BindFragDataLocation(GLuint program,GLuint colorNumber,const GLchar * name)320 _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
321 const GLchar *name)
322 {
323 _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
324 }
325
326 void GLAPIENTRY
_mesa_BindFragDataLocation_no_error(GLuint program,GLuint colorNumber,const GLchar * name)327 _mesa_BindFragDataLocation_no_error(GLuint program, GLuint colorNumber,
328 const GLchar *name)
329 {
330 GET_CURRENT_CONTEXT(ctx);
331
332 if (!name)
333 return;
334
335 struct gl_shader_program *const shProg =
336 _mesa_lookup_shader_program(ctx, program);
337
338 bind_frag_data_location(shProg, name, colorNumber, 0);
339 }
340
341 void GLAPIENTRY
_mesa_BindFragDataLocationIndexed(GLuint program,GLuint colorNumber,GLuint index,const GLchar * name)342 _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
343 GLuint index, const GLchar *name)
344 {
345 GET_CURRENT_CONTEXT(ctx);
346
347 struct gl_shader_program *const shProg =
348 _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
349 if (!shProg)
350 return;
351
352 if (!name)
353 return;
354
355 if (strncmp(name, "gl_", 3) == 0) {
356 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
357 return;
358 }
359
360 if (index > 1) {
361 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
362 return;
363 }
364
365 if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
366 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
367 return;
368 }
369
370 if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
371 _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
372 return;
373 }
374
375 bind_frag_data_location(shProg, name, colorNumber, index);
376 }
377
378 void GLAPIENTRY
_mesa_BindFragDataLocationIndexed_no_error(GLuint program,GLuint colorNumber,GLuint index,const GLchar * name)379 _mesa_BindFragDataLocationIndexed_no_error(GLuint program, GLuint colorNumber,
380 GLuint index, const GLchar *name)
381 {
382 GET_CURRENT_CONTEXT(ctx);
383
384 if (!name)
385 return;
386
387 struct gl_shader_program *const shProg =
388 _mesa_lookup_shader_program(ctx, program);
389
390 bind_frag_data_location(shProg, name, colorNumber, index);
391 }
392
393 GLint GLAPIENTRY
_mesa_GetFragDataIndex(GLuint program,const GLchar * name)394 _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
395 {
396 GET_CURRENT_CONTEXT(ctx);
397 struct gl_shader_program *const shProg =
398 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
399
400 if (!shProg) {
401 return -1;
402 }
403
404 if (!shProg->data->LinkStatus) {
405 _mesa_error(ctx, GL_INVALID_OPERATION,
406 "glGetFragDataIndex(program not linked)");
407 return -1;
408 }
409
410 if (!name)
411 return -1;
412
413 /* Not having a fragment shader is not an error.
414 */
415 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
416 return -1;
417
418 return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
419 name);
420 }
421
422 GLint GLAPIENTRY
_mesa_GetFragDataLocation(GLuint program,const GLchar * name)423 _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
424 {
425 GET_CURRENT_CONTEXT(ctx);
426 struct gl_shader_program *const shProg =
427 _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
428
429 if (!shProg) {
430 return -1;
431 }
432
433 if (!shProg->data->LinkStatus) {
434 _mesa_error(ctx, GL_INVALID_OPERATION,
435 "glGetFragDataLocation(program not linked)");
436 return -1;
437 }
438
439 if (!name)
440 return -1;
441
442 /* Not having a fragment shader is not an error.
443 */
444 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
445 return -1;
446
447 unsigned array_index = 0;
448 struct gl_program_resource *res =
449 _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name,
450 &array_index);
451
452 if (!res)
453 return -1;
454
455 return program_resource_location(res, array_index);
456 }
457
458 const char*
_mesa_program_resource_name(struct gl_program_resource * res)459 _mesa_program_resource_name(struct gl_program_resource *res)
460 {
461 switch (res->Type) {
462 case GL_UNIFORM_BLOCK:
463 case GL_SHADER_STORAGE_BLOCK:
464 return RESOURCE_UBO(res)->name.string;
465 case GL_TRANSFORM_FEEDBACK_VARYING:
466 return RESOURCE_XFV(res)->name.string;
467 case GL_PROGRAM_INPUT:
468 case GL_PROGRAM_OUTPUT:
469 return RESOURCE_VAR(res)->name.string;
470 case GL_UNIFORM:
471 case GL_BUFFER_VARIABLE:
472 return RESOURCE_UNI(res)->name.string;
473 case GL_VERTEX_SUBROUTINE_UNIFORM:
474 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
475 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
476 case GL_COMPUTE_SUBROUTINE_UNIFORM:
477 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
478 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
479 return RESOURCE_UNI(res)->name.string + MESA_SUBROUTINE_PREFIX_LEN;
480 case GL_VERTEX_SUBROUTINE:
481 case GL_GEOMETRY_SUBROUTINE:
482 case GL_FRAGMENT_SUBROUTINE:
483 case GL_COMPUTE_SUBROUTINE:
484 case GL_TESS_CONTROL_SUBROUTINE:
485 case GL_TESS_EVALUATION_SUBROUTINE:
486 return RESOURCE_SUB(res)->name.string;
487 default:
488 break;
489 }
490 return NULL;
491 }
492
493 int
_mesa_program_resource_name_length(struct gl_program_resource * res)494 _mesa_program_resource_name_length(struct gl_program_resource *res)
495 {
496 switch (res->Type) {
497 case GL_UNIFORM_BLOCK:
498 case GL_SHADER_STORAGE_BLOCK:
499 return RESOURCE_UBO(res)->name.length;
500 case GL_TRANSFORM_FEEDBACK_VARYING:
501 return RESOURCE_XFV(res)->name.length;
502 case GL_PROGRAM_INPUT:
503 case GL_PROGRAM_OUTPUT:
504 return RESOURCE_VAR(res)->name.length;
505 case GL_UNIFORM:
506 case GL_BUFFER_VARIABLE:
507 return RESOURCE_UNI(res)->name.length;
508 case GL_VERTEX_SUBROUTINE_UNIFORM:
509 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
510 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
511 case GL_COMPUTE_SUBROUTINE_UNIFORM:
512 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
513 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
514 return RESOURCE_UNI(res)->name.length - MESA_SUBROUTINE_PREFIX_LEN;
515 case GL_VERTEX_SUBROUTINE:
516 case GL_GEOMETRY_SUBROUTINE:
517 case GL_FRAGMENT_SUBROUTINE:
518 case GL_COMPUTE_SUBROUTINE:
519 case GL_TESS_CONTROL_SUBROUTINE:
520 case GL_TESS_EVALUATION_SUBROUTINE:
521 return RESOURCE_SUB(res)->name.length;
522 default:
523 break;
524 }
525 return 0;
526 }
527
528 bool
_mesa_program_get_resource_name(struct gl_program_resource * res,struct gl_resource_name * out)529 _mesa_program_get_resource_name(struct gl_program_resource *res,
530 struct gl_resource_name *out)
531 {
532 switch (res->Type) {
533 case GL_UNIFORM_BLOCK:
534 case GL_SHADER_STORAGE_BLOCK:
535 *out = RESOURCE_UBO(res)->name;
536 return out->string != NULL;
537 case GL_TRANSFORM_FEEDBACK_VARYING:
538 *out = RESOURCE_XFV(res)->name;
539 return out->string != NULL;
540 case GL_PROGRAM_INPUT:
541 case GL_PROGRAM_OUTPUT:
542 *out = RESOURCE_VAR(res)->name;
543 return out->string != NULL;
544 case GL_UNIFORM:
545 case GL_BUFFER_VARIABLE:
546 *out = RESOURCE_UNI(res)->name;
547 return out->string != NULL;
548 case GL_VERTEX_SUBROUTINE_UNIFORM:
549 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
550 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
551 case GL_COMPUTE_SUBROUTINE_UNIFORM:
552 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
553 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
554 *out = RESOURCE_UNI(res)->name;
555 out->string += MESA_SUBROUTINE_PREFIX_LEN;
556 out->length -= MESA_SUBROUTINE_PREFIX_LEN;
557 assert(out->string); /* always non-NULL */
558 return true;
559 case GL_VERTEX_SUBROUTINE:
560 case GL_GEOMETRY_SUBROUTINE:
561 case GL_FRAGMENT_SUBROUTINE:
562 case GL_COMPUTE_SUBROUTINE:
563 case GL_TESS_CONTROL_SUBROUTINE:
564 case GL_TESS_EVALUATION_SUBROUTINE:
565 *out = RESOURCE_SUB(res)->name;
566 return out->string != NULL;
567 default:
568 return false;
569 }
570 }
571
572 unsigned
_mesa_program_resource_array_size(struct gl_program_resource * res)573 _mesa_program_resource_array_size(struct gl_program_resource *res)
574 {
575 switch (res->Type) {
576 case GL_TRANSFORM_FEEDBACK_VARYING:
577 return RESOURCE_XFV(res)->Size > 1 ?
578 RESOURCE_XFV(res)->Size : 0;
579 case GL_PROGRAM_INPUT:
580 case GL_PROGRAM_OUTPUT:
581 return RESOURCE_VAR(res)->type->length;
582 case GL_UNIFORM:
583 case GL_VERTEX_SUBROUTINE_UNIFORM:
584 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
585 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
586 case GL_COMPUTE_SUBROUTINE_UNIFORM:
587 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
588 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
589 return RESOURCE_UNI(res)->array_elements;
590 case GL_BUFFER_VARIABLE:
591 /* Unsized arrays */
592 if (RESOURCE_UNI(res)->array_stride > 0 &&
593 RESOURCE_UNI(res)->array_elements == 0)
594 return 1;
595 else
596 return RESOURCE_UNI(res)->array_elements;
597 case GL_VERTEX_SUBROUTINE:
598 case GL_GEOMETRY_SUBROUTINE:
599 case GL_FRAGMENT_SUBROUTINE:
600 case GL_COMPUTE_SUBROUTINE:
601 case GL_TESS_CONTROL_SUBROUTINE:
602 case GL_TESS_EVALUATION_SUBROUTINE:
603 case GL_ATOMIC_COUNTER_BUFFER:
604 case GL_UNIFORM_BLOCK:
605 case GL_SHADER_STORAGE_BLOCK:
606 return 0;
607 default:
608 assert(!"support for resource type not implemented");
609 }
610 return 0;
611 }
612
613 /**
614 * Checks if array subscript is valid and if so sets array_index.
615 */
616 static bool
valid_array_index(const GLchar * name,int len,unsigned * array_index)617 valid_array_index(const GLchar *name, int len, unsigned *array_index)
618 {
619 long idx = 0;
620 const GLchar *out_base_name_end;
621
622 idx = link_util_parse_program_resource_name(name, len, &out_base_name_end);
623 if (idx < 0)
624 return false;
625
626 if (array_index)
627 *array_index = idx;
628
629 return true;
630 }
631
632 static struct gl_program_resource *
search_resource_hash(struct gl_shader_program * shProg,GLenum programInterface,const char * name,int len,unsigned * array_index)633 search_resource_hash(struct gl_shader_program *shProg,
634 GLenum programInterface, const char *name, int len,
635 unsigned *array_index)
636 {
637 unsigned type = GET_PROGRAM_RESOURCE_TYPE_FROM_GLENUM(programInterface);
638 assert(type < ARRAY_SIZE(shProg->data->ProgramResourceHash));
639
640 if (!shProg->data->ProgramResourceHash[type])
641 return NULL;
642
643 const char *base_name_end;
644 long index = link_util_parse_program_resource_name(name, len, &base_name_end);
645 char *name_copy;
646
647 /* If dealing with array, we need to get the basename. */
648 if (index >= 0) {
649 name_copy = (char *) alloca(base_name_end - name + 1);
650 memcpy(name_copy, name, base_name_end - name);
651 name_copy[base_name_end - name] = '\0';
652 len = base_name_end - name;
653 } else {
654 name_copy = (char*) name;
655 }
656
657 uint32_t hash = _mesa_hash_string_with_length(name_copy, len);
658 struct hash_entry *entry =
659 _mesa_hash_table_search_pre_hashed(shProg->data->ProgramResourceHash[type],
660 hash, name_copy);
661 if (!entry)
662 return NULL;
663
664 if (array_index)
665 *array_index = index >= 0 ? index : 0;
666
667 return (struct gl_program_resource *)entry->data;
668 }
669
670 /* Find a program resource with specific name in given interface.
671 */
672 struct gl_program_resource *
_mesa_program_resource_find_name(struct gl_shader_program * shProg,GLenum programInterface,const char * name,unsigned * array_index)673 _mesa_program_resource_find_name(struct gl_shader_program *shProg,
674 GLenum programInterface, const char *name,
675 unsigned *array_index)
676 {
677 if (name == NULL)
678 return NULL;
679
680 int len = strlen(name);
681
682 /* If we have a name, try the ProgramResourceHash first. */
683 struct gl_program_resource *res =
684 search_resource_hash(shProg, programInterface, name, len, array_index);
685
686 if (res)
687 return res;
688
689 res = shProg->data->ProgramResourceList;
690 for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
691 if (res->Type != programInterface)
692 continue;
693
694 struct gl_resource_name rname;
695
696 /* Since ARB_gl_spirv lack of name reflections is a possibility */
697 if (!_mesa_program_get_resource_name(res, &rname))
698 continue;
699
700 bool found = false;
701
702 /* From ARB_program_interface_query spec:
703 *
704 * "uint GetProgramResourceIndex(uint program, enum programInterface,
705 * const char *name);
706 * [...]
707 * If <name> exactly matches the name string of one of the active
708 * resources for <programInterface>, the index of the matched resource is
709 * returned. Additionally, if <name> would exactly match the name string
710 * of an active resource if "[0]" were appended to <name>, the index of
711 * the matched resource is returned. [...]"
712 *
713 * "A string provided to GetProgramResourceLocation or
714 * GetProgramResourceLocationIndex is considered to match an active variable
715 * if:
716 *
717 * * the string exactly matches the name of the active variable;
718 *
719 * * if the string identifies the base name of an active array, where the
720 * string would exactly match the name of the variable if the suffix
721 * "[0]" were appended to the string; [...]"
722 */
723 /* Remove array's index from interface block name comparison only if
724 * array's index is zero and the resulting string length is the same
725 * than the provided name's length.
726 */
727 int length_without_array_index =
728 rname.last_square_bracket >= 0 ? rname.last_square_bracket : rname.length;
729 bool rname_has_array_index_zero = rname.suffix_is_zero_square_bracketed &&
730 rname.last_square_bracket == len;
731
732 if (len >= rname.length && strncmp(rname.string, name, rname.length) == 0)
733 found = true;
734 else if (rname_has_array_index_zero &&
735 strncmp(rname.string, name, length_without_array_index) == 0)
736 found = true;
737
738 if (found) {
739 switch (programInterface) {
740 case GL_UNIFORM_BLOCK:
741 case GL_SHADER_STORAGE_BLOCK:
742 /* Basename match, check if array or struct. */
743 if (rname_has_array_index_zero ||
744 name[rname.length] == '\0' ||
745 name[rname.length] == '[' ||
746 name[rname.length] == '.') {
747 return res;
748 }
749 break;
750 case GL_TRANSFORM_FEEDBACK_VARYING:
751 case GL_BUFFER_VARIABLE:
752 case GL_UNIFORM:
753 case GL_VERTEX_SUBROUTINE_UNIFORM:
754 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
755 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
756 case GL_COMPUTE_SUBROUTINE_UNIFORM:
757 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
758 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
759 case GL_VERTEX_SUBROUTINE:
760 case GL_GEOMETRY_SUBROUTINE:
761 case GL_FRAGMENT_SUBROUTINE:
762 case GL_COMPUTE_SUBROUTINE:
763 case GL_TESS_CONTROL_SUBROUTINE:
764 case GL_TESS_EVALUATION_SUBROUTINE:
765 if (name[rname.length] == '.') {
766 return res;
767 }
768 FALLTHROUGH;
769 case GL_PROGRAM_INPUT:
770 case GL_PROGRAM_OUTPUT:
771 if (name[rname.length] == '\0') {
772 return res;
773 } else if (name[rname.length] == '[' &&
774 valid_array_index(name, len, array_index)) {
775 return res;
776 }
777 break;
778 default:
779 assert(!"not implemented for given interface");
780 }
781 }
782 }
783 return NULL;
784 }
785
786 /* Find an uniform or buffer variable program resource with an specific offset
787 * inside a block with an specific binding.
788 *
789 * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
790 */
791 static struct gl_program_resource *
program_resource_find_binding_offset(struct gl_shader_program * shProg,GLenum programInterface,const GLuint binding,const GLint offset)792 program_resource_find_binding_offset(struct gl_shader_program *shProg,
793 GLenum programInterface,
794 const GLuint binding,
795 const GLint offset)
796 {
797
798 /* First we need to get the BLOCK_INDEX from the BUFFER_BINDING */
799 GLenum blockInterface;
800
801 switch (programInterface) {
802 case GL_BUFFER_VARIABLE:
803 blockInterface = GL_SHADER_STORAGE_BLOCK;
804 break;
805 case GL_UNIFORM:
806 blockInterface = GL_UNIFORM_BLOCK;
807 break;
808 default:
809 assert("Invalid program interface");
810 return NULL;
811 }
812
813 int block_index = -1;
814 int starting_index = -1;
815 struct gl_program_resource *res = shProg->data->ProgramResourceList;
816
817 /* Blocks are added to the resource list in the same order that they are
818 * added to UniformBlocks/ShaderStorageBlocks. Furthermore, all the blocks
819 * of each type (UBO/SSBO) are contiguous, so we can infer block_index from
820 * the resource list.
821 */
822 for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
823 if (res->Type != blockInterface)
824 continue;
825
826 /* Store the first index where a resource of the specific interface is. */
827 if (starting_index == -1)
828 starting_index = i;
829
830 const struct gl_uniform_block *block = RESOURCE_UBO(res);
831
832 if (block->Binding == binding) {
833 /* For arrays, or arrays of arrays of blocks, we want the resource
834 * for the block with base index. Most properties for members of each
835 * block are inherited from the block with the base index, including
836 * a uniform being active or not.
837 */
838 block_index = i - starting_index - block->linearized_array_index;
839 break;
840 }
841 }
842
843 if (block_index == -1)
844 return NULL;
845
846 /* We now look for the resource corresponding to the uniform or buffer
847 * variable using the BLOCK_INDEX and OFFSET.
848 */
849 res = shProg->data->ProgramResourceList;
850 for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
851 if (res->Type != programInterface)
852 continue;
853
854 const struct gl_uniform_storage *uniform = RESOURCE_UNI(res);
855
856 if (uniform->block_index == block_index && uniform->offset == offset) {
857 return res;
858 }
859 }
860
861 return NULL;
862 }
863
864 /* Checks if an uniform or buffer variable is in the active program resource
865 * list.
866 *
867 * It takes into accout that for variables coming from SPIR-V binaries their
868 * names could not be available (ARB_gl_spirv). In that case, it will use the
869 * the offset and the block binding to locate the resource.
870 *
871 * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
872 */
873 struct gl_program_resource *
_mesa_program_resource_find_active_variable(struct gl_shader_program * shProg,GLenum programInterface,const gl_uniform_block * block,unsigned index)874 _mesa_program_resource_find_active_variable(struct gl_shader_program *shProg,
875 GLenum programInterface,
876 const gl_uniform_block *block,
877 unsigned index)
878 {
879 struct gl_program_resource *res;
880 struct gl_uniform_buffer_variable uni = block->Uniforms[index];
881
882 assert(programInterface == GL_UNIFORM ||
883 programInterface == GL_BUFFER_VARIABLE);
884
885 if (uni.IndexName) {
886 res = _mesa_program_resource_find_name(shProg, programInterface, uni.IndexName,
887 NULL);
888 } else {
889 /* As the resource has no associated name (ARB_gl_spirv),
890 * we can use the UBO/SSBO binding and offset to find it.
891 */
892 res = program_resource_find_binding_offset(shProg, programInterface,
893 block->Binding, uni.Offset);
894 }
895
896 return res;
897 }
898
899 static GLuint
calc_resource_index(struct gl_shader_program * shProg,struct gl_program_resource * res)900 calc_resource_index(struct gl_shader_program *shProg,
901 struct gl_program_resource *res)
902 {
903 unsigned i;
904 GLuint index = 0;
905 for (i = 0; i < shProg->data->NumProgramResourceList; i++) {
906 if (&shProg->data->ProgramResourceList[i] == res)
907 return index;
908 if (shProg->data->ProgramResourceList[i].Type == res->Type)
909 index++;
910 }
911 return GL_INVALID_INDEX;
912 }
913
914 /**
915 * Calculate index for the given resource.
916 */
917 GLuint
_mesa_program_resource_index(struct gl_shader_program * shProg,struct gl_program_resource * res)918 _mesa_program_resource_index(struct gl_shader_program *shProg,
919 struct gl_program_resource *res)
920 {
921 if (!res)
922 return GL_INVALID_INDEX;
923
924 switch (res->Type) {
925 case GL_ATOMIC_COUNTER_BUFFER:
926 return RESOURCE_ATC(res) - shProg->data->AtomicBuffers;
927 case GL_VERTEX_SUBROUTINE:
928 case GL_GEOMETRY_SUBROUTINE:
929 case GL_FRAGMENT_SUBROUTINE:
930 case GL_COMPUTE_SUBROUTINE:
931 case GL_TESS_CONTROL_SUBROUTINE:
932 case GL_TESS_EVALUATION_SUBROUTINE:
933 return RESOURCE_SUB(res)->index;
934 case GL_UNIFORM_BLOCK:
935 case GL_SHADER_STORAGE_BLOCK:
936 case GL_TRANSFORM_FEEDBACK_BUFFER:
937 case GL_TRANSFORM_FEEDBACK_VARYING:
938 default:
939 return calc_resource_index(shProg, res);
940 }
941 }
942
943 /**
944 * Find a program resource that points to given data.
945 */
946 static struct gl_program_resource*
program_resource_find_data(struct gl_shader_program * shProg,void * data)947 program_resource_find_data(struct gl_shader_program *shProg, void *data)
948 {
949 struct gl_program_resource *res = shProg->data->ProgramResourceList;
950 for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
951 i++, res++) {
952 if (res->Data == data)
953 return res;
954 }
955 return NULL;
956 }
957
958 /* Find a program resource with specific index in given interface.
959 */
960 struct gl_program_resource *
_mesa_program_resource_find_index(struct gl_shader_program * shProg,GLenum programInterface,GLuint index)961 _mesa_program_resource_find_index(struct gl_shader_program *shProg,
962 GLenum programInterface, GLuint index)
963 {
964 struct gl_program_resource *res = shProg->data->ProgramResourceList;
965 int idx = -1;
966
967 for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
968 i++, res++) {
969 if (res->Type != programInterface)
970 continue;
971
972 switch (res->Type) {
973 case GL_UNIFORM_BLOCK:
974 case GL_ATOMIC_COUNTER_BUFFER:
975 case GL_SHADER_STORAGE_BLOCK:
976 case GL_TRANSFORM_FEEDBACK_BUFFER:
977 if (_mesa_program_resource_index(shProg, res) == index)
978 return res;
979 break;
980 case GL_TRANSFORM_FEEDBACK_VARYING:
981 case GL_PROGRAM_INPUT:
982 case GL_PROGRAM_OUTPUT:
983 case GL_UNIFORM:
984 case GL_VERTEX_SUBROUTINE_UNIFORM:
985 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
986 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
987 case GL_COMPUTE_SUBROUTINE_UNIFORM:
988 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
989 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
990 case GL_VERTEX_SUBROUTINE:
991 case GL_GEOMETRY_SUBROUTINE:
992 case GL_FRAGMENT_SUBROUTINE:
993 case GL_COMPUTE_SUBROUTINE:
994 case GL_TESS_CONTROL_SUBROUTINE:
995 case GL_TESS_EVALUATION_SUBROUTINE:
996 case GL_BUFFER_VARIABLE:
997 if (++idx == (int) index)
998 return res;
999 break;
1000 default:
1001 assert(!"not implemented for given interface");
1002 }
1003 }
1004 return NULL;
1005 }
1006
1007 /* Function returns if resource name is expected to have index
1008 * appended into it.
1009 *
1010 *
1011 * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
1012 * spec says:
1013 *
1014 * "If the active uniform is an array, the uniform name returned in
1015 * name will always be the name of the uniform array appended with
1016 * "[0]"."
1017 *
1018 * The same text also appears in the OpenGL 4.2 spec. It does not,
1019 * however, appear in any previous spec. Previous specifications are
1020 * ambiguous in this regard. However, either name can later be passed
1021 * to glGetUniformLocation (and related APIs), so there shouldn't be any
1022 * harm in always appending "[0]" to uniform array names.
1023 */
1024 static bool
add_index_to_name(struct gl_program_resource * res)1025 add_index_to_name(struct gl_program_resource *res)
1026 {
1027 /* Transform feedback varyings have array index already appended
1028 * in their names.
1029 */
1030 return res->Type != GL_TRANSFORM_FEEDBACK_VARYING;
1031 }
1032
1033 /* Get name length of a program resource. This consists of
1034 * base name + 3 for '[0]' if resource is an array.
1035 */
1036 extern unsigned
_mesa_program_resource_name_length_array(struct gl_program_resource * res)1037 _mesa_program_resource_name_length_array(struct gl_program_resource *res)
1038 {
1039 int length = _mesa_program_resource_name_length(res);
1040
1041 /* For shaders constructed from SPIR-V binaries, variables may not
1042 * have names associated with them.
1043 */
1044 if (!length)
1045 return 0;
1046
1047 if (_mesa_program_resource_array_size(res) && add_index_to_name(res))
1048 length += 3;
1049 return length;
1050 }
1051
1052 /* Get full name of a program resource.
1053 */
1054 bool
_mesa_get_program_resource_name(struct gl_shader_program * shProg,GLenum programInterface,GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name,bool glthread,const char * caller)1055 _mesa_get_program_resource_name(struct gl_shader_program *shProg,
1056 GLenum programInterface, GLuint index,
1057 GLsizei bufSize, GLsizei *length,
1058 GLchar *name, bool glthread,
1059 const char *caller)
1060 {
1061 GET_CURRENT_CONTEXT(ctx);
1062
1063 /* Find resource with given interface and index. */
1064 struct gl_program_resource *res =
1065 _mesa_program_resource_find_index(shProg, programInterface, index);
1066
1067 /* The error INVALID_VALUE is generated if <index> is greater than
1068 * or equal to the number of entries in the active resource list for
1069 * <programInterface>.
1070 */
1071 if (!res) {
1072 _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
1073 "%s(index %u)", caller, index);
1074 return false;
1075 }
1076
1077 if (bufSize < 0) {
1078 _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
1079 "%s(bufSize %d)", caller, bufSize);
1080 return false;
1081 }
1082
1083 GLsizei localLength;
1084
1085 if (length == NULL)
1086 length = &localLength;
1087
1088 _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
1089
1090 /* The resource name can be NULL for shaders constructed from SPIR-V
1091 * binaries. In that case, we do not add the '[0]'.
1092 */
1093 if (name && name[0] != '\0' &&
1094 _mesa_program_resource_array_size(res) && add_index_to_name(res)) {
1095 int i;
1096
1097 /* The comparison is strange because *length does *NOT* include the
1098 * terminating NUL, but maxLength does.
1099 */
1100 for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
1101 name[*length + i] = "[0]"[i];
1102
1103 name[*length + i] = '\0';
1104 *length += i;
1105 }
1106 return true;
1107 }
1108
1109 static GLint
program_resource_location(struct gl_program_resource * res,unsigned array_index)1110 program_resource_location(struct gl_program_resource *res, unsigned array_index)
1111 {
1112 switch (res->Type) {
1113 case GL_PROGRAM_INPUT: {
1114 const gl_shader_variable *var = RESOURCE_VAR(res);
1115
1116 if (var->location == -1)
1117 return -1;
1118
1119 /* If the input is an array, fail if the index is out of bounds. */
1120 if (array_index > 0
1121 && array_index >= var->type->length) {
1122 return -1;
1123 }
1124 return var->location +
1125 (array_index * var->type->without_array()->matrix_columns);
1126 }
1127 case GL_PROGRAM_OUTPUT:
1128 if (RESOURCE_VAR(res)->location == -1)
1129 return -1;
1130
1131 /* If the output is an array, fail if the index is out of bounds. */
1132 if (array_index > 0
1133 && array_index >= RESOURCE_VAR(res)->type->length) {
1134 return -1;
1135 }
1136 return RESOURCE_VAR(res)->location + array_index;
1137 case GL_UNIFORM:
1138 /* If the uniform is built-in, fail. */
1139 if (RESOURCE_UNI(res)->builtin)
1140 return -1;
1141
1142 /* From page 79 of the OpenGL 4.2 spec:
1143 *
1144 * "A valid name cannot be a structure, an array of structures, or any
1145 * portion of a single vector or a matrix."
1146 */
1147 if (RESOURCE_UNI(res)->type->without_array()->is_struct())
1148 return -1;
1149
1150 /* From the GL_ARB_uniform_buffer_object spec:
1151 *
1152 * "The value -1 will be returned if <name> does not correspond to an
1153 * active uniform variable name in <program>, if <name> is associated
1154 * with a named uniform block, or if <name> starts with the reserved
1155 * prefix "gl_"."
1156 */
1157 if (RESOURCE_UNI(res)->block_index != -1 ||
1158 RESOURCE_UNI(res)->atomic_buffer_index != -1)
1159 return -1;
1160
1161 FALLTHROUGH;
1162 case GL_VERTEX_SUBROUTINE_UNIFORM:
1163 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1164 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1165 case GL_COMPUTE_SUBROUTINE_UNIFORM:
1166 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1167 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1168 /* If the uniform is an array, fail if the index is out of bounds. */
1169 if (array_index > 0
1170 && array_index >= RESOURCE_UNI(res)->array_elements) {
1171 return -1;
1172 }
1173
1174 /* location in remap table + array element offset */
1175 return RESOURCE_UNI(res)->remap_location + array_index;
1176 default:
1177 return -1;
1178 }
1179 }
1180
1181 /**
1182 * Function implements following location queries:
1183 * glGetUniformLocation
1184 */
1185 GLint
_mesa_program_resource_location(struct gl_shader_program * shProg,GLenum programInterface,const char * name)1186 _mesa_program_resource_location(struct gl_shader_program *shProg,
1187 GLenum programInterface, const char *name)
1188 {
1189 unsigned array_index = 0;
1190 struct gl_program_resource *res =
1191 _mesa_program_resource_find_name(shProg, programInterface, name,
1192 &array_index);
1193
1194 /* Resource not found. */
1195 if (!res)
1196 return -1;
1197
1198 return program_resource_location(res, array_index);
1199 }
1200
1201 static GLint
_get_resource_location_index(struct gl_program_resource * res)1202 _get_resource_location_index(struct gl_program_resource *res)
1203 {
1204 /* Non-existent variable or resource is not referenced by fragment stage. */
1205 if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
1206 return -1;
1207
1208 /* From OpenGL 4.5 spec, 7.3 Program Objects
1209 * "The value -1 will be returned by either command...
1210 * ... or if name identifies an active variable that does not have a
1211 * valid location assigned.
1212 */
1213 if (RESOURCE_VAR(res)->location == -1)
1214 return -1;
1215 return RESOURCE_VAR(res)->index;
1216 }
1217
1218 /**
1219 * Function implements following index queries:
1220 * glGetFragDataIndex
1221 */
1222 GLint
_mesa_program_resource_location_index(struct gl_shader_program * shProg,GLenum programInterface,const char * name)1223 _mesa_program_resource_location_index(struct gl_shader_program *shProg,
1224 GLenum programInterface, const char *name)
1225 {
1226 struct gl_program_resource *res =
1227 _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
1228
1229 return _get_resource_location_index(res);
1230 }
1231
1232 static uint8_t
stage_from_enum(GLenum ref)1233 stage_from_enum(GLenum ref)
1234 {
1235 switch (ref) {
1236 case GL_REFERENCED_BY_VERTEX_SHADER:
1237 return MESA_SHADER_VERTEX;
1238 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1239 return MESA_SHADER_TESS_CTRL;
1240 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1241 return MESA_SHADER_TESS_EVAL;
1242 case GL_REFERENCED_BY_GEOMETRY_SHADER:
1243 return MESA_SHADER_GEOMETRY;
1244 case GL_REFERENCED_BY_FRAGMENT_SHADER:
1245 return MESA_SHADER_FRAGMENT;
1246 case GL_REFERENCED_BY_COMPUTE_SHADER:
1247 return MESA_SHADER_COMPUTE;
1248 default:
1249 assert(!"shader stage not supported");
1250 return MESA_SHADER_STAGES;
1251 }
1252 }
1253
1254 /**
1255 * Check if resource is referenced by given 'referenced by' stage enum.
1256 * ATC and UBO resources hold stage references of their own.
1257 */
1258 static bool
is_resource_referenced(struct gl_shader_program * shProg,struct gl_program_resource * res,GLuint index,uint8_t stage)1259 is_resource_referenced(struct gl_shader_program *shProg,
1260 struct gl_program_resource *res,
1261 GLuint index, uint8_t stage)
1262 {
1263 /* First, check if we even have such a stage active. */
1264 if (!shProg->_LinkedShaders[stage])
1265 return false;
1266
1267 if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
1268 return RESOURCE_ATC(res)->StageReferences[stage];
1269
1270 if (res->Type == GL_UNIFORM_BLOCK)
1271 return shProg->data->UniformBlocks[index].stageref & (1 << stage);
1272
1273 if (res->Type == GL_SHADER_STORAGE_BLOCK)
1274 return shProg->data->ShaderStorageBlocks[index].stageref & (1 << stage);
1275
1276 return res->StageReferences & (1 << stage);
1277 }
1278
1279 static unsigned
get_buffer_property(struct gl_shader_program * shProg,struct gl_program_resource * res,const GLenum prop,GLint * val,bool glthread,const char * caller)1280 get_buffer_property(struct gl_shader_program *shProg,
1281 struct gl_program_resource *res, const GLenum prop,
1282 GLint *val, bool glthread, const char *caller)
1283 {
1284 GET_CURRENT_CONTEXT(ctx);
1285 if (res->Type != GL_UNIFORM_BLOCK &&
1286 res->Type != GL_ATOMIC_COUNTER_BUFFER &&
1287 res->Type != GL_SHADER_STORAGE_BLOCK &&
1288 res->Type != GL_TRANSFORM_FEEDBACK_BUFFER)
1289 goto invalid_operation;
1290
1291 if (res->Type == GL_UNIFORM_BLOCK) {
1292 switch (prop) {
1293 case GL_BUFFER_BINDING:
1294 *val = RESOURCE_UBO(res)->Binding;
1295 return 1;
1296 case GL_BUFFER_DATA_SIZE:
1297 *val = RESOURCE_UBO(res)->UniformBufferSize;
1298 return 1;
1299 case GL_NUM_ACTIVE_VARIABLES:
1300 *val = 0;
1301 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1302 struct gl_program_resource *uni =
1303 _mesa_program_resource_find_active_variable(
1304 shProg,
1305 GL_UNIFORM,
1306 RESOURCE_UBO(res),
1307 i);
1308
1309 if (!uni)
1310 continue;
1311 (*val)++;
1312 }
1313 return 1;
1314 case GL_ACTIVE_VARIABLES: {
1315 unsigned num_values = 0;
1316 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1317 struct gl_program_resource *uni =
1318 _mesa_program_resource_find_active_variable(
1319 shProg,
1320 GL_UNIFORM,
1321 RESOURCE_UBO(res),
1322 i);
1323
1324 if (!uni)
1325 continue;
1326 *val++ =
1327 _mesa_program_resource_index(shProg, uni);
1328 num_values++;
1329 }
1330 return num_values;
1331 }
1332 }
1333 } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
1334 switch (prop) {
1335 case GL_BUFFER_BINDING:
1336 *val = RESOURCE_UBO(res)->Binding;
1337 return 1;
1338 case GL_BUFFER_DATA_SIZE:
1339 *val = RESOURCE_UBO(res)->UniformBufferSize;
1340 return 1;
1341 case GL_NUM_ACTIVE_VARIABLES:
1342 *val = 0;
1343 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1344 struct gl_program_resource *uni =
1345 _mesa_program_resource_find_active_variable(
1346 shProg,
1347 GL_BUFFER_VARIABLE,
1348 RESOURCE_UBO(res),
1349 i);
1350
1351 if (!uni)
1352 continue;
1353 (*val)++;
1354 }
1355 return 1;
1356 case GL_ACTIVE_VARIABLES: {
1357 unsigned num_values = 0;
1358 for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
1359 struct gl_program_resource *uni =
1360 _mesa_program_resource_find_active_variable(
1361 shProg,
1362 GL_BUFFER_VARIABLE,
1363 RESOURCE_UBO(res),
1364 i);
1365
1366 if (!uni)
1367 continue;
1368 *val++ =
1369 _mesa_program_resource_index(shProg, uni);
1370 num_values++;
1371 }
1372 return num_values;
1373 }
1374 }
1375 } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
1376 switch (prop) {
1377 case GL_BUFFER_BINDING:
1378 *val = RESOURCE_ATC(res)->Binding;
1379 return 1;
1380 case GL_BUFFER_DATA_SIZE:
1381 *val = RESOURCE_ATC(res)->MinimumSize;
1382 return 1;
1383 case GL_NUM_ACTIVE_VARIABLES:
1384 *val = RESOURCE_ATC(res)->NumUniforms;
1385 return 1;
1386 case GL_ACTIVE_VARIABLES:
1387 for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) {
1388 /* Active atomic buffer contains index to UniformStorage. Find
1389 * out gl_program_resource via data pointer and then calculate
1390 * index of that uniform.
1391 */
1392 unsigned idx = RESOURCE_ATC(res)->Uniforms[i];
1393 struct gl_program_resource *uni =
1394 program_resource_find_data(shProg,
1395 &shProg->data->UniformStorage[idx]);
1396 assert(uni);
1397 *val++ = _mesa_program_resource_index(shProg, uni);
1398 }
1399 return RESOURCE_ATC(res)->NumUniforms;
1400 }
1401 } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) {
1402 switch (prop) {
1403 case GL_BUFFER_BINDING:
1404 *val = RESOURCE_XFB(res)->Binding;
1405 return 1;
1406 case GL_NUM_ACTIVE_VARIABLES:
1407 *val = RESOURCE_XFB(res)->NumVaryings;
1408 return 1;
1409 case GL_ACTIVE_VARIABLES:
1410 struct gl_transform_feedback_info *linked_xfb =
1411 shProg->last_vert_prog->sh.LinkedTransformFeedback;
1412 for (int i = 0; i < linked_xfb->NumVarying; i++) {
1413 unsigned index = linked_xfb->Varyings[i].BufferIndex;
1414 struct gl_program_resource *buf_res =
1415 _mesa_program_resource_find_index(shProg,
1416 GL_TRANSFORM_FEEDBACK_BUFFER,
1417 index);
1418 assert(buf_res);
1419 if (res == buf_res) {
1420 *val++ = i;
1421 }
1422 }
1423 return RESOURCE_XFB(res)->NumVaryings;
1424 }
1425 }
1426 assert(!"support for property type not implemented");
1427
1428 invalid_operation:
1429 _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
1430 "%s(%s prop %s)", caller,
1431 _mesa_enum_to_string(res->Type),
1432 _mesa_enum_to_string(prop));
1433
1434 return 0;
1435 }
1436
1437 unsigned
_mesa_program_resource_prop(struct gl_shader_program * shProg,struct gl_program_resource * res,GLuint index,const GLenum prop,GLint * val,bool glthread,const char * caller)1438 _mesa_program_resource_prop(struct gl_shader_program *shProg,
1439 struct gl_program_resource *res, GLuint index,
1440 const GLenum prop, GLint *val, bool glthread,
1441 const char *caller)
1442 {
1443 GET_CURRENT_CONTEXT(ctx);
1444
1445 #define VALIDATE_TYPE(type)\
1446 if (res->Type != type)\
1447 goto invalid_operation;
1448
1449 #define VALIDATE_TYPE_2(type1, type2)\
1450 if (res->Type != type1 && res->Type != type2)\
1451 goto invalid_operation;
1452
1453 switch(prop) {
1454 case GL_NAME_LENGTH:
1455 switch (res->Type) {
1456 case GL_ATOMIC_COUNTER_BUFFER:
1457 case GL_TRANSFORM_FEEDBACK_BUFFER:
1458 goto invalid_operation;
1459 default:
1460 /* Resource name length + terminator. */
1461 *val = _mesa_program_resource_name_length_array(res) + 1;
1462 }
1463 return 1;
1464 case GL_TYPE:
1465 switch (res->Type) {
1466 case GL_UNIFORM:
1467 case GL_BUFFER_VARIABLE:
1468 *val = RESOURCE_UNI(res)->type->gl_type;
1469 *val = mediump_to_highp_type(*val);
1470 return 1;
1471 case GL_PROGRAM_INPUT:
1472 case GL_PROGRAM_OUTPUT:
1473 *val = RESOURCE_VAR(res)->type->gl_type;
1474 *val = mediump_to_highp_type(*val);
1475 return 1;
1476 case GL_TRANSFORM_FEEDBACK_VARYING:
1477 *val = RESOURCE_XFV(res)->Type;
1478 *val = mediump_to_highp_type(*val);
1479 return 1;
1480 default:
1481 goto invalid_operation;
1482 }
1483 case GL_ARRAY_SIZE:
1484 switch (res->Type) {
1485 case GL_UNIFORM:
1486 case GL_BUFFER_VARIABLE:
1487 case GL_VERTEX_SUBROUTINE_UNIFORM:
1488 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1489 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1490 case GL_COMPUTE_SUBROUTINE_UNIFORM:
1491 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1492 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1493
1494 /* Test if a buffer variable is an array or an unsized array.
1495 * Unsized arrays return zero as array size.
1496 */
1497 if (RESOURCE_UNI(res)->is_shader_storage &&
1498 RESOURCE_UNI(res)->array_stride > 0)
1499 *val = RESOURCE_UNI(res)->array_elements;
1500 else
1501 *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
1502 return 1;
1503 case GL_PROGRAM_INPUT:
1504 case GL_PROGRAM_OUTPUT:
1505 *val = MAX2(_mesa_program_resource_array_size(res), 1);
1506 return 1;
1507 case GL_TRANSFORM_FEEDBACK_VARYING:
1508 *val = RESOURCE_XFV(res)->Size;
1509 return 1;
1510 default:
1511 goto invalid_operation;
1512 }
1513 case GL_OFFSET:
1514 switch (res->Type) {
1515 case GL_UNIFORM:
1516 case GL_BUFFER_VARIABLE:
1517 *val = RESOURCE_UNI(res)->offset;
1518 return 1;
1519 case GL_TRANSFORM_FEEDBACK_VARYING:
1520 *val = RESOURCE_XFV(res)->Offset;
1521 return 1;
1522 default:
1523 goto invalid_operation;
1524 }
1525 case GL_BLOCK_INDEX:
1526 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1527 *val = RESOURCE_UNI(res)->block_index;
1528 return 1;
1529 case GL_ARRAY_STRIDE:
1530 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1531 *val = RESOURCE_UNI(res)->array_stride;
1532 return 1;
1533 case GL_MATRIX_STRIDE:
1534 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1535 *val = RESOURCE_UNI(res)->matrix_stride;
1536 return 1;
1537 case GL_IS_ROW_MAJOR:
1538 VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1539 *val = RESOURCE_UNI(res)->row_major;
1540 return 1;
1541 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
1542 VALIDATE_TYPE(GL_UNIFORM);
1543 *val = RESOURCE_UNI(res)->atomic_buffer_index;
1544 return 1;
1545 case GL_BUFFER_BINDING:
1546 case GL_BUFFER_DATA_SIZE:
1547 case GL_NUM_ACTIVE_VARIABLES:
1548 case GL_ACTIVE_VARIABLES:
1549 return get_buffer_property(shProg, res, prop, val, glthread, caller);
1550 case GL_REFERENCED_BY_COMPUTE_SHADER:
1551 if (!_mesa_has_compute_shaders(ctx))
1552 goto invalid_enum;
1553 FALLTHROUGH;
1554 case GL_REFERENCED_BY_VERTEX_SHADER:
1555 case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1556 case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1557 case GL_REFERENCED_BY_GEOMETRY_SHADER:
1558 case GL_REFERENCED_BY_FRAGMENT_SHADER:
1559 switch (res->Type) {
1560 case GL_UNIFORM:
1561 case GL_PROGRAM_INPUT:
1562 case GL_PROGRAM_OUTPUT:
1563 case GL_UNIFORM_BLOCK:
1564 case GL_BUFFER_VARIABLE:
1565 case GL_SHADER_STORAGE_BLOCK:
1566 case GL_ATOMIC_COUNTER_BUFFER:
1567 *val = is_resource_referenced(shProg, res, index,
1568 stage_from_enum(prop));
1569 return 1;
1570 default:
1571 goto invalid_operation;
1572 }
1573 case GL_LOCATION:
1574 switch (res->Type) {
1575 case GL_UNIFORM:
1576 case GL_VERTEX_SUBROUTINE_UNIFORM:
1577 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1578 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1579 case GL_COMPUTE_SUBROUTINE_UNIFORM:
1580 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1581 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1582 case GL_PROGRAM_INPUT:
1583 case GL_PROGRAM_OUTPUT:
1584 *val = program_resource_location(res, 0);
1585 return 1;
1586 default:
1587 goto invalid_operation;
1588 }
1589 case GL_LOCATION_COMPONENT:
1590 switch (res->Type) {
1591 case GL_PROGRAM_INPUT:
1592 case GL_PROGRAM_OUTPUT:
1593 *val = RESOURCE_VAR(res)->component;
1594 return 1;
1595 default:
1596 goto invalid_operation;
1597 }
1598 case GL_LOCATION_INDEX: {
1599 int tmp;
1600 if (res->Type != GL_PROGRAM_OUTPUT)
1601 goto invalid_operation;
1602 tmp = program_resource_location(res, 0);
1603 if (tmp == -1)
1604 *val = -1;
1605 else
1606 *val = _get_resource_location_index(res);
1607 return 1;
1608 }
1609 case GL_NUM_COMPATIBLE_SUBROUTINES:
1610 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1611 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1612 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1613 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1614 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1615 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1616 goto invalid_operation;
1617 *val = RESOURCE_UNI(res)->num_compatible_subroutines;
1618 return 1;
1619 case GL_COMPATIBLE_SUBROUTINES: {
1620 const struct gl_uniform_storage *uni;
1621 struct gl_program *p;
1622 unsigned count, i;
1623 int j;
1624
1625 if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1626 res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1627 res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1628 res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1629 res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1630 res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1631 goto invalid_operation;
1632 uni = RESOURCE_UNI(res);
1633
1634 p = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]->Program;
1635 count = 0;
1636 for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
1637 struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
1638 for (j = 0; j < fn->num_compat_types; j++) {
1639 if (fn->types[j] == uni->type) {
1640 val[count++] = i;
1641 break;
1642 }
1643 }
1644 }
1645 return count;
1646 }
1647
1648 case GL_TOP_LEVEL_ARRAY_SIZE:
1649 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1650 *val = RESOURCE_UNI(res)->top_level_array_size;
1651 return 1;
1652
1653 case GL_TOP_LEVEL_ARRAY_STRIDE:
1654 VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1655 *val = RESOURCE_UNI(res)->top_level_array_stride;
1656 return 1;
1657
1658 /* GL_ARB_tessellation_shader */
1659 case GL_IS_PER_PATCH:
1660 switch (res->Type) {
1661 case GL_PROGRAM_INPUT:
1662 case GL_PROGRAM_OUTPUT:
1663 *val = RESOURCE_VAR(res)->patch;
1664 return 1;
1665 default:
1666 goto invalid_operation;
1667 }
1668
1669 case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX:
1670 VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING);
1671 *val = RESOURCE_XFV(res)->BufferIndex;
1672 return 1;
1673 case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE:
1674 VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER);
1675 *val = RESOURCE_XFB(res)->Stride * 4;
1676 return 1;
1677
1678 default:
1679 goto invalid_enum;
1680 }
1681
1682 #undef VALIDATE_TYPE
1683 #undef VALIDATE_TYPE_2
1684
1685 invalid_enum:
1686 _mesa_error_glthread_safe(ctx, GL_INVALID_ENUM, glthread,
1687 "%s(%s prop %s)", caller,
1688 _mesa_enum_to_string(res->Type),
1689 _mesa_enum_to_string(prop));
1690 return 0;
1691
1692 invalid_operation:
1693 _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
1694 "%s(%s prop %s)", caller,
1695 _mesa_enum_to_string(res->Type),
1696 _mesa_enum_to_string(prop));
1697 return 0;
1698 }
1699
1700 extern void
_mesa_get_program_resourceiv(struct gl_shader_program * shProg,GLenum programInterface,GLuint index,GLsizei propCount,const GLenum * props,GLsizei bufSize,GLsizei * length,GLint * params)1701 _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1702 GLenum programInterface, GLuint index, GLsizei propCount,
1703 const GLenum *props, GLsizei bufSize,
1704 GLsizei *length, GLint *params)
1705 {
1706 GET_CURRENT_CONTEXT(ctx);
1707 GLint *val = (GLint *) params;
1708 const GLenum *prop = props;
1709 GLsizei amount = 0;
1710
1711 struct gl_program_resource *res =
1712 _mesa_program_resource_find_index(shProg, programInterface, index);
1713
1714 /* No such resource found or bufSize negative. */
1715 if (!res || bufSize < 0) {
1716 _mesa_error(ctx, GL_INVALID_VALUE,
1717 "glGetProgramResourceiv(%s index %d bufSize %d)",
1718 _mesa_enum_to_string(programInterface), index, bufSize);
1719 return;
1720 }
1721
1722 /* Write propCount values until error occurs or bufSize reached. */
1723 for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1724 int props_written =
1725 _mesa_program_resource_prop(shProg, res, index, *prop, val,
1726 false, "glGetProgramResourceiv");
1727
1728 /* Error happened. */
1729 if (props_written == 0)
1730 return;
1731
1732 amount += props_written;
1733 }
1734
1735 /* If <length> is not NULL, the actual number of integer values
1736 * written to <params> will be written to <length>.
1737 */
1738 if (length)
1739 *length = amount;
1740 }
1741
1742 extern void
_mesa_get_program_interfaceiv(struct gl_shader_program * shProg,GLenum programInterface,GLenum pname,GLint * params)1743 _mesa_get_program_interfaceiv(struct gl_shader_program *shProg,
1744 GLenum programInterface, GLenum pname,
1745 GLint *params)
1746 {
1747 GET_CURRENT_CONTEXT(ctx);
1748 unsigned i;
1749
1750 /* Validate pname against interface. */
1751 switch(pname) {
1752 case GL_ACTIVE_RESOURCES:
1753 for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++)
1754 if (shProg->data->ProgramResourceList[i].Type == programInterface)
1755 (*params)++;
1756 break;
1757 case GL_MAX_NAME_LENGTH:
1758 if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
1759 programInterface == GL_TRANSFORM_FEEDBACK_BUFFER) {
1760 _mesa_error(ctx, GL_INVALID_OPERATION,
1761 "glGetProgramInterfaceiv(%s pname %s)",
1762 _mesa_enum_to_string(programInterface),
1763 _mesa_enum_to_string(pname));
1764 return;
1765 }
1766 /* Name length consists of base name, 3 additional chars '[0]' if
1767 * resource is an array and finally 1 char for string terminator.
1768 */
1769 for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1770 if (shProg->data->ProgramResourceList[i].Type != programInterface)
1771 continue;
1772 unsigned len =
1773 _mesa_program_resource_name_length_array(&shProg->data->ProgramResourceList[i]);
1774 *params = MAX2((unsigned)*params, len + 1);
1775 }
1776 break;
1777 case GL_MAX_NUM_ACTIVE_VARIABLES:
1778 switch (programInterface) {
1779 case GL_UNIFORM_BLOCK:
1780 for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1781 if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1782 struct gl_uniform_block *block =
1783 (struct gl_uniform_block *)
1784 shProg->data->ProgramResourceList[i].Data;
1785 *params = MAX2((unsigned)*params, block->NumUniforms);
1786 }
1787 }
1788 break;
1789 case GL_SHADER_STORAGE_BLOCK:
1790 for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1791 if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1792 struct gl_uniform_block *block =
1793 (struct gl_uniform_block *)
1794 shProg->data->ProgramResourceList[i].Data;
1795 GLint block_params = 0;
1796 for (unsigned j = 0; j < block->NumUniforms; j++) {
1797 struct gl_program_resource *uni =
1798 _mesa_program_resource_find_active_variable(
1799 shProg,
1800 GL_BUFFER_VARIABLE,
1801 block,
1802 j);
1803 if (!uni)
1804 continue;
1805 block_params++;
1806 }
1807 *params = MAX2(*params, block_params);
1808 }
1809 }
1810 break;
1811 case GL_ATOMIC_COUNTER_BUFFER:
1812 for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1813 if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1814 struct gl_active_atomic_buffer *buffer =
1815 (struct gl_active_atomic_buffer *)
1816 shProg->data->ProgramResourceList[i].Data;
1817 *params = MAX2((unsigned)*params, buffer->NumUniforms);
1818 }
1819 }
1820 break;
1821 case GL_TRANSFORM_FEEDBACK_BUFFER:
1822 for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1823 if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1824 struct gl_transform_feedback_buffer *buffer =
1825 (struct gl_transform_feedback_buffer *)
1826 shProg->data->ProgramResourceList[i].Data;
1827 *params = MAX2((unsigned)*params, buffer->NumVaryings);
1828 }
1829 }
1830 break;
1831 default:
1832 _mesa_error(ctx, GL_INVALID_OPERATION,
1833 "glGetProgramInterfaceiv(%s pname %s)",
1834 _mesa_enum_to_string(programInterface),
1835 _mesa_enum_to_string(pname));
1836 }
1837 break;
1838 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
1839 switch (programInterface) {
1840 case GL_VERTEX_SUBROUTINE_UNIFORM:
1841 case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1842 case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1843 case GL_COMPUTE_SUBROUTINE_UNIFORM:
1844 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1845 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
1846 for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
1847 if (shProg->data->ProgramResourceList[i].Type == programInterface) {
1848 struct gl_uniform_storage *uni =
1849 (struct gl_uniform_storage *)
1850 shProg->data->ProgramResourceList[i].Data;
1851 *params = MAX2((unsigned)*params, uni->num_compatible_subroutines);
1852 }
1853 }
1854 break;
1855 }
1856
1857 default:
1858 _mesa_error(ctx, GL_INVALID_OPERATION,
1859 "glGetProgramInterfaceiv(%s pname %s)",
1860 _mesa_enum_to_string(programInterface),
1861 _mesa_enum_to_string(pname));
1862 }
1863 break;
1864 default:
1865 _mesa_error(ctx, GL_INVALID_OPERATION,
1866 "glGetProgramInterfaceiv(pname %s)",
1867 _mesa_enum_to_string(pname));
1868 }
1869 }
1870
1871 static bool
validate_io(struct gl_program * producer,struct gl_program * consumer)1872 validate_io(struct gl_program *producer, struct gl_program *consumer)
1873 {
1874 if (producer->sh.data->linked_stages == consumer->sh.data->linked_stages)
1875 return true;
1876
1877 const bool producer_is_array_stage =
1878 producer->info.stage == MESA_SHADER_TESS_CTRL;
1879 const bool consumer_is_array_stage =
1880 consumer->info.stage == MESA_SHADER_GEOMETRY ||
1881 consumer->info.stage == MESA_SHADER_TESS_CTRL ||
1882 consumer->info.stage == MESA_SHADER_TESS_EVAL;
1883
1884 bool valid = true;
1885
1886 gl_shader_variable const **outputs =
1887 (gl_shader_variable const **) calloc(producer->sh.data->NumProgramResourceList,
1888 sizeof(gl_shader_variable *));
1889 if (outputs == NULL)
1890 return false;
1891
1892 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1893 * says:
1894 *
1895 * At an interface between program objects, the set of inputs and
1896 * outputs are considered to match exactly if and only if:
1897 *
1898 * - Every declared input variable has a matching output, as described
1899 * above.
1900 * - There are no user-defined output variables declared without a
1901 * matching input variable declaration.
1902 *
1903 * Every input has an output, and every output has an input. Scan the list
1904 * of producer resources once, and generate the list of outputs. As inputs
1905 * and outputs are matched, remove the matched outputs from the set. At
1906 * the end, the set must be empty. If the set is not empty, then there is
1907 * some output that did not have an input.
1908 */
1909 unsigned num_outputs = 0;
1910 for (unsigned i = 0; i < producer->sh.data->NumProgramResourceList; i++) {
1911 struct gl_program_resource *res =
1912 &producer->sh.data->ProgramResourceList[i];
1913
1914 if (res->Type != GL_PROGRAM_OUTPUT)
1915 continue;
1916
1917 gl_shader_variable const *const var = RESOURCE_VAR(res);
1918
1919 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1920 * says:
1921 *
1922 * Built-in inputs or outputs do not affect interface matching.
1923 */
1924 if (is_gl_identifier(var->name.string))
1925 continue;
1926
1927 outputs[num_outputs++] = var;
1928 }
1929
1930 unsigned match_index = 0;
1931 for (unsigned i = 0; i < consumer->sh.data->NumProgramResourceList; i++) {
1932 struct gl_program_resource *res =
1933 &consumer->sh.data->ProgramResourceList[i];
1934
1935 if (res->Type != GL_PROGRAM_INPUT)
1936 continue;
1937
1938 gl_shader_variable const *const consumer_var = RESOURCE_VAR(res);
1939 gl_shader_variable const *producer_var = NULL;
1940
1941 if (is_gl_identifier(consumer_var->name.string))
1942 continue;
1943
1944 /* Inputs with explicit locations match other outputs with explicit
1945 * locations by location instead of by name.
1946 */
1947 if (consumer_var->explicit_location) {
1948 for (unsigned j = 0; j < num_outputs; j++) {
1949 const gl_shader_variable *const var = outputs[j];
1950
1951 if (var->explicit_location &&
1952 consumer_var->location == var->location) {
1953 producer_var = var;
1954 match_index = j;
1955 break;
1956 }
1957 }
1958 } else {
1959 for (unsigned j = 0; j < num_outputs; j++) {
1960 const gl_shader_variable *const var = outputs[j];
1961
1962 if (!var->explicit_location &&
1963 strcmp(consumer_var->name.string, var->name.string) == 0) {
1964 producer_var = var;
1965 match_index = j;
1966 break;
1967 }
1968 }
1969 }
1970
1971 /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1972 * says:
1973 *
1974 * - An output variable is considered to match an input variable in
1975 * the subsequent shader if:
1976 *
1977 * - the two variables match in name, type, and qualification; or
1978 *
1979 * - the two variables are declared with the same location
1980 * qualifier and match in type and qualification.
1981 */
1982 if (producer_var == NULL) {
1983 valid = false;
1984 goto out;
1985 }
1986
1987 /* An output cannot match more than one input, so remove the output from
1988 * the set of possible outputs.
1989 */
1990 outputs[match_index] = NULL;
1991 num_outputs--;
1992 if (match_index < num_outputs)
1993 outputs[match_index] = outputs[num_outputs];
1994
1995 /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says:
1996 *
1997 * "Tessellation control shader per-vertex output variables and
1998 * blocks and tessellation control, tessellation evaluation, and
1999 * geometry shader per-vertex input variables and blocks are
2000 * required to be declared as arrays, with each element representing
2001 * input or output values for a single vertex of a multi-vertex
2002 * primitive. For the purposes of interface matching, such variables
2003 * and blocks are treated as though they were not declared as
2004 * arrays."
2005 *
2006 * So we unwrap those types before matching.
2007 */
2008 const glsl_type *consumer_type = consumer_var->type;
2009 const glsl_type *consumer_interface_type = consumer_var->interface_type;
2010 const glsl_type *producer_type = producer_var->type;
2011 const glsl_type *producer_interface_type = producer_var->interface_type;
2012
2013 if (consumer_is_array_stage) {
2014 if (consumer_interface_type) {
2015 /* the interface is the array; the underlying types should match */
2016 if (consumer_interface_type->is_array() && !consumer_var->patch)
2017 consumer_interface_type = consumer_interface_type->fields.array;
2018 } else {
2019 if (consumer_type->is_array() && !consumer_var->patch)
2020 consumer_type = consumer_type->fields.array;
2021 }
2022 }
2023
2024 if (producer_is_array_stage) {
2025 if (producer_interface_type) {
2026 /* the interface is the array; the underlying types should match */
2027 if (producer_interface_type->is_array() && !producer_var->patch)
2028 producer_interface_type = producer_interface_type->fields.array;
2029 } else {
2030 if (producer_type->is_array() && !producer_var->patch)
2031 producer_type = producer_type->fields.array;
2032 }
2033 }
2034
2035 if (producer_type != consumer_type) {
2036 valid = false;
2037 goto out;
2038 }
2039
2040 if (producer_interface_type != consumer_interface_type) {
2041 valid = false;
2042 goto out;
2043 }
2044
2045 /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
2046 *
2047 * Qualifier Class| Qualifier |in/out
2048 * ---------------+-------------+------
2049 * Storage | in |
2050 * | out | N/A
2051 * | uniform |
2052 * ---------------+-------------+------
2053 * Auxiliary | centroid | No
2054 * ---------------+-------------+------
2055 * | location | Yes
2056 * | Block layout| N/A
2057 * | binding | N/A
2058 * | offset | N/A
2059 * | format | N/A
2060 * ---------------+-------------+------
2061 * Interpolation | smooth |
2062 * | flat | Yes
2063 * ---------------+-------------+------
2064 * | lowp |
2065 * Precision | mediump | Yes
2066 * | highp |
2067 * ---------------+-------------+------
2068 * Variance | invariant | No
2069 * ---------------+-------------+------
2070 * Memory | all | N/A
2071 *
2072 * Note that location mismatches are detected by the loops above that
2073 * find the producer variable that goes with the consumer variable.
2074 */
2075 unsigned producer_interpolation = producer_var->interpolation;
2076 unsigned consumer_interpolation = consumer_var->interpolation;
2077 if (producer_interpolation == INTERP_MODE_NONE)
2078 producer_interpolation = INTERP_MODE_SMOOTH;
2079 if (consumer_interpolation == INTERP_MODE_NONE)
2080 consumer_interpolation = INTERP_MODE_SMOOTH;
2081 if (producer_interpolation != consumer_interpolation) {
2082 valid = false;
2083 goto out;
2084 }
2085
2086 if (producer_var->precision != consumer_var->precision) {
2087 valid = false;
2088 goto out;
2089 }
2090
2091 if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
2092 valid = false;
2093 goto out;
2094 }
2095 }
2096
2097 out:
2098 free(outputs);
2099 return valid && num_outputs == 0;
2100 }
2101
2102 /**
2103 * Validate inputs against outputs in a program pipeline.
2104 */
2105 extern "C" bool
_mesa_validate_pipeline_io(struct gl_pipeline_object * pipeline)2106 _mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
2107 {
2108 struct gl_program **prog = (struct gl_program **) pipeline->CurrentProgram;
2109
2110 /* Find first active stage in pipeline. */
2111 unsigned idx, prev = 0;
2112 for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
2113 if (prog[idx]) {
2114 prev = idx;
2115 break;
2116 }
2117 }
2118
2119 for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
2120 if (prog[idx]) {
2121 /* Pipeline might include both non-compute and a compute program, do
2122 * not attempt to validate varyings between non-compute and compute
2123 * stage.
2124 */
2125 if (prog[idx]->info.stage == MESA_SHADER_COMPUTE)
2126 break;
2127
2128 if (!validate_io(prog[prev], prog[idx]))
2129 return false;
2130
2131 prev = idx;
2132 }
2133 }
2134 return true;
2135 }
2136
2137 extern "C" void
_mesa_program_resource_hash_destroy(struct gl_shader_program * shProg)2138 _mesa_program_resource_hash_destroy(struct gl_shader_program *shProg)
2139 {
2140 for (unsigned i = 0; i < ARRAY_SIZE(shProg->data->ProgramResourceHash); i++) {
2141 if (shProg->data->ProgramResourceHash[i]) {
2142 _mesa_hash_table_destroy(shProg->data->ProgramResourceHash[i], NULL);
2143 shProg->data->ProgramResourceHash[i] = NULL;
2144 }
2145 }
2146 }
2147
2148 extern "C" void
_mesa_create_program_resource_hash(struct gl_shader_program * shProg)2149 _mesa_create_program_resource_hash(struct gl_shader_program *shProg)
2150 {
2151 /* Rebuild resource hash. */
2152 _mesa_program_resource_hash_destroy(shProg);
2153
2154 struct gl_program_resource *res = shProg->data->ProgramResourceList;
2155 for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
2156 struct gl_resource_name name;
2157 if (_mesa_program_get_resource_name(res, &name)) {
2158 unsigned type = GET_PROGRAM_RESOURCE_TYPE_FROM_GLENUM(res->Type);
2159 assert(type < ARRAY_SIZE(shProg->data->ProgramResourceHash));
2160
2161 if (!shProg->data->ProgramResourceHash[type]) {
2162 shProg->data->ProgramResourceHash[type] =
2163 _mesa_hash_table_create(shProg, _mesa_hash_string,
2164 _mesa_key_string_equal);
2165 }
2166
2167 _mesa_hash_table_insert(shProg->data->ProgramResourceHash[type],
2168 name.string, res);
2169 }
2170 }
2171 }
2172