• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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