• 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/core.h"
33 #include "main/enums.h"
34 #include "main/shaderapi.h"
35 #include "main/shaderobj.h"
36 #include "main/uniforms.h"
37 #include "compiler/glsl/glsl_symbol_table.h"
38 #include "compiler/glsl/ir.h"
39 #include "compiler/glsl/program.h"
40 #include "util/string_to_uint_map.h"
41 #include "util/strndup.h"
42 
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 void GLAPIENTRY
_mesa_BindAttribLocation(GLuint program,GLuint index,const GLchar * name)67 _mesa_BindAttribLocation(GLuint program, GLuint index,
68                          const GLchar *name)
69 {
70    GET_CURRENT_CONTEXT(ctx);
71 
72    struct gl_shader_program *const shProg =
73       _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
74    if (!shProg)
75       return;
76 
77    if (!name)
78       return;
79 
80    if (strncmp(name, "gl_", 3) == 0) {
81       _mesa_error(ctx, GL_INVALID_OPERATION,
82                   "glBindAttribLocation(illegal name)");
83       return;
84    }
85 
86    if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
87       _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(%u >= %u)",
88                   index, ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs);
89       return;
90    }
91 
92    /* Replace the current value if it's already in the list.  Add
93     * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
94     * between built-in attributes and user-defined attributes.
95     */
96    shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
97 
98    /*
99     * Note that this attribute binding won't go into effect until
100     * glLinkProgram is called again.
101     */
102 }
103 
104 void GLAPIENTRY
_mesa_GetActiveAttrib(GLuint program,GLuint desired_index,GLsizei maxLength,GLsizei * length,GLint * size,GLenum * type,GLchar * name)105 _mesa_GetActiveAttrib(GLuint program, GLuint desired_index,
106                       GLsizei maxLength, GLsizei * length, GLint * size,
107                       GLenum * type, GLchar * name)
108 {
109    GET_CURRENT_CONTEXT(ctx);
110    struct gl_shader_program *shProg;
111 
112    if (maxLength < 0) {
113       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
114       return;
115    }
116 
117    shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
118    if (!shProg)
119       return;
120 
121    if (!shProg->data->LinkStatus) {
122       _mesa_error(ctx, GL_INVALID_VALUE,
123                   "glGetActiveAttrib(program not linked)");
124       return;
125    }
126 
127    if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
128       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
129       return;
130    }
131 
132    struct gl_program_resource *res =
133       _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
134                                         desired_index);
135 
136    /* User asked for index that does not exist. */
137    if (!res) {
138       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
139       return;
140    }
141 
142    const gl_shader_variable *const var = RESOURCE_VAR(res);
143 
144    const char *var_name = var->name;
145 
146    _mesa_copy_string(name, maxLength, length, var_name);
147 
148    if (size)
149       _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
150                                   size, "glGetActiveAttrib");
151 
152    if (type)
153       _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
154                                   (GLint *) type, "glGetActiveAttrib");
155 }
156 
157 GLint GLAPIENTRY
_mesa_GetAttribLocation(GLuint program,const GLchar * name)158 _mesa_GetAttribLocation(GLuint program, const GLchar * name)
159 {
160    GET_CURRENT_CONTEXT(ctx);
161    struct gl_shader_program *const shProg =
162       _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
163 
164    if (!shProg) {
165       return -1;
166    }
167 
168    if (!shProg->data->LinkStatus) {
169       _mesa_error(ctx, GL_INVALID_OPERATION,
170                   "glGetAttribLocation(program not linked)");
171       return -1;
172    }
173 
174    if (!name)
175       return -1;
176 
177    /* Not having a vertex shader is not an error.
178     */
179    if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
180       return -1;
181 
182    unsigned array_index = 0;
183    struct gl_program_resource *res =
184       _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name,
185                                        &array_index);
186 
187    if (!res)
188       return -1;
189 
190    return program_resource_location(res, array_index);
191 }
192 
193 unsigned
_mesa_count_active_attribs(struct gl_shader_program * shProg)194 _mesa_count_active_attribs(struct gl_shader_program *shProg)
195 {
196    if (!shProg->data->LinkStatus
197        || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
198       return 0;
199    }
200 
201    struct gl_program_resource *res = shProg->ProgramResourceList;
202    unsigned count = 0;
203    for (unsigned j = 0; j < shProg->NumProgramResourceList; j++, res++) {
204       if (res->Type == GL_PROGRAM_INPUT &&
205           res->StageReferences & (1 << MESA_SHADER_VERTEX))
206          count++;
207    }
208    return count;
209 }
210 
211 
212 size_t
_mesa_longest_attribute_name_length(struct gl_shader_program * shProg)213 _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
214 {
215    if (!shProg->data->LinkStatus
216        || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
217       return 0;
218    }
219 
220    struct gl_program_resource *res = shProg->ProgramResourceList;
221    size_t longest = 0;
222    for (unsigned j = 0; j < shProg->NumProgramResourceList; j++, res++) {
223       if (res->Type == GL_PROGRAM_INPUT &&
224           res->StageReferences & (1 << MESA_SHADER_VERTEX)) {
225 
226           const size_t length = strlen(RESOURCE_VAR(res)->name);
227           if (length >= longest)
228              longest = length + 1;
229       }
230    }
231 
232    return longest;
233 }
234 
235 void GLAPIENTRY
_mesa_BindFragDataLocation(GLuint program,GLuint colorNumber,const GLchar * name)236 _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
237 			   const GLchar *name)
238 {
239    _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
240 }
241 
242 void GLAPIENTRY
_mesa_BindFragDataLocationIndexed(GLuint program,GLuint colorNumber,GLuint index,const GLchar * name)243 _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
244                                   GLuint index, const GLchar *name)
245 {
246    GET_CURRENT_CONTEXT(ctx);
247 
248    struct gl_shader_program *const shProg =
249       _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
250    if (!shProg)
251       return;
252 
253    if (!name)
254       return;
255 
256    if (strncmp(name, "gl_", 3) == 0) {
257       _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
258       return;
259    }
260 
261    if (index > 1) {
262       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
263       return;
264    }
265 
266    if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
267       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
268       return;
269    }
270 
271    if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
272       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
273       return;
274    }
275 
276    /* Replace the current value if it's already in the list.  Add
277     * FRAG_RESULT_DATA0 because that's how the linker differentiates
278     * between built-in attributes and user-defined attributes.
279     */
280    shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
281    shProg->FragDataIndexBindings->put(index, name);
282    /*
283     * Note that this binding won't go into effect until
284     * glLinkProgram is called again.
285     */
286 
287 }
288 
289 GLint GLAPIENTRY
_mesa_GetFragDataIndex(GLuint program,const GLchar * name)290 _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
291 {
292    GET_CURRENT_CONTEXT(ctx);
293    struct gl_shader_program *const shProg =
294       _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
295 
296    if (!shProg) {
297       return -1;
298    }
299 
300    if (!shProg->data->LinkStatus) {
301       _mesa_error(ctx, GL_INVALID_OPERATION,
302                   "glGetFragDataIndex(program not linked)");
303       return -1;
304    }
305 
306    if (!name)
307       return -1;
308 
309    if (strncmp(name, "gl_", 3) == 0) {
310       _mesa_error(ctx, GL_INVALID_OPERATION,
311                   "glGetFragDataIndex(illegal name)");
312       return -1;
313    }
314 
315    /* Not having a fragment shader is not an error.
316     */
317    if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
318       return -1;
319 
320    return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
321                                                 name);
322 }
323 
324 GLint GLAPIENTRY
_mesa_GetFragDataLocation(GLuint program,const GLchar * name)325 _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
326 {
327    GET_CURRENT_CONTEXT(ctx);
328    struct gl_shader_program *const shProg =
329       _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
330 
331    if (!shProg) {
332       return -1;
333    }
334 
335    if (!shProg->data->LinkStatus) {
336       _mesa_error(ctx, GL_INVALID_OPERATION,
337                   "glGetFragDataLocation(program not linked)");
338       return -1;
339    }
340 
341    if (!name)
342       return -1;
343 
344    if (strncmp(name, "gl_", 3) == 0) {
345       _mesa_error(ctx, GL_INVALID_OPERATION,
346                   "glGetFragDataLocation(illegal name)");
347       return -1;
348    }
349 
350    /* Not having a fragment shader is not an error.
351     */
352    if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
353       return -1;
354 
355    unsigned array_index = 0;
356    struct gl_program_resource *res =
357       _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name,
358                                        &array_index);
359 
360    if (!res)
361       return -1;
362 
363    return program_resource_location(res, array_index);
364 }
365 
366 const char*
_mesa_program_resource_name(struct gl_program_resource * res)367 _mesa_program_resource_name(struct gl_program_resource *res)
368 {
369    switch (res->Type) {
370    case GL_UNIFORM_BLOCK:
371    case GL_SHADER_STORAGE_BLOCK:
372       return RESOURCE_UBO(res)->Name;
373    case GL_TRANSFORM_FEEDBACK_VARYING:
374       return RESOURCE_XFV(res)->Name;
375    case GL_PROGRAM_INPUT:
376    case GL_PROGRAM_OUTPUT:
377       return RESOURCE_VAR(res)->name;
378    case GL_UNIFORM:
379    case GL_BUFFER_VARIABLE:
380       return RESOURCE_UNI(res)->name;
381    case GL_VERTEX_SUBROUTINE_UNIFORM:
382    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
383    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
384    case GL_COMPUTE_SUBROUTINE_UNIFORM:
385    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
386    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
387       return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN;
388    case GL_VERTEX_SUBROUTINE:
389    case GL_GEOMETRY_SUBROUTINE:
390    case GL_FRAGMENT_SUBROUTINE:
391    case GL_COMPUTE_SUBROUTINE:
392    case GL_TESS_CONTROL_SUBROUTINE:
393    case GL_TESS_EVALUATION_SUBROUTINE:
394       return RESOURCE_SUB(res)->name;
395    default:
396       assert(!"support for resource type not implemented");
397    }
398    return NULL;
399 }
400 
401 
402 unsigned
_mesa_program_resource_array_size(struct gl_program_resource * res)403 _mesa_program_resource_array_size(struct gl_program_resource *res)
404 {
405    switch (res->Type) {
406    case GL_TRANSFORM_FEEDBACK_VARYING:
407       return RESOURCE_XFV(res)->Size > 1 ?
408              RESOURCE_XFV(res)->Size : 0;
409    case GL_PROGRAM_INPUT:
410    case GL_PROGRAM_OUTPUT:
411       return RESOURCE_VAR(res)->type->length;
412    case GL_UNIFORM:
413    case GL_VERTEX_SUBROUTINE_UNIFORM:
414    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
415    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
416    case GL_COMPUTE_SUBROUTINE_UNIFORM:
417    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
418    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
419       return RESOURCE_UNI(res)->array_elements;
420    case GL_BUFFER_VARIABLE:
421       /* Unsized arrays */
422       if (RESOURCE_UNI(res)->array_stride > 0 &&
423           RESOURCE_UNI(res)->array_elements == 0)
424          return 1;
425       else
426          return RESOURCE_UNI(res)->array_elements;
427    case GL_VERTEX_SUBROUTINE:
428    case GL_GEOMETRY_SUBROUTINE:
429    case GL_FRAGMENT_SUBROUTINE:
430    case GL_COMPUTE_SUBROUTINE:
431    case GL_TESS_CONTROL_SUBROUTINE:
432    case GL_TESS_EVALUATION_SUBROUTINE:
433    case GL_ATOMIC_COUNTER_BUFFER:
434    case GL_UNIFORM_BLOCK:
435    case GL_SHADER_STORAGE_BLOCK:
436       return 0;
437    default:
438       assert(!"support for resource type not implemented");
439    }
440    return 0;
441 }
442 
443 /**
444  * Checks if array subscript is valid and if so sets array_index.
445  */
446 static bool
valid_array_index(const GLchar * name,unsigned * array_index)447 valid_array_index(const GLchar *name, unsigned *array_index)
448 {
449    long idx = 0;
450    const GLchar *out_base_name_end;
451 
452    idx = parse_program_resource_name(name, &out_base_name_end);
453    if (idx < 0)
454       return false;
455 
456    if (array_index)
457       *array_index = idx;
458 
459    return true;
460 }
461 
462 /* Find a program resource with specific name in given interface.
463  */
464 struct gl_program_resource *
_mesa_program_resource_find_name(struct gl_shader_program * shProg,GLenum programInterface,const char * name,unsigned * array_index)465 _mesa_program_resource_find_name(struct gl_shader_program *shProg,
466                                  GLenum programInterface, const char *name,
467                                  unsigned *array_index)
468 {
469    struct gl_program_resource *res = shProg->ProgramResourceList;
470    for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
471       if (res->Type != programInterface)
472          continue;
473 
474       /* Resource basename. */
475       const char *rname = _mesa_program_resource_name(res);
476       unsigned baselen = strlen(rname);
477       unsigned baselen_without_array_index = baselen;
478       const char *rname_last_square_bracket = strrchr(rname, '[');
479       bool found = false;
480       bool rname_has_array_index_zero = false;
481       /* From ARB_program_interface_query spec:
482        *
483        * "uint GetProgramResourceIndex(uint program, enum programInterface,
484        *                               const char *name);
485        *  [...]
486        *  If <name> exactly matches the name string of one of the active
487        *  resources for <programInterface>, the index of the matched resource is
488        *  returned. Additionally, if <name> would exactly match the name string
489        *  of an active resource if "[0]" were appended to <name>, the index of
490        *  the matched resource is returned. [...]"
491        *
492        * "A string provided to GetProgramResourceLocation or
493        * GetProgramResourceLocationIndex is considered to match an active variable
494        * if:
495        *
496        *  * the string exactly matches the name of the active variable;
497        *
498        *  * if the string identifies the base name of an active array, where the
499        *    string would exactly match the name of the variable if the suffix
500        *    "[0]" were appended to the string; [...]"
501        */
502       /* Remove array's index from interface block name comparison only if
503        * array's index is zero and the resulting string length is the same
504        * than the provided name's length.
505        */
506       if (rname_last_square_bracket) {
507          baselen_without_array_index -= strlen(rname_last_square_bracket);
508          rname_has_array_index_zero =
509             (strcmp(rname_last_square_bracket, "[0]") == 0) &&
510             (baselen_without_array_index == strlen(name));
511       }
512 
513       if (strncmp(rname, name, baselen) == 0)
514          found = true;
515       else if (rname_has_array_index_zero &&
516                strncmp(rname, name, baselen_without_array_index) == 0)
517          found = true;
518 
519       if (found) {
520          switch (programInterface) {
521          case GL_UNIFORM_BLOCK:
522          case GL_SHADER_STORAGE_BLOCK:
523             /* Basename match, check if array or struct. */
524             if (rname_has_array_index_zero ||
525                 name[baselen] == '\0' ||
526                 name[baselen] == '[' ||
527                 name[baselen] == '.') {
528                return res;
529             }
530             break;
531          case GL_TRANSFORM_FEEDBACK_VARYING:
532          case GL_BUFFER_VARIABLE:
533          case GL_UNIFORM:
534          case GL_VERTEX_SUBROUTINE_UNIFORM:
535          case GL_GEOMETRY_SUBROUTINE_UNIFORM:
536          case GL_FRAGMENT_SUBROUTINE_UNIFORM:
537          case GL_COMPUTE_SUBROUTINE_UNIFORM:
538          case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
539          case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
540          case GL_VERTEX_SUBROUTINE:
541          case GL_GEOMETRY_SUBROUTINE:
542          case GL_FRAGMENT_SUBROUTINE:
543          case GL_COMPUTE_SUBROUTINE:
544          case GL_TESS_CONTROL_SUBROUTINE:
545          case GL_TESS_EVALUATION_SUBROUTINE:
546             if (name[baselen] == '.') {
547                return res;
548             }
549             /* fall-through */
550          case GL_PROGRAM_INPUT:
551          case GL_PROGRAM_OUTPUT:
552             if (name[baselen] == '\0') {
553                return res;
554             } else if (name[baselen] == '[' &&
555                 valid_array_index(name, array_index)) {
556                return res;
557             }
558             break;
559          default:
560             assert(!"not implemented for given interface");
561          }
562       }
563    }
564    return NULL;
565 }
566 
567 static GLuint
calc_resource_index(struct gl_shader_program * shProg,struct gl_program_resource * res)568 calc_resource_index(struct gl_shader_program *shProg,
569                     struct gl_program_resource *res)
570 {
571    unsigned i;
572    GLuint index = 0;
573    for (i = 0; i < shProg->NumProgramResourceList; i++) {
574       if (&shProg->ProgramResourceList[i] == res)
575          return index;
576       if (shProg->ProgramResourceList[i].Type == res->Type)
577          index++;
578    }
579    return GL_INVALID_INDEX;
580 }
581 
582 /**
583  * Calculate index for the given resource.
584  */
585 GLuint
_mesa_program_resource_index(struct gl_shader_program * shProg,struct gl_program_resource * res)586 _mesa_program_resource_index(struct gl_shader_program *shProg,
587                              struct gl_program_resource *res)
588 {
589    if (!res)
590       return GL_INVALID_INDEX;
591 
592    switch (res->Type) {
593    case GL_ATOMIC_COUNTER_BUFFER:
594       return RESOURCE_ATC(res) - shProg->data->AtomicBuffers;
595    case GL_VERTEX_SUBROUTINE:
596    case GL_GEOMETRY_SUBROUTINE:
597    case GL_FRAGMENT_SUBROUTINE:
598    case GL_COMPUTE_SUBROUTINE:
599    case GL_TESS_CONTROL_SUBROUTINE:
600    case GL_TESS_EVALUATION_SUBROUTINE:
601       return RESOURCE_SUB(res)->index;
602    case GL_UNIFORM_BLOCK:
603    case GL_SHADER_STORAGE_BLOCK:
604    case GL_TRANSFORM_FEEDBACK_BUFFER:
605    case GL_TRANSFORM_FEEDBACK_VARYING:
606    default:
607       return calc_resource_index(shProg, res);
608    }
609 }
610 
611 /**
612  * Find a program resource that points to given data.
613  */
614 static struct gl_program_resource*
program_resource_find_data(struct gl_shader_program * shProg,void * data)615 program_resource_find_data(struct gl_shader_program *shProg, void *data)
616 {
617    struct gl_program_resource *res = shProg->ProgramResourceList;
618    for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
619       if (res->Data == data)
620          return res;
621    }
622    return NULL;
623 }
624 
625 /* Find a program resource with specific index in given interface.
626  */
627 struct gl_program_resource *
_mesa_program_resource_find_index(struct gl_shader_program * shProg,GLenum programInterface,GLuint index)628 _mesa_program_resource_find_index(struct gl_shader_program *shProg,
629                                   GLenum programInterface, GLuint index)
630 {
631    struct gl_program_resource *res = shProg->ProgramResourceList;
632    int idx = -1;
633 
634    for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
635       if (res->Type != programInterface)
636          continue;
637 
638       switch (res->Type) {
639       case GL_UNIFORM_BLOCK:
640       case GL_ATOMIC_COUNTER_BUFFER:
641       case GL_SHADER_STORAGE_BLOCK:
642       case GL_TRANSFORM_FEEDBACK_BUFFER:
643          if (_mesa_program_resource_index(shProg, res) == index)
644             return res;
645          break;
646       case GL_TRANSFORM_FEEDBACK_VARYING:
647       case GL_PROGRAM_INPUT:
648       case GL_PROGRAM_OUTPUT:
649       case GL_UNIFORM:
650       case GL_VERTEX_SUBROUTINE_UNIFORM:
651       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
652       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
653       case GL_COMPUTE_SUBROUTINE_UNIFORM:
654       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
655       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
656       case GL_VERTEX_SUBROUTINE:
657       case GL_GEOMETRY_SUBROUTINE:
658       case GL_FRAGMENT_SUBROUTINE:
659       case GL_COMPUTE_SUBROUTINE:
660       case GL_TESS_CONTROL_SUBROUTINE:
661       case GL_TESS_EVALUATION_SUBROUTINE:
662       case GL_BUFFER_VARIABLE:
663          if (++idx == (int) index)
664             return res;
665          break;
666       default:
667          assert(!"not implemented for given interface");
668       }
669    }
670    return NULL;
671 }
672 
673 /* Function returns if resource name is expected to have index
674  * appended into it.
675  *
676  *
677  * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
678  * spec says:
679  *
680  *     "If the active uniform is an array, the uniform name returned in
681  *     name will always be the name of the uniform array appended with
682  *     "[0]"."
683  *
684  * The same text also appears in the OpenGL 4.2 spec.  It does not,
685  * however, appear in any previous spec.  Previous specifications are
686  * ambiguous in this regard.  However, either name can later be passed
687  * to glGetUniformLocation (and related APIs), so there shouldn't be any
688  * harm in always appending "[0]" to uniform array names.
689  */
690 static bool
add_index_to_name(struct gl_program_resource * res)691 add_index_to_name(struct gl_program_resource *res)
692 {
693    /* Transform feedback varyings have array index already appended
694     * in their names.
695     */
696    return res->Type != GL_TRANSFORM_FEEDBACK_VARYING;
697 }
698 
699 /* Get name length of a program resource. This consists of
700  * base name + 3 for '[0]' if resource is an array.
701  */
702 extern unsigned
_mesa_program_resource_name_len(struct gl_program_resource * res)703 _mesa_program_resource_name_len(struct gl_program_resource *res)
704 {
705    unsigned length = strlen(_mesa_program_resource_name(res));
706    if (_mesa_program_resource_array_size(res) && add_index_to_name(res))
707       length += 3;
708    return length;
709 }
710 
711 /* Get full name of a program resource.
712  */
713 bool
_mesa_get_program_resource_name(struct gl_shader_program * shProg,GLenum programInterface,GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name,const char * caller)714 _mesa_get_program_resource_name(struct gl_shader_program *shProg,
715                                 GLenum programInterface, GLuint index,
716                                 GLsizei bufSize, GLsizei *length,
717                                 GLchar *name, const char *caller)
718 {
719    GET_CURRENT_CONTEXT(ctx);
720 
721    /* Find resource with given interface and index. */
722    struct gl_program_resource *res =
723       _mesa_program_resource_find_index(shProg, programInterface, index);
724 
725    /* The error INVALID_VALUE is generated if <index> is greater than
726    * or equal to the number of entries in the active resource list for
727    * <programInterface>.
728    */
729    if (!res) {
730       _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
731       return false;
732    }
733 
734    if (bufSize < 0) {
735       _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
736       return false;
737    }
738 
739    GLsizei localLength;
740 
741    if (length == NULL)
742       length = &localLength;
743 
744    _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
745 
746    if (_mesa_program_resource_array_size(res) && add_index_to_name(res)) {
747       int i;
748 
749       /* The comparison is strange because *length does *NOT* include the
750        * terminating NUL, but maxLength does.
751        */
752       for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
753          name[*length + i] = "[0]"[i];
754 
755       name[*length + i] = '\0';
756       *length += i;
757    }
758    return true;
759 }
760 
761 static GLint
program_resource_location(struct gl_program_resource * res,unsigned array_index)762 program_resource_location(struct gl_program_resource *res, unsigned array_index)
763 {
764    switch (res->Type) {
765    case GL_PROGRAM_INPUT: {
766       const gl_shader_variable *var = RESOURCE_VAR(res);
767 
768       if (var->location == -1)
769          return -1;
770 
771       /* If the input is an array, fail if the index is out of bounds. */
772       if (array_index > 0
773           && array_index >= var->type->length) {
774          return -1;
775       }
776       return var->location +
777 	     (array_index * var->type->without_array()->matrix_columns);
778    }
779    case GL_PROGRAM_OUTPUT:
780       if (RESOURCE_VAR(res)->location == -1)
781          return -1;
782 
783       /* If the output is an array, fail if the index is out of bounds. */
784       if (array_index > 0
785           && array_index >= RESOURCE_VAR(res)->type->length) {
786          return -1;
787       }
788       return RESOURCE_VAR(res)->location + array_index;
789    case GL_UNIFORM:
790       /* If the uniform is built-in, fail. */
791       if (RESOURCE_UNI(res)->builtin)
792          return -1;
793 
794      /* From page 79 of the OpenGL 4.2 spec:
795       *
796       *     "A valid name cannot be a structure, an array of structures, or any
797       *     portion of a single vector or a matrix."
798       */
799       if (RESOURCE_UNI(res)->type->without_array()->is_record())
800          return -1;
801 
802       /* From the GL_ARB_uniform_buffer_object spec:
803        *
804        *     "The value -1 will be returned if <name> does not correspond to an
805        *     active uniform variable name in <program>, if <name> is associated
806        *     with a named uniform block, or if <name> starts with the reserved
807        *     prefix "gl_"."
808        */
809       if (RESOURCE_UNI(res)->block_index != -1 ||
810           RESOURCE_UNI(res)->atomic_buffer_index != -1)
811          return -1;
812 
813       /* fallthrough */
814    case GL_VERTEX_SUBROUTINE_UNIFORM:
815    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
816    case GL_FRAGMENT_SUBROUTINE_UNIFORM:
817    case GL_COMPUTE_SUBROUTINE_UNIFORM:
818    case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
819    case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
820       /* If the uniform is an array, fail if the index is out of bounds. */
821       if (array_index > 0
822           && array_index >= RESOURCE_UNI(res)->array_elements) {
823          return -1;
824       }
825 
826       /* location in remap table + array element offset */
827       return RESOURCE_UNI(res)->remap_location + array_index;
828    default:
829       return -1;
830    }
831 }
832 
833 /**
834  * Function implements following location queries:
835  *    glGetUniformLocation
836  */
837 GLint
_mesa_program_resource_location(struct gl_shader_program * shProg,GLenum programInterface,const char * name)838 _mesa_program_resource_location(struct gl_shader_program *shProg,
839                                 GLenum programInterface, const char *name)
840 {
841    unsigned array_index = 0;
842    struct gl_program_resource *res =
843       _mesa_program_resource_find_name(shProg, programInterface, name,
844                                        &array_index);
845 
846    /* Resource not found. */
847    if (!res)
848       return -1;
849 
850    return program_resource_location(res, array_index);
851 }
852 
853 /**
854  * Function implements following index queries:
855  *    glGetFragDataIndex
856  */
857 GLint
_mesa_program_resource_location_index(struct gl_shader_program * shProg,GLenum programInterface,const char * name)858 _mesa_program_resource_location_index(struct gl_shader_program *shProg,
859                                       GLenum programInterface, const char *name)
860 {
861    struct gl_program_resource *res =
862       _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
863 
864    /* Non-existent variable or resource is not referenced by fragment stage. */
865    if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
866       return -1;
867 
868    /* From OpenGL 4.5 spec, 7.3 Program Objects
869     * "The value -1 will be returned by either command...
870     *  ... or if name identifies an active variable that does not have a
871     * valid location assigned.
872     */
873    if (RESOURCE_VAR(res)->location == -1)
874       return -1;
875    return RESOURCE_VAR(res)->index;
876 }
877 
878 static uint8_t
stage_from_enum(GLenum ref)879 stage_from_enum(GLenum ref)
880 {
881    switch (ref) {
882    case GL_REFERENCED_BY_VERTEX_SHADER:
883       return MESA_SHADER_VERTEX;
884    case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
885       return MESA_SHADER_TESS_CTRL;
886    case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
887       return MESA_SHADER_TESS_EVAL;
888    case GL_REFERENCED_BY_GEOMETRY_SHADER:
889       return MESA_SHADER_GEOMETRY;
890    case GL_REFERENCED_BY_FRAGMENT_SHADER:
891       return MESA_SHADER_FRAGMENT;
892    case GL_REFERENCED_BY_COMPUTE_SHADER:
893       return MESA_SHADER_COMPUTE;
894    default:
895       assert(!"shader stage not supported");
896       return MESA_SHADER_STAGES;
897    }
898 }
899 
900 /**
901  * Check if resource is referenced by given 'referenced by' stage enum.
902  * ATC and UBO resources hold stage references of their own.
903  */
904 static bool
is_resource_referenced(struct gl_shader_program * shProg,struct gl_program_resource * res,GLuint index,uint8_t stage)905 is_resource_referenced(struct gl_shader_program *shProg,
906                        struct gl_program_resource *res,
907                        GLuint index, uint8_t stage)
908 {
909    /* First, check if we even have such a stage active. */
910    if (!shProg->_LinkedShaders[stage])
911       return false;
912 
913    if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
914       return RESOURCE_ATC(res)->StageReferences[stage];
915 
916    if (res->Type == GL_UNIFORM_BLOCK)
917       return shProg->data->UniformBlocks[index].stageref & (1 << stage);
918 
919    if (res->Type == GL_SHADER_STORAGE_BLOCK)
920       return shProg->data->ShaderStorageBlocks[index].stageref & (1 << stage);
921 
922    return res->StageReferences & (1 << stage);
923 }
924 
925 static unsigned
get_buffer_property(struct gl_shader_program * shProg,struct gl_program_resource * res,const GLenum prop,GLint * val,const char * caller)926 get_buffer_property(struct gl_shader_program *shProg,
927                     struct gl_program_resource *res, const GLenum prop,
928                     GLint *val, const char *caller)
929 {
930    GET_CURRENT_CONTEXT(ctx);
931    if (res->Type != GL_UNIFORM_BLOCK &&
932        res->Type != GL_ATOMIC_COUNTER_BUFFER &&
933        res->Type != GL_SHADER_STORAGE_BLOCK &&
934        res->Type != GL_TRANSFORM_FEEDBACK_BUFFER)
935       goto invalid_operation;
936 
937    if (res->Type == GL_UNIFORM_BLOCK) {
938       switch (prop) {
939       case GL_BUFFER_BINDING:
940          *val = RESOURCE_UBO(res)->Binding;
941          return 1;
942       case GL_BUFFER_DATA_SIZE:
943          *val = RESOURCE_UBO(res)->UniformBufferSize;
944          return 1;
945       case GL_NUM_ACTIVE_VARIABLES:
946          *val = 0;
947          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
948             const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
949             struct gl_program_resource *uni =
950                _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
951                                                 NULL);
952             if (!uni)
953                continue;
954             (*val)++;
955          }
956          return 1;
957       case GL_ACTIVE_VARIABLES: {
958          unsigned num_values = 0;
959          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
960             const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
961             struct gl_program_resource *uni =
962                _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname,
963                                                 NULL);
964             if (!uni)
965                continue;
966             *val++ =
967                _mesa_program_resource_index(shProg, uni);
968             num_values++;
969          }
970          return num_values;
971       }
972       }
973    } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
974       switch (prop) {
975       case GL_BUFFER_BINDING:
976          *val = RESOURCE_UBO(res)->Binding;
977          return 1;
978       case GL_BUFFER_DATA_SIZE:
979          *val = RESOURCE_UBO(res)->UniformBufferSize;
980          return 1;
981       case GL_NUM_ACTIVE_VARIABLES:
982          *val = 0;
983          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
984             const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
985             struct gl_program_resource *uni =
986                _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
987                                                 iname, NULL);
988             if (!uni)
989                continue;
990             (*val)++;
991          }
992          return 1;
993       case GL_ACTIVE_VARIABLES: {
994          unsigned num_values = 0;
995          for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
996             const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
997             struct gl_program_resource *uni =
998                _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
999                                                 iname, NULL);
1000             if (!uni)
1001                continue;
1002             *val++ =
1003                _mesa_program_resource_index(shProg, uni);
1004             num_values++;
1005          }
1006          return num_values;
1007       }
1008       }
1009    } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
1010       switch (prop) {
1011       case GL_BUFFER_BINDING:
1012          *val = RESOURCE_ATC(res)->Binding;
1013          return 1;
1014       case GL_BUFFER_DATA_SIZE:
1015          *val = RESOURCE_ATC(res)->MinimumSize;
1016          return 1;
1017       case GL_NUM_ACTIVE_VARIABLES:
1018          *val = RESOURCE_ATC(res)->NumUniforms;
1019          return 1;
1020       case GL_ACTIVE_VARIABLES:
1021          for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) {
1022             /* Active atomic buffer contains index to UniformStorage. Find
1023              * out gl_program_resource via data pointer and then calculate
1024              * index of that uniform.
1025              */
1026             unsigned idx = RESOURCE_ATC(res)->Uniforms[i];
1027             struct gl_program_resource *uni =
1028                program_resource_find_data(shProg,
1029                                           &shProg->data->UniformStorage[idx]);
1030             assert(uni);
1031             *val++ = _mesa_program_resource_index(shProg, uni);
1032          }
1033          return RESOURCE_ATC(res)->NumUniforms;
1034       }
1035    } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) {
1036       switch (prop) {
1037       case GL_BUFFER_BINDING:
1038          *val = RESOURCE_XFB(res)->Binding;
1039          return 1;
1040       case GL_NUM_ACTIVE_VARIABLES:
1041          *val = RESOURCE_XFB(res)->NumVaryings;
1042          return 1;
1043       case GL_ACTIVE_VARIABLES:
1044          struct gl_transform_feedback_info *linked_xfb =
1045             shProg->xfb_program->sh.LinkedTransformFeedback;
1046          for (int i = 0; i < linked_xfb->NumVarying; i++) {
1047             unsigned index = linked_xfb->Varyings[i].BufferIndex;
1048             struct gl_program_resource *buf_res =
1049                _mesa_program_resource_find_index(shProg,
1050                                                  GL_TRANSFORM_FEEDBACK_BUFFER,
1051                                                  index);
1052             assert(buf_res);
1053             if (res == buf_res) {
1054                *val++ = i;
1055             }
1056          }
1057          return RESOURCE_XFB(res)->NumVaryings;
1058       }
1059    }
1060    assert(!"support for property type not implemented");
1061 
1062 invalid_operation:
1063    _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1064                _mesa_enum_to_string(res->Type),
1065                _mesa_enum_to_string(prop));
1066 
1067    return 0;
1068 }
1069 
1070 unsigned
_mesa_program_resource_prop(struct gl_shader_program * shProg,struct gl_program_resource * res,GLuint index,const GLenum prop,GLint * val,const char * caller)1071 _mesa_program_resource_prop(struct gl_shader_program *shProg,
1072                             struct gl_program_resource *res, GLuint index,
1073                             const GLenum prop, GLint *val, const char *caller)
1074 {
1075    GET_CURRENT_CONTEXT(ctx);
1076 
1077 #define VALIDATE_TYPE(type)\
1078    if (res->Type != type)\
1079       goto invalid_operation;
1080 
1081 #define VALIDATE_TYPE_2(type1, type2)\
1082    if (res->Type != type1 && res->Type != type2)\
1083       goto invalid_operation;
1084 
1085    switch(prop) {
1086    case GL_NAME_LENGTH:
1087       switch (res->Type) {
1088       case GL_ATOMIC_COUNTER_BUFFER:
1089       case GL_TRANSFORM_FEEDBACK_BUFFER:
1090          goto invalid_operation;
1091       default:
1092          /* Resource name length + terminator. */
1093          *val = _mesa_program_resource_name_len(res) + 1;
1094       }
1095       return 1;
1096    case GL_TYPE:
1097       switch (res->Type) {
1098       case GL_UNIFORM:
1099       case GL_BUFFER_VARIABLE:
1100          *val = RESOURCE_UNI(res)->type->gl_type;
1101          return 1;
1102       case GL_PROGRAM_INPUT:
1103       case GL_PROGRAM_OUTPUT:
1104          *val = RESOURCE_VAR(res)->type->gl_type;
1105          return 1;
1106       case GL_TRANSFORM_FEEDBACK_VARYING:
1107          *val = RESOURCE_XFV(res)->Type;
1108          return 1;
1109       default:
1110          goto invalid_operation;
1111       }
1112    case GL_ARRAY_SIZE:
1113       switch (res->Type) {
1114       case GL_UNIFORM:
1115       case GL_BUFFER_VARIABLE:
1116       case GL_VERTEX_SUBROUTINE_UNIFORM:
1117       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1118       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1119       case GL_COMPUTE_SUBROUTINE_UNIFORM:
1120       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1121       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1122 
1123          /* Test if a buffer variable is an array or an unsized array.
1124           * Unsized arrays return zero as array size.
1125           */
1126          if (RESOURCE_UNI(res)->is_shader_storage &&
1127              RESOURCE_UNI(res)->array_stride > 0)
1128             *val = RESOURCE_UNI(res)->array_elements;
1129          else
1130             *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
1131          return 1;
1132       case GL_PROGRAM_INPUT:
1133       case GL_PROGRAM_OUTPUT:
1134          *val = MAX2(_mesa_program_resource_array_size(res), 1);
1135          return 1;
1136       case GL_TRANSFORM_FEEDBACK_VARYING:
1137          *val = RESOURCE_XFV(res)->Size;
1138          return 1;
1139       default:
1140          goto invalid_operation;
1141       }
1142    case GL_OFFSET:
1143       switch (res->Type) {
1144       case GL_UNIFORM:
1145       case GL_BUFFER_VARIABLE:
1146          *val = RESOURCE_UNI(res)->offset;
1147          return 1;
1148       case GL_TRANSFORM_FEEDBACK_VARYING:
1149          *val = RESOURCE_XFV(res)->Offset;
1150          return 1;
1151       default:
1152          goto invalid_operation;
1153       }
1154    case GL_BLOCK_INDEX:
1155       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1156       *val = RESOURCE_UNI(res)->block_index;
1157       return 1;
1158    case GL_ARRAY_STRIDE:
1159       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1160       *val = RESOURCE_UNI(res)->array_stride;
1161       return 1;
1162    case GL_MATRIX_STRIDE:
1163       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1164       *val = RESOURCE_UNI(res)->matrix_stride;
1165       return 1;
1166    case GL_IS_ROW_MAJOR:
1167       VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
1168       *val = RESOURCE_UNI(res)->row_major;
1169       return 1;
1170    case GL_ATOMIC_COUNTER_BUFFER_INDEX:
1171       VALIDATE_TYPE(GL_UNIFORM);
1172       *val = RESOURCE_UNI(res)->atomic_buffer_index;
1173       return 1;
1174    case GL_BUFFER_BINDING:
1175    case GL_BUFFER_DATA_SIZE:
1176    case GL_NUM_ACTIVE_VARIABLES:
1177    case GL_ACTIVE_VARIABLES:
1178       return get_buffer_property(shProg, res, prop, val, caller);
1179    case GL_REFERENCED_BY_COMPUTE_SHADER:
1180       if (!_mesa_has_compute_shaders(ctx))
1181          goto invalid_enum;
1182       /* fallthrough */
1183    case GL_REFERENCED_BY_VERTEX_SHADER:
1184    case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
1185    case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
1186    case GL_REFERENCED_BY_GEOMETRY_SHADER:
1187    case GL_REFERENCED_BY_FRAGMENT_SHADER:
1188       switch (res->Type) {
1189       case GL_UNIFORM:
1190       case GL_PROGRAM_INPUT:
1191       case GL_PROGRAM_OUTPUT:
1192       case GL_UNIFORM_BLOCK:
1193       case GL_BUFFER_VARIABLE:
1194       case GL_SHADER_STORAGE_BLOCK:
1195       case GL_ATOMIC_COUNTER_BUFFER:
1196          *val = is_resource_referenced(shProg, res, index,
1197                                        stage_from_enum(prop));
1198          return 1;
1199       default:
1200          goto invalid_operation;
1201       }
1202    case GL_LOCATION:
1203       switch (res->Type) {
1204       case GL_UNIFORM:
1205       case GL_VERTEX_SUBROUTINE_UNIFORM:
1206       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
1207       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
1208       case GL_COMPUTE_SUBROUTINE_UNIFORM:
1209       case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
1210       case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
1211       case GL_PROGRAM_INPUT:
1212       case GL_PROGRAM_OUTPUT:
1213          *val = program_resource_location(res, 0);
1214          return 1;
1215       default:
1216          goto invalid_operation;
1217       }
1218    case GL_LOCATION_COMPONENT:
1219       switch (res->Type) {
1220       case GL_PROGRAM_INPUT:
1221       case GL_PROGRAM_OUTPUT:
1222          *val = RESOURCE_VAR(res)->component;
1223          return 1;
1224       default:
1225          goto invalid_operation;
1226       }
1227    case GL_LOCATION_INDEX: {
1228       int tmp;
1229       if (res->Type != GL_PROGRAM_OUTPUT)
1230          goto invalid_operation;
1231       tmp = program_resource_location(res, 0);
1232       if (tmp == -1)
1233          *val = -1;
1234       else
1235          *val = _mesa_program_resource_location_index(shProg, res->Type,
1236                                                       RESOURCE_VAR(res)->name);
1237       return 1;
1238    }
1239    case GL_NUM_COMPATIBLE_SUBROUTINES:
1240       if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1241           res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1242           res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1243           res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1244           res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1245           res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1246          goto invalid_operation;
1247       *val = RESOURCE_UNI(res)->num_compatible_subroutines;
1248       return 1;
1249    case GL_COMPATIBLE_SUBROUTINES: {
1250       const struct gl_uniform_storage *uni;
1251       struct gl_program *p;
1252       unsigned count, i;
1253       int j;
1254 
1255       if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
1256           res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
1257           res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
1258           res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
1259           res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
1260           res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
1261          goto invalid_operation;
1262       uni = RESOURCE_UNI(res);
1263 
1264       p = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]->Program;
1265       count = 0;
1266       for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
1267          struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
1268          for (j = 0; j < fn->num_compat_types; j++) {
1269             if (fn->types[j] == uni->type) {
1270                val[count++] = i;
1271                break;
1272             }
1273          }
1274       }
1275       return count;
1276    }
1277 
1278    case GL_TOP_LEVEL_ARRAY_SIZE:
1279       VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1280       *val = RESOURCE_UNI(res)->top_level_array_size;
1281       return 1;
1282 
1283    case GL_TOP_LEVEL_ARRAY_STRIDE:
1284       VALIDATE_TYPE(GL_BUFFER_VARIABLE);
1285       *val = RESOURCE_UNI(res)->top_level_array_stride;
1286       return 1;
1287 
1288    /* GL_ARB_tessellation_shader */
1289    case GL_IS_PER_PATCH:
1290       switch (res->Type) {
1291       case GL_PROGRAM_INPUT:
1292       case GL_PROGRAM_OUTPUT:
1293          *val = RESOURCE_VAR(res)->patch;
1294          return 1;
1295       default:
1296          goto invalid_operation;
1297       }
1298 
1299    case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX:
1300       VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING);
1301       *val = RESOURCE_XFV(res)->BufferIndex;
1302       return 1;
1303    case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE:
1304       VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER);
1305       *val = RESOURCE_XFB(res)->Stride * 4;
1306       return 1;
1307 
1308    default:
1309       goto invalid_enum;
1310    }
1311 
1312 #undef VALIDATE_TYPE
1313 #undef VALIDATE_TYPE_2
1314 
1315 invalid_enum:
1316    _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
1317                _mesa_enum_to_string(res->Type),
1318                _mesa_enum_to_string(prop));
1319    return 0;
1320 
1321 invalid_operation:
1322    _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
1323                _mesa_enum_to_string(res->Type),
1324                _mesa_enum_to_string(prop));
1325    return 0;
1326 }
1327 
1328 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)1329 _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
1330                              GLenum programInterface, GLuint index, GLsizei propCount,
1331                              const GLenum *props, GLsizei bufSize,
1332                              GLsizei *length, GLint *params)
1333 {
1334    GET_CURRENT_CONTEXT(ctx);
1335    GLint *val = (GLint *) params;
1336    const GLenum *prop = props;
1337    GLsizei amount = 0;
1338 
1339    struct gl_program_resource *res =
1340       _mesa_program_resource_find_index(shProg, programInterface, index);
1341 
1342    /* No such resource found or bufSize negative. */
1343    if (!res || bufSize < 0) {
1344       _mesa_error(ctx, GL_INVALID_VALUE,
1345                   "glGetProgramResourceiv(%s index %d bufSize %d)",
1346                   _mesa_enum_to_string(programInterface), index, bufSize);
1347       return;
1348    }
1349 
1350    /* Write propCount values until error occurs or bufSize reached. */
1351    for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
1352       int props_written =
1353          _mesa_program_resource_prop(shProg, res, index, *prop, val,
1354                                      "glGetProgramResourceiv");
1355 
1356       /* Error happened. */
1357       if (props_written == 0)
1358          return;
1359 
1360       amount += props_written;
1361    }
1362 
1363    /* If <length> is not NULL, the actual number of integer values
1364     * written to <params> will be written to <length>.
1365     */
1366    if (length)
1367       *length = amount;
1368 }
1369 
1370 static bool
validate_io(struct gl_shader_program * producer,struct gl_shader_program * consumer,gl_shader_stage producer_stage,gl_shader_stage consumer_stage)1371 validate_io(struct gl_shader_program *producer,
1372             struct gl_shader_program *consumer,
1373             gl_shader_stage producer_stage,
1374             gl_shader_stage consumer_stage)
1375 {
1376    if (producer == consumer)
1377       return true;
1378 
1379    const bool nonarray_stage_to_array_stage =
1380       producer_stage != MESA_SHADER_TESS_CTRL &&
1381       (consumer_stage == MESA_SHADER_GEOMETRY ||
1382        consumer_stage == MESA_SHADER_TESS_CTRL ||
1383        consumer_stage == MESA_SHADER_TESS_EVAL);
1384 
1385    bool valid = true;
1386 
1387    gl_shader_variable const **outputs =
1388       (gl_shader_variable const **) calloc(producer->NumProgramResourceList,
1389                                            sizeof(gl_shader_variable *));
1390    if (outputs == NULL)
1391       return false;
1392 
1393    /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1394     * says:
1395     *
1396     *    At an interface between program objects, the set of inputs and
1397     *    outputs are considered to match exactly if and only if:
1398     *
1399     *    - Every declared input variable has a matching output, as described
1400     *      above.
1401     *    - There are no user-defined output variables declared without a
1402     *      matching input variable declaration.
1403     *
1404     * Every input has an output, and every output has an input.  Scan the list
1405     * of producer resources once, and generate the list of outputs.  As inputs
1406     * and outputs are matched, remove the matched outputs from the set.  At
1407     * the end, the set must be empty.  If the set is not empty, then there is
1408     * some output that did not have an input.
1409     */
1410    unsigned num_outputs = 0;
1411    for (unsigned i = 0; i < producer->NumProgramResourceList; i++) {
1412       struct gl_program_resource *res = &producer->ProgramResourceList[i];
1413 
1414       if (res->Type != GL_PROGRAM_OUTPUT)
1415          continue;
1416 
1417       gl_shader_variable const *const var = RESOURCE_VAR(res);
1418 
1419       /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1420        * says:
1421        *
1422        *    Built-in inputs or outputs do not affect interface matching.
1423        */
1424       if (is_gl_identifier(var->name))
1425          continue;
1426 
1427       outputs[num_outputs++] = var;
1428    }
1429 
1430    unsigned match_index = 0;
1431    for (unsigned i = 0; i < consumer->NumProgramResourceList; i++) {
1432       struct gl_program_resource *res = &consumer->ProgramResourceList[i];
1433 
1434       if (res->Type != GL_PROGRAM_INPUT)
1435          continue;
1436 
1437       gl_shader_variable const *const consumer_var = RESOURCE_VAR(res);
1438       gl_shader_variable const *producer_var = NULL;
1439 
1440       if (is_gl_identifier(consumer_var->name))
1441          continue;
1442 
1443       /* Inputs with explicit locations match other outputs with explicit
1444        * locations by location instead of by name.
1445        */
1446       if (consumer_var->explicit_location) {
1447          for (unsigned j = 0; j < num_outputs; j++) {
1448             const gl_shader_variable *const var = outputs[j];
1449 
1450             if (var->explicit_location &&
1451                 consumer_var->location == var->location) {
1452                producer_var = var;
1453                match_index = j;
1454                break;
1455             }
1456          }
1457       } else {
1458          for (unsigned j = 0; j < num_outputs; j++) {
1459             const gl_shader_variable *const var = outputs[j];
1460 
1461             if (!var->explicit_location &&
1462                 strcmp(consumer_var->name, var->name) == 0) {
1463                producer_var = var;
1464                match_index = j;
1465                break;
1466             }
1467          }
1468       }
1469 
1470       /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
1471        * says:
1472        *
1473        *    - An output variable is considered to match an input variable in
1474        *      the subsequent shader if:
1475        *
1476        *      - the two variables match in name, type, and qualification; or
1477        *
1478        *      - the two variables are declared with the same location
1479        *        qualifier and match in type and qualification.
1480        */
1481       if (producer_var == NULL) {
1482          valid = false;
1483          goto out;
1484       }
1485 
1486       /* An output cannot match more than one input, so remove the output from
1487        * the set of possible outputs.
1488        */
1489       outputs[match_index] = NULL;
1490       num_outputs--;
1491       if (match_index < num_outputs)
1492          outputs[match_index] = outputs[num_outputs];
1493 
1494       /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
1495        *
1496        *    Qualifier Class|  Qualifier  |in/out
1497        *    ---------------+-------------+------
1498        *    Storage        |     in      |
1499        *                   |     out     |  N/A
1500        *                   |   uniform   |
1501        *    ---------------+-------------+------
1502        *    Auxiliary      |   centroid  |   No
1503        *    ---------------+-------------+------
1504        *                   |   location  |  Yes
1505        *                   | Block layout|  N/A
1506        *                   |   binding   |  N/A
1507        *                   |   offset    |  N/A
1508        *                   |   format    |  N/A
1509        *    ---------------+-------------+------
1510        *    Interpolation  |   smooth    |
1511        *                   |    flat     |  Yes
1512        *    ---------------+-------------+------
1513        *                   |    lowp     |
1514        *    Precision      |   mediump   |  Yes
1515        *                   |    highp    |
1516        *    ---------------+-------------+------
1517        *    Variance       |  invariant  |   No
1518        *    ---------------+-------------+------
1519        *    Memory         |     all     |  N/A
1520        *
1521        * Note that location mismatches are detected by the loops above that
1522        * find the producer variable that goes with the consumer variable.
1523        */
1524       if (nonarray_stage_to_array_stage) {
1525          if (consumer_var->interface_type != NULL) {
1526             /* the interface is the array; underlying types should match */
1527             if (producer_var->type != consumer_var->type) {
1528                valid = false;
1529                goto out;
1530             }
1531 
1532             if (!consumer_var->interface_type->is_array() ||
1533                 consumer_var->interface_type->fields.array != producer_var->interface_type) {
1534                valid = false;
1535                goto out;
1536             }
1537          } else {
1538             if (producer_var->interface_type != NULL) {
1539                valid = false;
1540                goto out;
1541             }
1542 
1543             if (!consumer_var->type->is_array() ||
1544                 consumer_var->type->fields.array != producer_var->type) {
1545                valid = false;
1546                goto out;
1547             }
1548          }
1549       } else {
1550          if (producer_var->type != consumer_var->type) {
1551             valid = false;
1552             goto out;
1553          }
1554 
1555          if (producer_var->interface_type != consumer_var->interface_type) {
1556             valid = false;
1557             goto out;
1558          }
1559       }
1560 
1561       if (producer_var->interpolation != consumer_var->interpolation) {
1562          valid = false;
1563          goto out;
1564       }
1565 
1566       if (producer_var->precision != consumer_var->precision) {
1567          valid = false;
1568          goto out;
1569       }
1570 
1571       if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
1572          valid = false;
1573          goto out;
1574       }
1575    }
1576 
1577  out:
1578    free(outputs);
1579    return valid && num_outputs == 0;
1580 }
1581 
1582 /**
1583  * Validate inputs against outputs in a program pipeline.
1584  */
1585 extern "C" bool
_mesa_validate_pipeline_io(struct gl_pipeline_object * pipeline)1586 _mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
1587 {
1588    struct gl_shader_program **shProg =
1589       (struct gl_shader_program **) pipeline->CurrentProgram;
1590 
1591    /* Find first active stage in pipeline. */
1592    unsigned idx, prev = 0;
1593    for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
1594       if (shProg[idx]) {
1595          prev = idx;
1596          break;
1597       }
1598    }
1599 
1600    for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
1601       if (shProg[idx]) {
1602          /* Pipeline might include both non-compute and a compute program, do
1603           * not attempt to validate varyings between non-compute and compute
1604           * stage.
1605           */
1606          if (shProg[idx]->_LinkedShaders[idx]->Stage == MESA_SHADER_COMPUTE)
1607             break;
1608 
1609          if (!validate_io(shProg[prev], shProg[idx],
1610                           shProg[prev]->_LinkedShaders[prev]->Stage,
1611                           shProg[idx]->_LinkedShaders[idx]->Stage))
1612             return false;
1613 
1614          prev = idx;
1615       }
1616    }
1617    return true;
1618 }
1619