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