1af69d88dSmrg/*
2af69d88dSmrg * Copyright © 2011 Intel Corporation
3af69d88dSmrg *
4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
6af69d88dSmrg * to deal in the Software without restriction, including without limitation
7af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9af69d88dSmrg * Software is furnished to do so, subject to the following conditions:
10af69d88dSmrg *
11af69d88dSmrg * The above copyright notice and this permission notice (including the next
12af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the
13af69d88dSmrg * Software.
14af69d88dSmrg *
15af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20af69d88dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21af69d88dSmrg * DEALINGS IN THE SOFTWARE.
22af69d88dSmrg */
23af69d88dSmrg
24af69d88dSmrg/**
25af69d88dSmrg * \file shader_query.cpp
26af69d88dSmrg * C-to-C++ bridge functions to query GLSL shader data
27af69d88dSmrg *
28af69d88dSmrg * \author Ian Romanick <ian.d.romanick@intel.com>
29af69d88dSmrg */
30af69d88dSmrg
3101e04c3fSmrg#include "main/context.h"
3201e04c3fSmrg#include "main/enums.h"
3301e04c3fSmrg#include "main/shaderapi.h"
3401e04c3fSmrg#include "main/shaderobj.h"
3501e04c3fSmrg#include "main/uniforms.h"
3601e04c3fSmrg#include "compiler/glsl/glsl_symbol_table.h"
3701e04c3fSmrg#include "compiler/glsl/ir.h"
3801e04c3fSmrg#include "compiler/glsl/program.h"
3901e04c3fSmrg#include "compiler/glsl/string_to_uint_map.h"
407ec681f3Smrg#include "util/mesa-sha1.h"
41af69d88dSmrg
4201e04c3fSmrgstatic GLint
4301e04c3fSmrgprogram_resource_location(struct gl_program_resource *res,
4401e04c3fSmrg                          unsigned array_index);
45af69d88dSmrg
4601e04c3fSmrg/**
4701e04c3fSmrg * Declare convenience functions to return resource data in a given type.
4801e04c3fSmrg * Warning! this is not type safe so be *very* careful when using these.
4901e04c3fSmrg */
5001e04c3fSmrg#define DECL_RESOURCE_FUNC(name, type) \
5101e04c3fSmrgconst type * RESOURCE_ ## name (gl_program_resource *res) { \
5201e04c3fSmrg   assert(res->Data); \
5301e04c3fSmrg   return (type *) res->Data; \
5401e04c3fSmrg}
55af69d88dSmrg
5601e04c3fSmrgDECL_RESOURCE_FUNC(VAR, gl_shader_variable);
5701e04c3fSmrgDECL_RESOURCE_FUNC(UBO, gl_uniform_block);
5801e04c3fSmrgDECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
5901e04c3fSmrgDECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
6001e04c3fSmrgDECL_RESOURCE_FUNC(XFV, gl_transform_feedback_varying_info);
6101e04c3fSmrgDECL_RESOURCE_FUNC(XFB, gl_transform_feedback_buffer);
6201e04c3fSmrgDECL_RESOURCE_FUNC(SUB, gl_subroutine_function);
6301e04c3fSmrg
647ec681f3Smrgstatic GLenum
657ec681f3Smrgmediump_to_highp_type(GLenum type)
667ec681f3Smrg{
677ec681f3Smrg   switch (type) {
687ec681f3Smrg   case GL_FLOAT16_NV:
697ec681f3Smrg      return GL_FLOAT;
707ec681f3Smrg   case GL_FLOAT16_VEC2_NV:
717ec681f3Smrg      return GL_FLOAT_VEC2;
727ec681f3Smrg   case GL_FLOAT16_VEC3_NV:
737ec681f3Smrg      return GL_FLOAT_VEC3;
747ec681f3Smrg   case GL_FLOAT16_VEC4_NV:
757ec681f3Smrg      return GL_FLOAT_VEC4;
767ec681f3Smrg   case GL_FLOAT16_MAT2_AMD:
777ec681f3Smrg      return GL_FLOAT_MAT2;
787ec681f3Smrg   case GL_FLOAT16_MAT3_AMD:
797ec681f3Smrg      return GL_FLOAT_MAT3;
807ec681f3Smrg   case GL_FLOAT16_MAT4_AMD:
817ec681f3Smrg      return GL_FLOAT_MAT4;
827ec681f3Smrg   case GL_FLOAT16_MAT2x3_AMD:
837ec681f3Smrg      return GL_FLOAT_MAT2x3;
847ec681f3Smrg   case GL_FLOAT16_MAT2x4_AMD:
857ec681f3Smrg      return GL_FLOAT_MAT2x4;
867ec681f3Smrg   case GL_FLOAT16_MAT3x2_AMD:
877ec681f3Smrg      return GL_FLOAT_MAT3x2;
887ec681f3Smrg   case GL_FLOAT16_MAT3x4_AMD:
897ec681f3Smrg      return GL_FLOAT_MAT3x4;
907ec681f3Smrg   case GL_FLOAT16_MAT4x2_AMD:
917ec681f3Smrg      return GL_FLOAT_MAT4x2;
927ec681f3Smrg   case GL_FLOAT16_MAT4x3_AMD:
937ec681f3Smrg      return GL_FLOAT_MAT4x3;
947ec681f3Smrg   default:
957ec681f3Smrg      return type;
967ec681f3Smrg   }
977ec681f3Smrg}
987ec681f3Smrg
9901e04c3fSmrgstatic void
10001e04c3fSmrgbind_attrib_location(struct gl_context *ctx,
10101e04c3fSmrg                     struct gl_shader_program *const shProg, GLuint index,
10201e04c3fSmrg                     const GLchar *name, bool no_error)
10301e04c3fSmrg{
104af69d88dSmrg   if (!name)
105af69d88dSmrg      return;
106af69d88dSmrg
10701e04c3fSmrg   if (!no_error) {
10801e04c3fSmrg      if (strncmp(name, "gl_", 3) == 0) {
10901e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
11001e04c3fSmrg                     "glBindAttribLocation(illegal name)");
11101e04c3fSmrg         return;
11201e04c3fSmrg      }
113af69d88dSmrg
11401e04c3fSmrg      if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
11501e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(%u >= %u)",
11601e04c3fSmrg                     index, ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs);
11701e04c3fSmrg         return;
11801e04c3fSmrg      }
119af69d88dSmrg   }
120af69d88dSmrg
121af69d88dSmrg   /* Replace the current value if it's already in the list.  Add
122af69d88dSmrg    * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
123af69d88dSmrg    * between built-in attributes and user-defined attributes.
124af69d88dSmrg    */
125af69d88dSmrg   shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
126af69d88dSmrg
127af69d88dSmrg   /*
128af69d88dSmrg    * Note that this attribute binding won't go into effect until
129af69d88dSmrg    * glLinkProgram is called again.
130af69d88dSmrg    */
131af69d88dSmrg}
132af69d88dSmrg
13301e04c3fSmrgvoid GLAPIENTRY
13401e04c3fSmrg_mesa_BindAttribLocation_no_error(GLuint program, GLuint index,
13501e04c3fSmrg                                  const GLchar *name)
136af69d88dSmrg{
13701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
138af69d88dSmrg
13901e04c3fSmrg   struct gl_shader_program *const shProg =
14001e04c3fSmrg      _mesa_lookup_shader_program(ctx, program);
14101e04c3fSmrg   bind_attrib_location(ctx, shProg, index, name, true);
14201e04c3fSmrg}
143af69d88dSmrg
14401e04c3fSmrgvoid GLAPIENTRY
14501e04c3fSmrg_mesa_BindAttribLocation(GLuint program, GLuint index,
14601e04c3fSmrg                         const GLchar *name)
14701e04c3fSmrg{
14801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
149af69d88dSmrg
15001e04c3fSmrg   struct gl_shader_program *const shProg =
15101e04c3fSmrg      _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
15201e04c3fSmrg   if (!shProg)
15301e04c3fSmrg      return;
15401e04c3fSmrg
15501e04c3fSmrg   bind_attrib_location(ctx, shProg, index, name, false);
156af69d88dSmrg}
157af69d88dSmrg
158af69d88dSmrgvoid GLAPIENTRY
15901e04c3fSmrg_mesa_GetActiveAttrib(GLuint program, GLuint desired_index,
16001e04c3fSmrg                      GLsizei maxLength, GLsizei * length, GLint * size,
16101e04c3fSmrg                      GLenum * type, GLchar * name)
162af69d88dSmrg{
163af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
164af69d88dSmrg   struct gl_shader_program *shProg;
165af69d88dSmrg
16601e04c3fSmrg   if (maxLength < 0) {
16701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)");
16801e04c3fSmrg      return;
16901e04c3fSmrg   }
17001e04c3fSmrg
171af69d88dSmrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
172af69d88dSmrg   if (!shProg)
173af69d88dSmrg      return;
174af69d88dSmrg
17501e04c3fSmrg   if (!shProg->data->LinkStatus) {
176af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
177af69d88dSmrg                  "glGetActiveAttrib(program not linked)");
178af69d88dSmrg      return;
179af69d88dSmrg   }
180af69d88dSmrg
181af69d88dSmrg   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
182af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
183af69d88dSmrg      return;
184af69d88dSmrg   }
185af69d88dSmrg
18601e04c3fSmrg   struct gl_program_resource *res =
18701e04c3fSmrg      _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
18801e04c3fSmrg                                        desired_index);
189af69d88dSmrg
19001e04c3fSmrg   /* User asked for index that does not exist. */
19101e04c3fSmrg   if (!res) {
19201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
19301e04c3fSmrg      return;
194af69d88dSmrg   }
195af69d88dSmrg
19601e04c3fSmrg   const gl_shader_variable *const var = RESOURCE_VAR(res);
197af69d88dSmrg
19801e04c3fSmrg   const char *var_name = var->name;
199af69d88dSmrg
20001e04c3fSmrg   _mesa_copy_string(name, maxLength, length, var_name);
201af69d88dSmrg
20201e04c3fSmrg   if (size)
20301e04c3fSmrg      _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
2047ec681f3Smrg                                  size, false, "glGetActiveAttrib");
205af69d88dSmrg
20601e04c3fSmrg   if (type)
20701e04c3fSmrg      _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
2087ec681f3Smrg                                  (GLint *) type, false, "glGetActiveAttrib");
209af69d88dSmrg}
210af69d88dSmrg
211af69d88dSmrgGLint GLAPIENTRY
21201e04c3fSmrg_mesa_GetAttribLocation(GLuint program, const GLchar * name)
213af69d88dSmrg{
214af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
215af69d88dSmrg   struct gl_shader_program *const shProg =
216af69d88dSmrg      _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
217af69d88dSmrg
218af69d88dSmrg   if (!shProg) {
219af69d88dSmrg      return -1;
220af69d88dSmrg   }
221af69d88dSmrg
22201e04c3fSmrg   if (!shProg->data->LinkStatus) {
223af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
224af69d88dSmrg                  "glGetAttribLocation(program not linked)");
225af69d88dSmrg      return -1;
226af69d88dSmrg   }
227af69d88dSmrg
228af69d88dSmrg   if (!name)
229af69d88dSmrg      return -1;
230af69d88dSmrg
231af69d88dSmrg   /* Not having a vertex shader is not an error.
232af69d88dSmrg    */
233af69d88dSmrg   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
234af69d88dSmrg      return -1;
235af69d88dSmrg
23601e04c3fSmrg   unsigned array_index = 0;
23701e04c3fSmrg   struct gl_program_resource *res =
23801e04c3fSmrg      _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name,
23901e04c3fSmrg                                       &array_index);
240af69d88dSmrg
24101e04c3fSmrg   if (!res)
24201e04c3fSmrg      return -1;
243af69d88dSmrg
24401e04c3fSmrg   return program_resource_location(res, array_index);
245af69d88dSmrg}
246af69d88dSmrg
247af69d88dSmrgunsigned
248af69d88dSmrg_mesa_count_active_attribs(struct gl_shader_program *shProg)
249af69d88dSmrg{
25001e04c3fSmrg   if (!shProg->data->LinkStatus
251af69d88dSmrg       || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
252af69d88dSmrg      return 0;
253af69d88dSmrg   }
254af69d88dSmrg
25501e04c3fSmrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
25601e04c3fSmrg   unsigned count = 0;
25701e04c3fSmrg   for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
25801e04c3fSmrg        j++, res++) {
25901e04c3fSmrg      if (res->Type == GL_PROGRAM_INPUT &&
26001e04c3fSmrg          res->StageReferences & (1 << MESA_SHADER_VERTEX))
26101e04c3fSmrg         count++;
262af69d88dSmrg   }
26301e04c3fSmrg   return count;
264af69d88dSmrg}
265af69d88dSmrg
266af69d88dSmrg
267af69d88dSmrgsize_t
268af69d88dSmrg_mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
269af69d88dSmrg{
27001e04c3fSmrg   if (!shProg->data->LinkStatus
271af69d88dSmrg       || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
272af69d88dSmrg      return 0;
273af69d88dSmrg   }
274af69d88dSmrg
27501e04c3fSmrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
276af69d88dSmrg   size_t longest = 0;
27701e04c3fSmrg   for (unsigned j = 0; j < shProg->data->NumProgramResourceList;
27801e04c3fSmrg        j++, res++) {
27901e04c3fSmrg      if (res->Type == GL_PROGRAM_INPUT &&
28001e04c3fSmrg          res->StageReferences & (1 << MESA_SHADER_VERTEX)) {
28101e04c3fSmrg
2827ec681f3Smrg         /* From the ARB_gl_spirv spec:
2837ec681f3Smrg          *
2847ec681f3Smrg          *   "If pname is ACTIVE_ATTRIBUTE_MAX_LENGTH, the length of the
2857ec681f3Smrg          *    longest active attribute name, including a null terminator, is
2867ec681f3Smrg          *    returned.  If no active attributes exist, zero is returned. If
2877ec681f3Smrg          *    no name reflection information is available, one is returned."
2887ec681f3Smrg          */
2897ec681f3Smrg         const size_t length = RESOURCE_VAR(res)->name != NULL ?
2907ec681f3Smrg            strlen(RESOURCE_VAR(res)->name) : 0;
2917ec681f3Smrg
2927ec681f3Smrg         if (length >= longest)
2937ec681f3Smrg            longest = length + 1;
29401e04c3fSmrg      }
295af69d88dSmrg   }
296af69d88dSmrg
297af69d88dSmrg   return longest;
298af69d88dSmrg}
299af69d88dSmrg
30001e04c3fSmrgvoid static
30101e04c3fSmrgbind_frag_data_location(struct gl_shader_program *const shProg,
30201e04c3fSmrg                        const char *name, unsigned colorNumber,
30301e04c3fSmrg                        unsigned index)
30401e04c3fSmrg{
30501e04c3fSmrg   /* Replace the current value if it's already in the list.  Add
30601e04c3fSmrg    * FRAG_RESULT_DATA0 because that's how the linker differentiates
30701e04c3fSmrg    * between built-in attributes and user-defined attributes.
30801e04c3fSmrg    */
30901e04c3fSmrg   shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
31001e04c3fSmrg   shProg->FragDataIndexBindings->put(index, name);
31101e04c3fSmrg
31201e04c3fSmrg   /*
31301e04c3fSmrg    * Note that this binding won't go into effect until
31401e04c3fSmrg    * glLinkProgram is called again.
31501e04c3fSmrg    */
31601e04c3fSmrg}
31701e04c3fSmrg
318af69d88dSmrgvoid GLAPIENTRY
319af69d88dSmrg_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
320af69d88dSmrg			   const GLchar *name)
321af69d88dSmrg{
322af69d88dSmrg   _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
323af69d88dSmrg}
324af69d88dSmrg
32501e04c3fSmrgvoid GLAPIENTRY
32601e04c3fSmrg_mesa_BindFragDataLocation_no_error(GLuint program, GLuint colorNumber,
32701e04c3fSmrg                                    const GLchar *name)
32801e04c3fSmrg{
32901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
33001e04c3fSmrg
33101e04c3fSmrg   if (!name)
33201e04c3fSmrg      return;
33301e04c3fSmrg
33401e04c3fSmrg   struct gl_shader_program *const shProg =
33501e04c3fSmrg      _mesa_lookup_shader_program(ctx, program);
33601e04c3fSmrg
33701e04c3fSmrg   bind_frag_data_location(shProg, name, colorNumber, 0);
33801e04c3fSmrg}
33901e04c3fSmrg
340af69d88dSmrgvoid GLAPIENTRY
341af69d88dSmrg_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
342af69d88dSmrg                                  GLuint index, const GLchar *name)
343af69d88dSmrg{
344af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
345af69d88dSmrg
346af69d88dSmrg   struct gl_shader_program *const shProg =
347af69d88dSmrg      _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
348af69d88dSmrg   if (!shProg)
349af69d88dSmrg      return;
350af69d88dSmrg
351af69d88dSmrg   if (!name)
352af69d88dSmrg      return;
353af69d88dSmrg
354af69d88dSmrg   if (strncmp(name, "gl_", 3) == 0) {
355af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
356af69d88dSmrg      return;
357af69d88dSmrg   }
358af69d88dSmrg
359af69d88dSmrg   if (index > 1) {
360af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
361af69d88dSmrg      return;
362af69d88dSmrg   }
363af69d88dSmrg
364af69d88dSmrg   if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
365af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
366af69d88dSmrg      return;
367af69d88dSmrg   }
368af69d88dSmrg
369af69d88dSmrg   if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
370af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
371af69d88dSmrg      return;
372af69d88dSmrg   }
373af69d88dSmrg
37401e04c3fSmrg   bind_frag_data_location(shProg, name, colorNumber, index);
37501e04c3fSmrg}
376af69d88dSmrg
37701e04c3fSmrgvoid GLAPIENTRY
37801e04c3fSmrg_mesa_BindFragDataLocationIndexed_no_error(GLuint program, GLuint colorNumber,
37901e04c3fSmrg                                           GLuint index, const GLchar *name)
38001e04c3fSmrg{
38101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
38201e04c3fSmrg
38301e04c3fSmrg   if (!name)
38401e04c3fSmrg      return;
38501e04c3fSmrg
38601e04c3fSmrg   struct gl_shader_program *const shProg =
38701e04c3fSmrg      _mesa_lookup_shader_program(ctx, program);
38801e04c3fSmrg
38901e04c3fSmrg   bind_frag_data_location(shProg, name, colorNumber, index);
390af69d88dSmrg}
391af69d88dSmrg
392af69d88dSmrgGLint GLAPIENTRY
393af69d88dSmrg_mesa_GetFragDataIndex(GLuint program, const GLchar *name)
394af69d88dSmrg{
395af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
396af69d88dSmrg   struct gl_shader_program *const shProg =
397af69d88dSmrg      _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
398af69d88dSmrg
399af69d88dSmrg   if (!shProg) {
400af69d88dSmrg      return -1;
401af69d88dSmrg   }
402af69d88dSmrg
40301e04c3fSmrg   if (!shProg->data->LinkStatus) {
404af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
405af69d88dSmrg                  "glGetFragDataIndex(program not linked)");
406af69d88dSmrg      return -1;
407af69d88dSmrg   }
408af69d88dSmrg
409af69d88dSmrg   if (!name)
410af69d88dSmrg      return -1;
411af69d88dSmrg
412af69d88dSmrg   /* Not having a fragment shader is not an error.
413af69d88dSmrg    */
414af69d88dSmrg   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
415af69d88dSmrg      return -1;
416af69d88dSmrg
41701e04c3fSmrg   return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
41801e04c3fSmrg                                                name);
419af69d88dSmrg}
420af69d88dSmrg
421af69d88dSmrgGLint GLAPIENTRY
422af69d88dSmrg_mesa_GetFragDataLocation(GLuint program, const GLchar *name)
423af69d88dSmrg{
424af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
425af69d88dSmrg   struct gl_shader_program *const shProg =
426af69d88dSmrg      _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
427af69d88dSmrg
428af69d88dSmrg   if (!shProg) {
429af69d88dSmrg      return -1;
430af69d88dSmrg   }
431af69d88dSmrg
43201e04c3fSmrg   if (!shProg->data->LinkStatus) {
433af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
434af69d88dSmrg                  "glGetFragDataLocation(program not linked)");
435af69d88dSmrg      return -1;
436af69d88dSmrg   }
437af69d88dSmrg
438af69d88dSmrg   if (!name)
439af69d88dSmrg      return -1;
440af69d88dSmrg
441af69d88dSmrg   /* Not having a fragment shader is not an error.
442af69d88dSmrg    */
443af69d88dSmrg   if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
444af69d88dSmrg      return -1;
445af69d88dSmrg
44601e04c3fSmrg   unsigned array_index = 0;
44701e04c3fSmrg   struct gl_program_resource *res =
44801e04c3fSmrg      _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name,
44901e04c3fSmrg                                       &array_index);
45001e04c3fSmrg
45101e04c3fSmrg   if (!res)
45201e04c3fSmrg      return -1;
45301e04c3fSmrg
45401e04c3fSmrg   return program_resource_location(res, array_index);
45501e04c3fSmrg}
45601e04c3fSmrg
45701e04c3fSmrgconst char*
45801e04c3fSmrg_mesa_program_resource_name(struct gl_program_resource *res)
45901e04c3fSmrg{
46001e04c3fSmrg   switch (res->Type) {
46101e04c3fSmrg   case GL_UNIFORM_BLOCK:
46201e04c3fSmrg   case GL_SHADER_STORAGE_BLOCK:
46301e04c3fSmrg      return RESOURCE_UBO(res)->Name;
46401e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_VARYING:
46501e04c3fSmrg      return RESOURCE_XFV(res)->Name;
46601e04c3fSmrg   case GL_PROGRAM_INPUT:
46701e04c3fSmrg   case GL_PROGRAM_OUTPUT:
46801e04c3fSmrg      return RESOURCE_VAR(res)->name;
46901e04c3fSmrg   case GL_UNIFORM:
47001e04c3fSmrg   case GL_BUFFER_VARIABLE:
47101e04c3fSmrg      return RESOURCE_UNI(res)->name;
47201e04c3fSmrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
47301e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
47401e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
47501e04c3fSmrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
47601e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
47701e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
47801e04c3fSmrg      return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN;
47901e04c3fSmrg   case GL_VERTEX_SUBROUTINE:
48001e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE:
48101e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE:
48201e04c3fSmrg   case GL_COMPUTE_SUBROUTINE:
48301e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE:
48401e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE:
48501e04c3fSmrg      return RESOURCE_SUB(res)->name;
48601e04c3fSmrg   default:
4877ec681f3Smrg      break;
48801e04c3fSmrg   }
48901e04c3fSmrg   return NULL;
49001e04c3fSmrg}
49101e04c3fSmrg
49201e04c3fSmrg
49301e04c3fSmrgunsigned
49401e04c3fSmrg_mesa_program_resource_array_size(struct gl_program_resource *res)
49501e04c3fSmrg{
49601e04c3fSmrg   switch (res->Type) {
49701e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_VARYING:
49801e04c3fSmrg      return RESOURCE_XFV(res)->Size > 1 ?
49901e04c3fSmrg             RESOURCE_XFV(res)->Size : 0;
50001e04c3fSmrg   case GL_PROGRAM_INPUT:
50101e04c3fSmrg   case GL_PROGRAM_OUTPUT:
50201e04c3fSmrg      return RESOURCE_VAR(res)->type->length;
50301e04c3fSmrg   case GL_UNIFORM:
50401e04c3fSmrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
50501e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
50601e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
50701e04c3fSmrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
50801e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
50901e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
51001e04c3fSmrg      return RESOURCE_UNI(res)->array_elements;
51101e04c3fSmrg   case GL_BUFFER_VARIABLE:
51201e04c3fSmrg      /* Unsized arrays */
51301e04c3fSmrg      if (RESOURCE_UNI(res)->array_stride > 0 &&
51401e04c3fSmrg          RESOURCE_UNI(res)->array_elements == 0)
51501e04c3fSmrg         return 1;
51601e04c3fSmrg      else
51701e04c3fSmrg         return RESOURCE_UNI(res)->array_elements;
51801e04c3fSmrg   case GL_VERTEX_SUBROUTINE:
51901e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE:
52001e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE:
52101e04c3fSmrg   case GL_COMPUTE_SUBROUTINE:
52201e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE:
52301e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE:
52401e04c3fSmrg   case GL_ATOMIC_COUNTER_BUFFER:
52501e04c3fSmrg   case GL_UNIFORM_BLOCK:
52601e04c3fSmrg   case GL_SHADER_STORAGE_BLOCK:
52701e04c3fSmrg      return 0;
52801e04c3fSmrg   default:
52901e04c3fSmrg      assert(!"support for resource type not implemented");
53001e04c3fSmrg   }
53101e04c3fSmrg   return 0;
53201e04c3fSmrg}
53301e04c3fSmrg
53401e04c3fSmrg/**
53501e04c3fSmrg * Checks if array subscript is valid and if so sets array_index.
53601e04c3fSmrg */
53701e04c3fSmrgstatic bool
53801e04c3fSmrgvalid_array_index(const GLchar *name, unsigned *array_index)
53901e04c3fSmrg{
54001e04c3fSmrg   long idx = 0;
54101e04c3fSmrg   const GLchar *out_base_name_end;
54201e04c3fSmrg
5437ec681f3Smrg   idx = parse_program_resource_name(name, strlen(name), &out_base_name_end);
54401e04c3fSmrg   if (idx < 0)
54501e04c3fSmrg      return false;
54601e04c3fSmrg
54701e04c3fSmrg   if (array_index)
54801e04c3fSmrg      *array_index = idx;
54901e04c3fSmrg
55001e04c3fSmrg   return true;
55101e04c3fSmrg}
55201e04c3fSmrg
5537ec681f3Smrgstatic uint32_t
5547ec681f3Smrgcompute_resource_key(GLenum programInterface, const char *name, size_t len)
5557ec681f3Smrg{
5567ec681f3Smrg   return _mesa_hash_data_with_seed(name, len, programInterface + len);
5577ec681f3Smrg}
5587ec681f3Smrg
5597ec681f3Smrgstatic struct gl_program_resource *
5607ec681f3Smrgsearch_resource_hash(struct gl_shader_program *shProg,
5617ec681f3Smrg                     GLenum programInterface, const char *name,
5627ec681f3Smrg                     unsigned *array_index)
5637ec681f3Smrg{
5647ec681f3Smrg   const char *base_name_end;
5657ec681f3Smrg   size_t len = strlen(name);
5667ec681f3Smrg   long index = parse_program_resource_name(name, len, &base_name_end);
5677ec681f3Smrg   char *name_copy;
5687ec681f3Smrg
5697ec681f3Smrg   /* If dealing with array, we need to get the basename. */
5707ec681f3Smrg   if (index >= 0) {
5717ec681f3Smrg      name_copy = (char *) malloc(base_name_end - name + 1);
5727ec681f3Smrg      memcpy(name_copy, name, base_name_end - name);
5737ec681f3Smrg      name_copy[base_name_end - name] = '\0';
5747ec681f3Smrg      len = base_name_end - name;
5757ec681f3Smrg   } else {
5767ec681f3Smrg      name_copy = (char*) name;
5777ec681f3Smrg   }
5787ec681f3Smrg
5797ec681f3Smrg   uint32_t key = compute_resource_key(programInterface, name_copy, len);
5807ec681f3Smrg   struct gl_program_resource *res = (struct gl_program_resource *)
5817ec681f3Smrg      _mesa_hash_table_u64_search(shProg->data->ProgramResourceHash, key);
5827ec681f3Smrg
5837ec681f3Smrg   if (name_copy != name)
5847ec681f3Smrg      free(name_copy);
5857ec681f3Smrg
5867ec681f3Smrg   if (res && array_index)
5877ec681f3Smrg      *array_index = index >= 0 ? index : 0;
5887ec681f3Smrg
5897ec681f3Smrg   return res;
5907ec681f3Smrg}
5917ec681f3Smrg
59201e04c3fSmrg/* Find a program resource with specific name in given interface.
59301e04c3fSmrg */
59401e04c3fSmrgstruct gl_program_resource *
59501e04c3fSmrg_mesa_program_resource_find_name(struct gl_shader_program *shProg,
59601e04c3fSmrg                                 GLenum programInterface, const char *name,
59701e04c3fSmrg                                 unsigned *array_index)
59801e04c3fSmrg{
5997ec681f3Smrg   struct gl_program_resource *res = NULL;
6007ec681f3Smrg
6017ec681f3Smrg   if (name == NULL)
6027ec681f3Smrg      return NULL;
6037ec681f3Smrg
6047ec681f3Smrg   /* If we have a name, try the ProgramResourceHash first. */
6057ec681f3Smrg   if (shProg->data->ProgramResourceHash)
6067ec681f3Smrg      res = search_resource_hash(shProg, programInterface, name, array_index);
6077ec681f3Smrg
6087ec681f3Smrg   if (res)
6097ec681f3Smrg      return res;
6107ec681f3Smrg
6117ec681f3Smrg   res = shProg->data->ProgramResourceList;
6127ec681f3Smrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
61301e04c3fSmrg      if (res->Type != programInterface)
61401e04c3fSmrg         continue;
61501e04c3fSmrg
61601e04c3fSmrg      /* Resource basename. */
61701e04c3fSmrg      const char *rname = _mesa_program_resource_name(res);
61801e04c3fSmrg
61901e04c3fSmrg      /* Since ARB_gl_spirv lack of name reflections is a possibility */
62001e04c3fSmrg      if (rname == NULL)
62101e04c3fSmrg         continue;
622af69d88dSmrg
62301e04c3fSmrg      unsigned baselen = strlen(rname);
62401e04c3fSmrg      unsigned baselen_without_array_index = baselen;
62501e04c3fSmrg      const char *rname_last_square_bracket = strrchr(rname, '[');
62601e04c3fSmrg      bool found = false;
62701e04c3fSmrg      bool rname_has_array_index_zero = false;
62801e04c3fSmrg      /* From ARB_program_interface_query spec:
629af69d88dSmrg       *
63001e04c3fSmrg       * "uint GetProgramResourceIndex(uint program, enum programInterface,
63101e04c3fSmrg       *                               const char *name);
63201e04c3fSmrg       *  [...]
63301e04c3fSmrg       *  If <name> exactly matches the name string of one of the active
63401e04c3fSmrg       *  resources for <programInterface>, the index of the matched resource is
63501e04c3fSmrg       *  returned. Additionally, if <name> would exactly match the name string
63601e04c3fSmrg       *  of an active resource if "[0]" were appended to <name>, the index of
63701e04c3fSmrg       *  the matched resource is returned. [...]"
638af69d88dSmrg       *
63901e04c3fSmrg       * "A string provided to GetProgramResourceLocation or
64001e04c3fSmrg       * GetProgramResourceLocationIndex is considered to match an active variable
64101e04c3fSmrg       * if:
64201e04c3fSmrg       *
64301e04c3fSmrg       *  * the string exactly matches the name of the active variable;
64401e04c3fSmrg       *
64501e04c3fSmrg       *  * if the string identifies the base name of an active array, where the
64601e04c3fSmrg       *    string would exactly match the name of the variable if the suffix
64701e04c3fSmrg       *    "[0]" were appended to the string; [...]"
648af69d88dSmrg       */
64901e04c3fSmrg      /* Remove array's index from interface block name comparison only if
65001e04c3fSmrg       * array's index is zero and the resulting string length is the same
65101e04c3fSmrg       * than the provided name's length.
65201e04c3fSmrg       */
65301e04c3fSmrg      if (rname_last_square_bracket) {
65401e04c3fSmrg         baselen_without_array_index -= strlen(rname_last_square_bracket);
65501e04c3fSmrg         rname_has_array_index_zero =
65601e04c3fSmrg            (strcmp(rname_last_square_bracket, "[0]") == 0) &&
65701e04c3fSmrg            (baselen_without_array_index == strlen(name));
65801e04c3fSmrg      }
659af69d88dSmrg
66001e04c3fSmrg      if (strncmp(rname, name, baselen) == 0)
66101e04c3fSmrg         found = true;
66201e04c3fSmrg      else if (rname_has_array_index_zero &&
66301e04c3fSmrg               strncmp(rname, name, baselen_without_array_index) == 0)
66401e04c3fSmrg         found = true;
66501e04c3fSmrg
66601e04c3fSmrg      if (found) {
66701e04c3fSmrg         switch (programInterface) {
66801e04c3fSmrg         case GL_UNIFORM_BLOCK:
66901e04c3fSmrg         case GL_SHADER_STORAGE_BLOCK:
67001e04c3fSmrg            /* Basename match, check if array or struct. */
67101e04c3fSmrg            if (rname_has_array_index_zero ||
67201e04c3fSmrg                name[baselen] == '\0' ||
67301e04c3fSmrg                name[baselen] == '[' ||
67401e04c3fSmrg                name[baselen] == '.') {
67501e04c3fSmrg               return res;
67601e04c3fSmrg            }
67701e04c3fSmrg            break;
67801e04c3fSmrg         case GL_TRANSFORM_FEEDBACK_VARYING:
67901e04c3fSmrg         case GL_BUFFER_VARIABLE:
68001e04c3fSmrg         case GL_UNIFORM:
68101e04c3fSmrg         case GL_VERTEX_SUBROUTINE_UNIFORM:
68201e04c3fSmrg         case GL_GEOMETRY_SUBROUTINE_UNIFORM:
68301e04c3fSmrg         case GL_FRAGMENT_SUBROUTINE_UNIFORM:
68401e04c3fSmrg         case GL_COMPUTE_SUBROUTINE_UNIFORM:
68501e04c3fSmrg         case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
68601e04c3fSmrg         case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
68701e04c3fSmrg         case GL_VERTEX_SUBROUTINE:
68801e04c3fSmrg         case GL_GEOMETRY_SUBROUTINE:
68901e04c3fSmrg         case GL_FRAGMENT_SUBROUTINE:
69001e04c3fSmrg         case GL_COMPUTE_SUBROUTINE:
69101e04c3fSmrg         case GL_TESS_CONTROL_SUBROUTINE:
69201e04c3fSmrg         case GL_TESS_EVALUATION_SUBROUTINE:
69301e04c3fSmrg            if (name[baselen] == '.') {
69401e04c3fSmrg               return res;
69501e04c3fSmrg            }
6967ec681f3Smrg            FALLTHROUGH;
69701e04c3fSmrg         case GL_PROGRAM_INPUT:
69801e04c3fSmrg         case GL_PROGRAM_OUTPUT:
69901e04c3fSmrg            if (name[baselen] == '\0') {
70001e04c3fSmrg               return res;
70101e04c3fSmrg            } else if (name[baselen] == '[' &&
70201e04c3fSmrg                valid_array_index(name, array_index)) {
70301e04c3fSmrg               return res;
70401e04c3fSmrg            }
70501e04c3fSmrg            break;
70601e04c3fSmrg         default:
70701e04c3fSmrg            assert(!"not implemented for given interface");
70801e04c3fSmrg         }
70901e04c3fSmrg      }
71001e04c3fSmrg   }
71101e04c3fSmrg   return NULL;
71201e04c3fSmrg}
713af69d88dSmrg
7147ec681f3Smrg/* Find an uniform or buffer variable program resource with an specific offset
7157ec681f3Smrg * inside a block with an specific binding.
7167ec681f3Smrg *
7177ec681f3Smrg * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
7187ec681f3Smrg */
7197ec681f3Smrgstatic struct gl_program_resource *
7207ec681f3Smrgprogram_resource_find_binding_offset(struct gl_shader_program *shProg,
7217ec681f3Smrg                                     GLenum programInterface,
7227ec681f3Smrg                                     const GLuint binding,
7237ec681f3Smrg                                     const GLint offset)
7247ec681f3Smrg{
7257ec681f3Smrg
7267ec681f3Smrg   /* First we need to get the BLOCK_INDEX from the BUFFER_BINDING */
7277ec681f3Smrg   GLenum blockInterface;
7287ec681f3Smrg
7297ec681f3Smrg   switch (programInterface) {
7307ec681f3Smrg   case GL_BUFFER_VARIABLE:
7317ec681f3Smrg      blockInterface = GL_SHADER_STORAGE_BLOCK;
7327ec681f3Smrg      break;
7337ec681f3Smrg   case GL_UNIFORM:
7347ec681f3Smrg      blockInterface = GL_UNIFORM_BLOCK;
7357ec681f3Smrg      break;
7367ec681f3Smrg   default:
7377ec681f3Smrg      assert("Invalid program interface");
7387ec681f3Smrg      return NULL;
7397ec681f3Smrg   }
7407ec681f3Smrg
7417ec681f3Smrg   int block_index = -1;
7427ec681f3Smrg   int starting_index = -1;
7437ec681f3Smrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
7447ec681f3Smrg
7457ec681f3Smrg   /* Blocks are added to the resource list in the same order that they are
7467ec681f3Smrg    * added to UniformBlocks/ShaderStorageBlocks. Furthermore, all the blocks
7477ec681f3Smrg    * of each type (UBO/SSBO) are contiguous, so we can infer block_index from
7487ec681f3Smrg    * the resource list.
7497ec681f3Smrg    */
7507ec681f3Smrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
7517ec681f3Smrg      if (res->Type != blockInterface)
7527ec681f3Smrg         continue;
7537ec681f3Smrg
7547ec681f3Smrg      /* Store the first index where a resource of the specific interface is. */
7557ec681f3Smrg      if (starting_index == -1)
7567ec681f3Smrg         starting_index = i;
7577ec681f3Smrg
7587ec681f3Smrg      const struct gl_uniform_block *block = RESOURCE_UBO(res);
7597ec681f3Smrg
7607ec681f3Smrg      if (block->Binding == binding) {
7617ec681f3Smrg         /* For arrays, or arrays of arrays of blocks, we want the resource
7627ec681f3Smrg          * for the block with base index. Most properties for members of each
7637ec681f3Smrg          * block are inherited from the block with the base index, including
7647ec681f3Smrg          * a uniform being active or not.
7657ec681f3Smrg          */
7667ec681f3Smrg         block_index = i - starting_index - block->linearized_array_index;
7677ec681f3Smrg         break;
7687ec681f3Smrg      }
7697ec681f3Smrg   }
7707ec681f3Smrg
7717ec681f3Smrg   if (block_index == -1)
7727ec681f3Smrg      return NULL;
7737ec681f3Smrg
7747ec681f3Smrg   /* We now look for the resource corresponding to the uniform or buffer
7757ec681f3Smrg    * variable using the BLOCK_INDEX and OFFSET.
7767ec681f3Smrg    */
7777ec681f3Smrg   res = shProg->data->ProgramResourceList;
7787ec681f3Smrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
7797ec681f3Smrg      if (res->Type != programInterface)
7807ec681f3Smrg         continue;
7817ec681f3Smrg
7827ec681f3Smrg      const struct gl_uniform_storage *uniform = RESOURCE_UNI(res);
7837ec681f3Smrg
7847ec681f3Smrg      if (uniform->block_index == block_index && uniform->offset == offset) {
7857ec681f3Smrg         return res;
7867ec681f3Smrg      }
7877ec681f3Smrg   }
7887ec681f3Smrg
7897ec681f3Smrg   return NULL;
7907ec681f3Smrg}
7917ec681f3Smrg
7927ec681f3Smrg/* Checks if an uniform or buffer variable is in the active program resource
7937ec681f3Smrg * list.
7947ec681f3Smrg *
7957ec681f3Smrg * It takes into accout that for variables coming from SPIR-V binaries their
7967ec681f3Smrg * names could not be available (ARB_gl_spirv). In that case, it will use the
7977ec681f3Smrg * the offset and the block binding to locate the resource.
7987ec681f3Smrg *
7997ec681f3Smrg * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
8007ec681f3Smrg */
8017ec681f3Smrgstruct gl_program_resource *
8027ec681f3Smrg_mesa_program_resource_find_active_variable(struct gl_shader_program *shProg,
8037ec681f3Smrg                                            GLenum programInterface,
8047ec681f3Smrg                                            const gl_uniform_block *block,
8057ec681f3Smrg                                            unsigned index)
8067ec681f3Smrg{
8077ec681f3Smrg   struct gl_program_resource *res;
8087ec681f3Smrg   struct gl_uniform_buffer_variable uni = block->Uniforms[index];
8097ec681f3Smrg
8107ec681f3Smrg   assert(programInterface == GL_UNIFORM ||
8117ec681f3Smrg          programInterface == GL_BUFFER_VARIABLE);
8127ec681f3Smrg
8137ec681f3Smrg   if (uni.IndexName) {
8147ec681f3Smrg      res = _mesa_program_resource_find_name(shProg, programInterface, uni.IndexName,
8157ec681f3Smrg                                             NULL);
8167ec681f3Smrg   } else {
8177ec681f3Smrg      /* As the resource has no associated name (ARB_gl_spirv),
8187ec681f3Smrg       * we can use the UBO/SSBO binding and offset to find it.
8197ec681f3Smrg       */
8207ec681f3Smrg      res = program_resource_find_binding_offset(shProg, programInterface,
8217ec681f3Smrg                                                 block->Binding, uni.Offset);
8227ec681f3Smrg   }
8237ec681f3Smrg
8247ec681f3Smrg   return res;
8257ec681f3Smrg}
8267ec681f3Smrg
82701e04c3fSmrgstatic GLuint
82801e04c3fSmrgcalc_resource_index(struct gl_shader_program *shProg,
82901e04c3fSmrg                    struct gl_program_resource *res)
83001e04c3fSmrg{
83101e04c3fSmrg   unsigned i;
83201e04c3fSmrg   GLuint index = 0;
83301e04c3fSmrg   for (i = 0; i < shProg->data->NumProgramResourceList; i++) {
83401e04c3fSmrg      if (&shProg->data->ProgramResourceList[i] == res)
83501e04c3fSmrg         return index;
83601e04c3fSmrg      if (shProg->data->ProgramResourceList[i].Type == res->Type)
83701e04c3fSmrg         index++;
838af69d88dSmrg   }
83901e04c3fSmrg   return GL_INVALID_INDEX;
84001e04c3fSmrg}
84101e04c3fSmrg
84201e04c3fSmrg/**
84301e04c3fSmrg * Calculate index for the given resource.
84401e04c3fSmrg */
84501e04c3fSmrgGLuint
84601e04c3fSmrg_mesa_program_resource_index(struct gl_shader_program *shProg,
84701e04c3fSmrg                             struct gl_program_resource *res)
84801e04c3fSmrg{
84901e04c3fSmrg   if (!res)
85001e04c3fSmrg      return GL_INVALID_INDEX;
85101e04c3fSmrg
85201e04c3fSmrg   switch (res->Type) {
85301e04c3fSmrg   case GL_ATOMIC_COUNTER_BUFFER:
85401e04c3fSmrg      return RESOURCE_ATC(res) - shProg->data->AtomicBuffers;
85501e04c3fSmrg   case GL_VERTEX_SUBROUTINE:
85601e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE:
85701e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE:
85801e04c3fSmrg   case GL_COMPUTE_SUBROUTINE:
85901e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE:
86001e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE:
86101e04c3fSmrg      return RESOURCE_SUB(res)->index;
86201e04c3fSmrg   case GL_UNIFORM_BLOCK:
86301e04c3fSmrg   case GL_SHADER_STORAGE_BLOCK:
86401e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
86501e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_VARYING:
86601e04c3fSmrg   default:
86701e04c3fSmrg      return calc_resource_index(shProg, res);
86801e04c3fSmrg   }
86901e04c3fSmrg}
87001e04c3fSmrg
87101e04c3fSmrg/**
87201e04c3fSmrg * Find a program resource that points to given data.
87301e04c3fSmrg */
87401e04c3fSmrgstatic struct gl_program_resource*
87501e04c3fSmrgprogram_resource_find_data(struct gl_shader_program *shProg, void *data)
87601e04c3fSmrg{
87701e04c3fSmrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
87801e04c3fSmrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
87901e04c3fSmrg        i++, res++) {
88001e04c3fSmrg      if (res->Data == data)
88101e04c3fSmrg         return res;
88201e04c3fSmrg   }
88301e04c3fSmrg   return NULL;
88401e04c3fSmrg}
88501e04c3fSmrg
88601e04c3fSmrg/* Find a program resource with specific index in given interface.
88701e04c3fSmrg */
88801e04c3fSmrgstruct gl_program_resource *
88901e04c3fSmrg_mesa_program_resource_find_index(struct gl_shader_program *shProg,
89001e04c3fSmrg                                  GLenum programInterface, GLuint index)
89101e04c3fSmrg{
89201e04c3fSmrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
89301e04c3fSmrg   int idx = -1;
89401e04c3fSmrg
89501e04c3fSmrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList;
89601e04c3fSmrg        i++, res++) {
89701e04c3fSmrg      if (res->Type != programInterface)
89801e04c3fSmrg         continue;
89901e04c3fSmrg
90001e04c3fSmrg      switch (res->Type) {
90101e04c3fSmrg      case GL_UNIFORM_BLOCK:
90201e04c3fSmrg      case GL_ATOMIC_COUNTER_BUFFER:
90301e04c3fSmrg      case GL_SHADER_STORAGE_BLOCK:
90401e04c3fSmrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
90501e04c3fSmrg         if (_mesa_program_resource_index(shProg, res) == index)
90601e04c3fSmrg            return res;
90701e04c3fSmrg         break;
90801e04c3fSmrg      case GL_TRANSFORM_FEEDBACK_VARYING:
90901e04c3fSmrg      case GL_PROGRAM_INPUT:
91001e04c3fSmrg      case GL_PROGRAM_OUTPUT:
91101e04c3fSmrg      case GL_UNIFORM:
91201e04c3fSmrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
91301e04c3fSmrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
91401e04c3fSmrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
91501e04c3fSmrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
91601e04c3fSmrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
91701e04c3fSmrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
91801e04c3fSmrg      case GL_VERTEX_SUBROUTINE:
91901e04c3fSmrg      case GL_GEOMETRY_SUBROUTINE:
92001e04c3fSmrg      case GL_FRAGMENT_SUBROUTINE:
92101e04c3fSmrg      case GL_COMPUTE_SUBROUTINE:
92201e04c3fSmrg      case GL_TESS_CONTROL_SUBROUTINE:
92301e04c3fSmrg      case GL_TESS_EVALUATION_SUBROUTINE:
92401e04c3fSmrg      case GL_BUFFER_VARIABLE:
92501e04c3fSmrg         if (++idx == (int) index)
92601e04c3fSmrg            return res;
92701e04c3fSmrg         break;
92801e04c3fSmrg      default:
92901e04c3fSmrg         assert(!"not implemented for given interface");
93001e04c3fSmrg      }
93101e04c3fSmrg   }
93201e04c3fSmrg   return NULL;
93301e04c3fSmrg}
93401e04c3fSmrg
93501e04c3fSmrg/* Function returns if resource name is expected to have index
93601e04c3fSmrg * appended into it.
93701e04c3fSmrg *
93801e04c3fSmrg *
93901e04c3fSmrg * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
94001e04c3fSmrg * spec says:
94101e04c3fSmrg *
94201e04c3fSmrg *     "If the active uniform is an array, the uniform name returned in
94301e04c3fSmrg *     name will always be the name of the uniform array appended with
94401e04c3fSmrg *     "[0]"."
94501e04c3fSmrg *
94601e04c3fSmrg * The same text also appears in the OpenGL 4.2 spec.  It does not,
94701e04c3fSmrg * however, appear in any previous spec.  Previous specifications are
94801e04c3fSmrg * ambiguous in this regard.  However, either name can later be passed
94901e04c3fSmrg * to glGetUniformLocation (and related APIs), so there shouldn't be any
95001e04c3fSmrg * harm in always appending "[0]" to uniform array names.
95101e04c3fSmrg */
95201e04c3fSmrgstatic bool
95301e04c3fSmrgadd_index_to_name(struct gl_program_resource *res)
95401e04c3fSmrg{
95501e04c3fSmrg   /* Transform feedback varyings have array index already appended
95601e04c3fSmrg    * in their names.
95701e04c3fSmrg    */
95801e04c3fSmrg   return res->Type != GL_TRANSFORM_FEEDBACK_VARYING;
95901e04c3fSmrg}
96001e04c3fSmrg
96101e04c3fSmrg/* Get name length of a program resource. This consists of
96201e04c3fSmrg * base name + 3 for '[0]' if resource is an array.
96301e04c3fSmrg */
96401e04c3fSmrgextern unsigned
96501e04c3fSmrg_mesa_program_resource_name_len(struct gl_program_resource *res)
96601e04c3fSmrg{
9677ec681f3Smrg   const char* name = _mesa_program_resource_name(res);
9687ec681f3Smrg
9697ec681f3Smrg   /* For shaders constructed from SPIR-V binaries, variables may not
9707ec681f3Smrg    * have names associated with them.
9717ec681f3Smrg    */
9727ec681f3Smrg   if (!name)
9737ec681f3Smrg      return 0;
9747ec681f3Smrg
9757ec681f3Smrg   unsigned length = strlen(name);
97601e04c3fSmrg   if (_mesa_program_resource_array_size(res) && add_index_to_name(res))
97701e04c3fSmrg      length += 3;
97801e04c3fSmrg   return length;
97901e04c3fSmrg}
980af69d88dSmrg
98101e04c3fSmrg/* Get full name of a program resource.
98201e04c3fSmrg */
98301e04c3fSmrgbool
98401e04c3fSmrg_mesa_get_program_resource_name(struct gl_shader_program *shProg,
98501e04c3fSmrg                                GLenum programInterface, GLuint index,
98601e04c3fSmrg                                GLsizei bufSize, GLsizei *length,
9877ec681f3Smrg                                GLchar *name, bool glthread,
9887ec681f3Smrg                                const char *caller)
98901e04c3fSmrg{
99001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
99101e04c3fSmrg
99201e04c3fSmrg   /* Find resource with given interface and index. */
99301e04c3fSmrg   struct gl_program_resource *res =
99401e04c3fSmrg      _mesa_program_resource_find_index(shProg, programInterface, index);
99501e04c3fSmrg
99601e04c3fSmrg   /* The error INVALID_VALUE is generated if <index> is greater than
99701e04c3fSmrg   * or equal to the number of entries in the active resource list for
99801e04c3fSmrg   * <programInterface>.
99901e04c3fSmrg   */
100001e04c3fSmrg   if (!res) {
10017ec681f3Smrg      _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
10027ec681f3Smrg                                "%s(index %u)", caller, index);
100301e04c3fSmrg      return false;
100401e04c3fSmrg   }
100501e04c3fSmrg
100601e04c3fSmrg   if (bufSize < 0) {
10077ec681f3Smrg      _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
10087ec681f3Smrg                                "%s(bufSize %d)", caller, bufSize);
100901e04c3fSmrg      return false;
101001e04c3fSmrg   }
101101e04c3fSmrg
101201e04c3fSmrg   GLsizei localLength;
101301e04c3fSmrg
101401e04c3fSmrg   if (length == NULL)
101501e04c3fSmrg      length = &localLength;
101601e04c3fSmrg
101701e04c3fSmrg   _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
101801e04c3fSmrg
10197ec681f3Smrg   /* The resource name can be NULL for shaders constructed from SPIR-V
10207ec681f3Smrg    * binaries. In that case, we do not add the '[0]'.
10217ec681f3Smrg    */
10227ec681f3Smrg   if (name && name[0] != '\0' &&
10237ec681f3Smrg       _mesa_program_resource_array_size(res) && add_index_to_name(res)) {
102401e04c3fSmrg      int i;
102501e04c3fSmrg
102601e04c3fSmrg      /* The comparison is strange because *length does *NOT* include the
102701e04c3fSmrg       * terminating NUL, but maxLength does.
102801e04c3fSmrg       */
102901e04c3fSmrg      for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
103001e04c3fSmrg         name[*length + i] = "[0]"[i];
103101e04c3fSmrg
103201e04c3fSmrg      name[*length + i] = '\0';
103301e04c3fSmrg      *length += i;
103401e04c3fSmrg   }
103501e04c3fSmrg   return true;
103601e04c3fSmrg}
103701e04c3fSmrg
103801e04c3fSmrgstatic GLint
103901e04c3fSmrgprogram_resource_location(struct gl_program_resource *res, unsigned array_index)
104001e04c3fSmrg{
104101e04c3fSmrg   switch (res->Type) {
104201e04c3fSmrg   case GL_PROGRAM_INPUT: {
104301e04c3fSmrg      const gl_shader_variable *var = RESOURCE_VAR(res);
104401e04c3fSmrg
104501e04c3fSmrg      if (var->location == -1)
104601e04c3fSmrg         return -1;
104701e04c3fSmrg
104801e04c3fSmrg      /* If the input is an array, fail if the index is out of bounds. */
104901e04c3fSmrg      if (array_index > 0
105001e04c3fSmrg          && array_index >= var->type->length) {
105101e04c3fSmrg         return -1;
105201e04c3fSmrg      }
105301e04c3fSmrg      return var->location +
105401e04c3fSmrg	     (array_index * var->type->without_array()->matrix_columns);
105501e04c3fSmrg   }
105601e04c3fSmrg   case GL_PROGRAM_OUTPUT:
105701e04c3fSmrg      if (RESOURCE_VAR(res)->location == -1)
105801e04c3fSmrg         return -1;
105901e04c3fSmrg
106001e04c3fSmrg      /* If the output is an array, fail if the index is out of bounds. */
106101e04c3fSmrg      if (array_index > 0
106201e04c3fSmrg          && array_index >= RESOURCE_VAR(res)->type->length) {
106301e04c3fSmrg         return -1;
106401e04c3fSmrg      }
106501e04c3fSmrg      return RESOURCE_VAR(res)->location + array_index;
106601e04c3fSmrg   case GL_UNIFORM:
106701e04c3fSmrg      /* If the uniform is built-in, fail. */
106801e04c3fSmrg      if (RESOURCE_UNI(res)->builtin)
106901e04c3fSmrg         return -1;
107001e04c3fSmrg
107101e04c3fSmrg     /* From page 79 of the OpenGL 4.2 spec:
107201e04c3fSmrg      *
107301e04c3fSmrg      *     "A valid name cannot be a structure, an array of structures, or any
107401e04c3fSmrg      *     portion of a single vector or a matrix."
107501e04c3fSmrg      */
1076b9abf16eSmaya      if (RESOURCE_UNI(res)->type->without_array()->is_struct())
107701e04c3fSmrg         return -1;
107801e04c3fSmrg
107901e04c3fSmrg      /* From the GL_ARB_uniform_buffer_object spec:
108001e04c3fSmrg       *
108101e04c3fSmrg       *     "The value -1 will be returned if <name> does not correspond to an
108201e04c3fSmrg       *     active uniform variable name in <program>, if <name> is associated
108301e04c3fSmrg       *     with a named uniform block, or if <name> starts with the reserved
108401e04c3fSmrg       *     prefix "gl_"."
108501e04c3fSmrg       */
108601e04c3fSmrg      if (RESOURCE_UNI(res)->block_index != -1 ||
108701e04c3fSmrg          RESOURCE_UNI(res)->atomic_buffer_index != -1)
108801e04c3fSmrg         return -1;
108901e04c3fSmrg
10907ec681f3Smrg      FALLTHROUGH;
109101e04c3fSmrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
109201e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
109301e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
109401e04c3fSmrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
109501e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
109601e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
109701e04c3fSmrg      /* If the uniform is an array, fail if the index is out of bounds. */
109801e04c3fSmrg      if (array_index > 0
109901e04c3fSmrg          && array_index >= RESOURCE_UNI(res)->array_elements) {
110001e04c3fSmrg         return -1;
110101e04c3fSmrg      }
110201e04c3fSmrg
110301e04c3fSmrg      /* location in remap table + array element offset */
110401e04c3fSmrg      return RESOURCE_UNI(res)->remap_location + array_index;
110501e04c3fSmrg   default:
110601e04c3fSmrg      return -1;
110701e04c3fSmrg   }
110801e04c3fSmrg}
110901e04c3fSmrg
111001e04c3fSmrg/**
111101e04c3fSmrg * Function implements following location queries:
111201e04c3fSmrg *    glGetUniformLocation
111301e04c3fSmrg */
111401e04c3fSmrgGLint
111501e04c3fSmrg_mesa_program_resource_location(struct gl_shader_program *shProg,
111601e04c3fSmrg                                GLenum programInterface, const char *name)
111701e04c3fSmrg{
111801e04c3fSmrg   unsigned array_index = 0;
111901e04c3fSmrg   struct gl_program_resource *res =
112001e04c3fSmrg      _mesa_program_resource_find_name(shProg, programInterface, name,
112101e04c3fSmrg                                       &array_index);
112201e04c3fSmrg
112301e04c3fSmrg   /* Resource not found. */
112401e04c3fSmrg   if (!res)
112501e04c3fSmrg      return -1;
112601e04c3fSmrg
112701e04c3fSmrg   return program_resource_location(res, array_index);
112801e04c3fSmrg}
112901e04c3fSmrg
11307ec681f3Smrgstatic GLint
11317ec681f3Smrg_get_resource_location_index(struct gl_program_resource *res)
113201e04c3fSmrg{
113301e04c3fSmrg   /* Non-existent variable or resource is not referenced by fragment stage. */
113401e04c3fSmrg   if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
113501e04c3fSmrg      return -1;
113601e04c3fSmrg
113701e04c3fSmrg   /* From OpenGL 4.5 spec, 7.3 Program Objects
113801e04c3fSmrg    * "The value -1 will be returned by either command...
113901e04c3fSmrg    *  ... or if name identifies an active variable that does not have a
114001e04c3fSmrg    * valid location assigned.
114101e04c3fSmrg    */
114201e04c3fSmrg   if (RESOURCE_VAR(res)->location == -1)
114301e04c3fSmrg      return -1;
114401e04c3fSmrg   return RESOURCE_VAR(res)->index;
114501e04c3fSmrg}
114601e04c3fSmrg
11477ec681f3Smrg/**
11487ec681f3Smrg * Function implements following index queries:
11497ec681f3Smrg *    glGetFragDataIndex
11507ec681f3Smrg */
11517ec681f3SmrgGLint
11527ec681f3Smrg_mesa_program_resource_location_index(struct gl_shader_program *shProg,
11537ec681f3Smrg                                      GLenum programInterface, const char *name)
11547ec681f3Smrg{
11557ec681f3Smrg   struct gl_program_resource *res =
11567ec681f3Smrg      _mesa_program_resource_find_name(shProg, programInterface, name, NULL);
11577ec681f3Smrg
11587ec681f3Smrg   return _get_resource_location_index(res);
11597ec681f3Smrg}
11607ec681f3Smrg
116101e04c3fSmrgstatic uint8_t
116201e04c3fSmrgstage_from_enum(GLenum ref)
116301e04c3fSmrg{
116401e04c3fSmrg   switch (ref) {
116501e04c3fSmrg   case GL_REFERENCED_BY_VERTEX_SHADER:
116601e04c3fSmrg      return MESA_SHADER_VERTEX;
116701e04c3fSmrg   case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
116801e04c3fSmrg      return MESA_SHADER_TESS_CTRL;
116901e04c3fSmrg   case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
117001e04c3fSmrg      return MESA_SHADER_TESS_EVAL;
117101e04c3fSmrg   case GL_REFERENCED_BY_GEOMETRY_SHADER:
117201e04c3fSmrg      return MESA_SHADER_GEOMETRY;
117301e04c3fSmrg   case GL_REFERENCED_BY_FRAGMENT_SHADER:
117401e04c3fSmrg      return MESA_SHADER_FRAGMENT;
117501e04c3fSmrg   case GL_REFERENCED_BY_COMPUTE_SHADER:
117601e04c3fSmrg      return MESA_SHADER_COMPUTE;
117701e04c3fSmrg   default:
117801e04c3fSmrg      assert(!"shader stage not supported");
117901e04c3fSmrg      return MESA_SHADER_STAGES;
118001e04c3fSmrg   }
118101e04c3fSmrg}
118201e04c3fSmrg
118301e04c3fSmrg/**
118401e04c3fSmrg * Check if resource is referenced by given 'referenced by' stage enum.
118501e04c3fSmrg * ATC and UBO resources hold stage references of their own.
118601e04c3fSmrg */
118701e04c3fSmrgstatic bool
118801e04c3fSmrgis_resource_referenced(struct gl_shader_program *shProg,
118901e04c3fSmrg                       struct gl_program_resource *res,
119001e04c3fSmrg                       GLuint index, uint8_t stage)
119101e04c3fSmrg{
119201e04c3fSmrg   /* First, check if we even have such a stage active. */
119301e04c3fSmrg   if (!shProg->_LinkedShaders[stage])
119401e04c3fSmrg      return false;
119501e04c3fSmrg
119601e04c3fSmrg   if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
119701e04c3fSmrg      return RESOURCE_ATC(res)->StageReferences[stage];
119801e04c3fSmrg
119901e04c3fSmrg   if (res->Type == GL_UNIFORM_BLOCK)
120001e04c3fSmrg      return shProg->data->UniformBlocks[index].stageref & (1 << stage);
120101e04c3fSmrg
120201e04c3fSmrg   if (res->Type == GL_SHADER_STORAGE_BLOCK)
120301e04c3fSmrg      return shProg->data->ShaderStorageBlocks[index].stageref & (1 << stage);
120401e04c3fSmrg
120501e04c3fSmrg   return res->StageReferences & (1 << stage);
120601e04c3fSmrg}
120701e04c3fSmrg
120801e04c3fSmrgstatic unsigned
120901e04c3fSmrgget_buffer_property(struct gl_shader_program *shProg,
121001e04c3fSmrg                    struct gl_program_resource *res, const GLenum prop,
12117ec681f3Smrg                    GLint *val, bool glthread, const char *caller)
121201e04c3fSmrg{
121301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
121401e04c3fSmrg   if (res->Type != GL_UNIFORM_BLOCK &&
121501e04c3fSmrg       res->Type != GL_ATOMIC_COUNTER_BUFFER &&
121601e04c3fSmrg       res->Type != GL_SHADER_STORAGE_BLOCK &&
121701e04c3fSmrg       res->Type != GL_TRANSFORM_FEEDBACK_BUFFER)
121801e04c3fSmrg      goto invalid_operation;
121901e04c3fSmrg
122001e04c3fSmrg   if (res->Type == GL_UNIFORM_BLOCK) {
122101e04c3fSmrg      switch (prop) {
122201e04c3fSmrg      case GL_BUFFER_BINDING:
122301e04c3fSmrg         *val = RESOURCE_UBO(res)->Binding;
122401e04c3fSmrg         return 1;
122501e04c3fSmrg      case GL_BUFFER_DATA_SIZE:
122601e04c3fSmrg         *val = RESOURCE_UBO(res)->UniformBufferSize;
122701e04c3fSmrg         return 1;
122801e04c3fSmrg      case GL_NUM_ACTIVE_VARIABLES:
122901e04c3fSmrg         *val = 0;
123001e04c3fSmrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
123101e04c3fSmrg            struct gl_program_resource *uni =
12327ec681f3Smrg               _mesa_program_resource_find_active_variable(
12337ec681f3Smrg                  shProg,
12347ec681f3Smrg                  GL_UNIFORM,
12357ec681f3Smrg                  RESOURCE_UBO(res),
12367ec681f3Smrg                  i);
12377ec681f3Smrg
123801e04c3fSmrg            if (!uni)
123901e04c3fSmrg               continue;
124001e04c3fSmrg            (*val)++;
124101e04c3fSmrg         }
124201e04c3fSmrg         return 1;
124301e04c3fSmrg      case GL_ACTIVE_VARIABLES: {
124401e04c3fSmrg         unsigned num_values = 0;
124501e04c3fSmrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
124601e04c3fSmrg            struct gl_program_resource *uni =
12477ec681f3Smrg               _mesa_program_resource_find_active_variable(
12487ec681f3Smrg                  shProg,
12497ec681f3Smrg                  GL_UNIFORM,
12507ec681f3Smrg                  RESOURCE_UBO(res),
12517ec681f3Smrg                  i);
12527ec681f3Smrg
125301e04c3fSmrg            if (!uni)
125401e04c3fSmrg               continue;
125501e04c3fSmrg            *val++ =
125601e04c3fSmrg               _mesa_program_resource_index(shProg, uni);
125701e04c3fSmrg            num_values++;
125801e04c3fSmrg         }
125901e04c3fSmrg         return num_values;
126001e04c3fSmrg      }
126101e04c3fSmrg      }
126201e04c3fSmrg   } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
126301e04c3fSmrg      switch (prop) {
126401e04c3fSmrg      case GL_BUFFER_BINDING:
126501e04c3fSmrg         *val = RESOURCE_UBO(res)->Binding;
126601e04c3fSmrg         return 1;
126701e04c3fSmrg      case GL_BUFFER_DATA_SIZE:
126801e04c3fSmrg         *val = RESOURCE_UBO(res)->UniformBufferSize;
126901e04c3fSmrg         return 1;
127001e04c3fSmrg      case GL_NUM_ACTIVE_VARIABLES:
127101e04c3fSmrg         *val = 0;
127201e04c3fSmrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
127301e04c3fSmrg            struct gl_program_resource *uni =
12747ec681f3Smrg               _mesa_program_resource_find_active_variable(
12757ec681f3Smrg                  shProg,
12767ec681f3Smrg                  GL_BUFFER_VARIABLE,
12777ec681f3Smrg                  RESOURCE_UBO(res),
12787ec681f3Smrg                  i);
12797ec681f3Smrg
128001e04c3fSmrg            if (!uni)
128101e04c3fSmrg               continue;
128201e04c3fSmrg            (*val)++;
128301e04c3fSmrg         }
128401e04c3fSmrg         return 1;
128501e04c3fSmrg      case GL_ACTIVE_VARIABLES: {
128601e04c3fSmrg         unsigned num_values = 0;
128701e04c3fSmrg         for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
128801e04c3fSmrg            struct gl_program_resource *uni =
12897ec681f3Smrg               _mesa_program_resource_find_active_variable(
12907ec681f3Smrg                  shProg,
12917ec681f3Smrg                  GL_BUFFER_VARIABLE,
12927ec681f3Smrg                  RESOURCE_UBO(res),
12937ec681f3Smrg                  i);
12947ec681f3Smrg
129501e04c3fSmrg            if (!uni)
129601e04c3fSmrg               continue;
129701e04c3fSmrg            *val++ =
129801e04c3fSmrg               _mesa_program_resource_index(shProg, uni);
129901e04c3fSmrg            num_values++;
130001e04c3fSmrg         }
130101e04c3fSmrg         return num_values;
130201e04c3fSmrg      }
130301e04c3fSmrg      }
130401e04c3fSmrg   } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
130501e04c3fSmrg      switch (prop) {
130601e04c3fSmrg      case GL_BUFFER_BINDING:
130701e04c3fSmrg         *val = RESOURCE_ATC(res)->Binding;
130801e04c3fSmrg         return 1;
130901e04c3fSmrg      case GL_BUFFER_DATA_SIZE:
131001e04c3fSmrg         *val = RESOURCE_ATC(res)->MinimumSize;
131101e04c3fSmrg         return 1;
131201e04c3fSmrg      case GL_NUM_ACTIVE_VARIABLES:
131301e04c3fSmrg         *val = RESOURCE_ATC(res)->NumUniforms;
131401e04c3fSmrg         return 1;
131501e04c3fSmrg      case GL_ACTIVE_VARIABLES:
131601e04c3fSmrg         for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) {
131701e04c3fSmrg            /* Active atomic buffer contains index to UniformStorage. Find
131801e04c3fSmrg             * out gl_program_resource via data pointer and then calculate
131901e04c3fSmrg             * index of that uniform.
132001e04c3fSmrg             */
132101e04c3fSmrg            unsigned idx = RESOURCE_ATC(res)->Uniforms[i];
132201e04c3fSmrg            struct gl_program_resource *uni =
132301e04c3fSmrg               program_resource_find_data(shProg,
132401e04c3fSmrg                                          &shProg->data->UniformStorage[idx]);
132501e04c3fSmrg            assert(uni);
132601e04c3fSmrg            *val++ = _mesa_program_resource_index(shProg, uni);
132701e04c3fSmrg         }
132801e04c3fSmrg         return RESOURCE_ATC(res)->NumUniforms;
132901e04c3fSmrg      }
133001e04c3fSmrg   } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) {
133101e04c3fSmrg      switch (prop) {
133201e04c3fSmrg      case GL_BUFFER_BINDING:
133301e04c3fSmrg         *val = RESOURCE_XFB(res)->Binding;
133401e04c3fSmrg         return 1;
133501e04c3fSmrg      case GL_NUM_ACTIVE_VARIABLES:
133601e04c3fSmrg         *val = RESOURCE_XFB(res)->NumVaryings;
133701e04c3fSmrg         return 1;
133801e04c3fSmrg      case GL_ACTIVE_VARIABLES:
133901e04c3fSmrg         struct gl_transform_feedback_info *linked_xfb =
134001e04c3fSmrg            shProg->last_vert_prog->sh.LinkedTransformFeedback;
134101e04c3fSmrg         for (int i = 0; i < linked_xfb->NumVarying; i++) {
134201e04c3fSmrg            unsigned index = linked_xfb->Varyings[i].BufferIndex;
134301e04c3fSmrg            struct gl_program_resource *buf_res =
134401e04c3fSmrg               _mesa_program_resource_find_index(shProg,
134501e04c3fSmrg                                                 GL_TRANSFORM_FEEDBACK_BUFFER,
134601e04c3fSmrg                                                 index);
134701e04c3fSmrg            assert(buf_res);
134801e04c3fSmrg            if (res == buf_res) {
134901e04c3fSmrg               *val++ = i;
135001e04c3fSmrg            }
135101e04c3fSmrg         }
135201e04c3fSmrg         return RESOURCE_XFB(res)->NumVaryings;
135301e04c3fSmrg      }
135401e04c3fSmrg   }
135501e04c3fSmrg   assert(!"support for property type not implemented");
135601e04c3fSmrg
135701e04c3fSmrginvalid_operation:
13587ec681f3Smrg   _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
13597ec681f3Smrg                             "%s(%s prop %s)", caller,
13607ec681f3Smrg                             _mesa_enum_to_string(res->Type),
13617ec681f3Smrg                             _mesa_enum_to_string(prop));
136201e04c3fSmrg
136301e04c3fSmrg   return 0;
136401e04c3fSmrg}
136501e04c3fSmrg
136601e04c3fSmrgunsigned
136701e04c3fSmrg_mesa_program_resource_prop(struct gl_shader_program *shProg,
136801e04c3fSmrg                            struct gl_program_resource *res, GLuint index,
13697ec681f3Smrg                            const GLenum prop, GLint *val, bool glthread,
13707ec681f3Smrg                            const char *caller)
137101e04c3fSmrg{
137201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
137301e04c3fSmrg
137401e04c3fSmrg#define VALIDATE_TYPE(type)\
137501e04c3fSmrg   if (res->Type != type)\
137601e04c3fSmrg      goto invalid_operation;
137701e04c3fSmrg
137801e04c3fSmrg#define VALIDATE_TYPE_2(type1, type2)\
137901e04c3fSmrg   if (res->Type != type1 && res->Type != type2)\
138001e04c3fSmrg      goto invalid_operation;
138101e04c3fSmrg
138201e04c3fSmrg   switch(prop) {
138301e04c3fSmrg   case GL_NAME_LENGTH:
138401e04c3fSmrg      switch (res->Type) {
138501e04c3fSmrg      case GL_ATOMIC_COUNTER_BUFFER:
138601e04c3fSmrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
138701e04c3fSmrg         goto invalid_operation;
138801e04c3fSmrg      default:
138901e04c3fSmrg         /* Resource name length + terminator. */
139001e04c3fSmrg         *val = _mesa_program_resource_name_len(res) + 1;
139101e04c3fSmrg      }
139201e04c3fSmrg      return 1;
139301e04c3fSmrg   case GL_TYPE:
139401e04c3fSmrg      switch (res->Type) {
139501e04c3fSmrg      case GL_UNIFORM:
139601e04c3fSmrg      case GL_BUFFER_VARIABLE:
139701e04c3fSmrg         *val = RESOURCE_UNI(res)->type->gl_type;
13987ec681f3Smrg         *val = mediump_to_highp_type(*val);
139901e04c3fSmrg         return 1;
140001e04c3fSmrg      case GL_PROGRAM_INPUT:
140101e04c3fSmrg      case GL_PROGRAM_OUTPUT:
140201e04c3fSmrg         *val = RESOURCE_VAR(res)->type->gl_type;
14037ec681f3Smrg         *val = mediump_to_highp_type(*val);
140401e04c3fSmrg         return 1;
140501e04c3fSmrg      case GL_TRANSFORM_FEEDBACK_VARYING:
140601e04c3fSmrg         *val = RESOURCE_XFV(res)->Type;
14077ec681f3Smrg         *val = mediump_to_highp_type(*val);
140801e04c3fSmrg         return 1;
140901e04c3fSmrg      default:
141001e04c3fSmrg         goto invalid_operation;
141101e04c3fSmrg      }
141201e04c3fSmrg   case GL_ARRAY_SIZE:
141301e04c3fSmrg      switch (res->Type) {
141401e04c3fSmrg      case GL_UNIFORM:
141501e04c3fSmrg      case GL_BUFFER_VARIABLE:
141601e04c3fSmrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
141701e04c3fSmrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
141801e04c3fSmrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
141901e04c3fSmrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
142001e04c3fSmrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
142101e04c3fSmrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
142201e04c3fSmrg
142301e04c3fSmrg         /* Test if a buffer variable is an array or an unsized array.
142401e04c3fSmrg          * Unsized arrays return zero as array size.
142501e04c3fSmrg          */
142601e04c3fSmrg         if (RESOURCE_UNI(res)->is_shader_storage &&
142701e04c3fSmrg             RESOURCE_UNI(res)->array_stride > 0)
142801e04c3fSmrg            *val = RESOURCE_UNI(res)->array_elements;
142901e04c3fSmrg         else
143001e04c3fSmrg            *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
143101e04c3fSmrg         return 1;
143201e04c3fSmrg      case GL_PROGRAM_INPUT:
143301e04c3fSmrg      case GL_PROGRAM_OUTPUT:
143401e04c3fSmrg         *val = MAX2(_mesa_program_resource_array_size(res), 1);
143501e04c3fSmrg         return 1;
143601e04c3fSmrg      case GL_TRANSFORM_FEEDBACK_VARYING:
143701e04c3fSmrg         *val = RESOURCE_XFV(res)->Size;
143801e04c3fSmrg         return 1;
143901e04c3fSmrg      default:
144001e04c3fSmrg         goto invalid_operation;
144101e04c3fSmrg      }
144201e04c3fSmrg   case GL_OFFSET:
144301e04c3fSmrg      switch (res->Type) {
144401e04c3fSmrg      case GL_UNIFORM:
144501e04c3fSmrg      case GL_BUFFER_VARIABLE:
144601e04c3fSmrg         *val = RESOURCE_UNI(res)->offset;
144701e04c3fSmrg         return 1;
144801e04c3fSmrg      case GL_TRANSFORM_FEEDBACK_VARYING:
144901e04c3fSmrg         *val = RESOURCE_XFV(res)->Offset;
145001e04c3fSmrg         return 1;
145101e04c3fSmrg      default:
145201e04c3fSmrg         goto invalid_operation;
145301e04c3fSmrg      }
145401e04c3fSmrg   case GL_BLOCK_INDEX:
145501e04c3fSmrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
145601e04c3fSmrg      *val = RESOURCE_UNI(res)->block_index;
145701e04c3fSmrg      return 1;
145801e04c3fSmrg   case GL_ARRAY_STRIDE:
145901e04c3fSmrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
146001e04c3fSmrg      *val = RESOURCE_UNI(res)->array_stride;
146101e04c3fSmrg      return 1;
146201e04c3fSmrg   case GL_MATRIX_STRIDE:
146301e04c3fSmrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
146401e04c3fSmrg      *val = RESOURCE_UNI(res)->matrix_stride;
146501e04c3fSmrg      return 1;
146601e04c3fSmrg   case GL_IS_ROW_MAJOR:
146701e04c3fSmrg      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
146801e04c3fSmrg      *val = RESOURCE_UNI(res)->row_major;
146901e04c3fSmrg      return 1;
147001e04c3fSmrg   case GL_ATOMIC_COUNTER_BUFFER_INDEX:
147101e04c3fSmrg      VALIDATE_TYPE(GL_UNIFORM);
147201e04c3fSmrg      *val = RESOURCE_UNI(res)->atomic_buffer_index;
147301e04c3fSmrg      return 1;
147401e04c3fSmrg   case GL_BUFFER_BINDING:
147501e04c3fSmrg   case GL_BUFFER_DATA_SIZE:
147601e04c3fSmrg   case GL_NUM_ACTIVE_VARIABLES:
147701e04c3fSmrg   case GL_ACTIVE_VARIABLES:
14787ec681f3Smrg      return get_buffer_property(shProg, res, prop, val, glthread, caller);
147901e04c3fSmrg   case GL_REFERENCED_BY_COMPUTE_SHADER:
148001e04c3fSmrg      if (!_mesa_has_compute_shaders(ctx))
148101e04c3fSmrg         goto invalid_enum;
14827ec681f3Smrg      FALLTHROUGH;
148301e04c3fSmrg   case GL_REFERENCED_BY_VERTEX_SHADER:
148401e04c3fSmrg   case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
148501e04c3fSmrg   case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
148601e04c3fSmrg   case GL_REFERENCED_BY_GEOMETRY_SHADER:
148701e04c3fSmrg   case GL_REFERENCED_BY_FRAGMENT_SHADER:
148801e04c3fSmrg      switch (res->Type) {
148901e04c3fSmrg      case GL_UNIFORM:
149001e04c3fSmrg      case GL_PROGRAM_INPUT:
149101e04c3fSmrg      case GL_PROGRAM_OUTPUT:
149201e04c3fSmrg      case GL_UNIFORM_BLOCK:
149301e04c3fSmrg      case GL_BUFFER_VARIABLE:
149401e04c3fSmrg      case GL_SHADER_STORAGE_BLOCK:
149501e04c3fSmrg      case GL_ATOMIC_COUNTER_BUFFER:
149601e04c3fSmrg         *val = is_resource_referenced(shProg, res, index,
149701e04c3fSmrg                                       stage_from_enum(prop));
149801e04c3fSmrg         return 1;
149901e04c3fSmrg      default:
150001e04c3fSmrg         goto invalid_operation;
150101e04c3fSmrg      }
150201e04c3fSmrg   case GL_LOCATION:
150301e04c3fSmrg      switch (res->Type) {
150401e04c3fSmrg      case GL_UNIFORM:
150501e04c3fSmrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
150601e04c3fSmrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
150701e04c3fSmrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
150801e04c3fSmrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
150901e04c3fSmrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
151001e04c3fSmrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
151101e04c3fSmrg      case GL_PROGRAM_INPUT:
151201e04c3fSmrg      case GL_PROGRAM_OUTPUT:
151301e04c3fSmrg         *val = program_resource_location(res, 0);
151401e04c3fSmrg         return 1;
151501e04c3fSmrg      default:
151601e04c3fSmrg         goto invalid_operation;
151701e04c3fSmrg      }
151801e04c3fSmrg   case GL_LOCATION_COMPONENT:
151901e04c3fSmrg      switch (res->Type) {
152001e04c3fSmrg      case GL_PROGRAM_INPUT:
152101e04c3fSmrg      case GL_PROGRAM_OUTPUT:
152201e04c3fSmrg         *val = RESOURCE_VAR(res)->component;
152301e04c3fSmrg         return 1;
152401e04c3fSmrg      default:
152501e04c3fSmrg         goto invalid_operation;
152601e04c3fSmrg      }
152701e04c3fSmrg   case GL_LOCATION_INDEX: {
152801e04c3fSmrg      int tmp;
152901e04c3fSmrg      if (res->Type != GL_PROGRAM_OUTPUT)
153001e04c3fSmrg         goto invalid_operation;
153101e04c3fSmrg      tmp = program_resource_location(res, 0);
153201e04c3fSmrg      if (tmp == -1)
153301e04c3fSmrg         *val = -1;
153401e04c3fSmrg      else
15357ec681f3Smrg         *val = _get_resource_location_index(res);
153601e04c3fSmrg      return 1;
153701e04c3fSmrg   }
153801e04c3fSmrg   case GL_NUM_COMPATIBLE_SUBROUTINES:
153901e04c3fSmrg      if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
154001e04c3fSmrg          res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
154101e04c3fSmrg          res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
154201e04c3fSmrg          res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
154301e04c3fSmrg          res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
154401e04c3fSmrg          res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
154501e04c3fSmrg         goto invalid_operation;
154601e04c3fSmrg      *val = RESOURCE_UNI(res)->num_compatible_subroutines;
154701e04c3fSmrg      return 1;
154801e04c3fSmrg   case GL_COMPATIBLE_SUBROUTINES: {
154901e04c3fSmrg      const struct gl_uniform_storage *uni;
155001e04c3fSmrg      struct gl_program *p;
155101e04c3fSmrg      unsigned count, i;
155201e04c3fSmrg      int j;
155301e04c3fSmrg
155401e04c3fSmrg      if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM &&
155501e04c3fSmrg          res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM &&
155601e04c3fSmrg          res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM &&
155701e04c3fSmrg          res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM &&
155801e04c3fSmrg          res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM &&
155901e04c3fSmrg          res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM)
156001e04c3fSmrg         goto invalid_operation;
156101e04c3fSmrg      uni = RESOURCE_UNI(res);
156201e04c3fSmrg
156301e04c3fSmrg      p = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]->Program;
156401e04c3fSmrg      count = 0;
156501e04c3fSmrg      for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
156601e04c3fSmrg         struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
156701e04c3fSmrg         for (j = 0; j < fn->num_compat_types; j++) {
156801e04c3fSmrg            if (fn->types[j] == uni->type) {
156901e04c3fSmrg               val[count++] = i;
157001e04c3fSmrg               break;
157101e04c3fSmrg            }
157201e04c3fSmrg         }
157301e04c3fSmrg      }
157401e04c3fSmrg      return count;
157501e04c3fSmrg   }
157601e04c3fSmrg
157701e04c3fSmrg   case GL_TOP_LEVEL_ARRAY_SIZE:
157801e04c3fSmrg      VALIDATE_TYPE(GL_BUFFER_VARIABLE);
157901e04c3fSmrg      *val = RESOURCE_UNI(res)->top_level_array_size;
158001e04c3fSmrg      return 1;
158101e04c3fSmrg
158201e04c3fSmrg   case GL_TOP_LEVEL_ARRAY_STRIDE:
158301e04c3fSmrg      VALIDATE_TYPE(GL_BUFFER_VARIABLE);
158401e04c3fSmrg      *val = RESOURCE_UNI(res)->top_level_array_stride;
158501e04c3fSmrg      return 1;
158601e04c3fSmrg
158701e04c3fSmrg   /* GL_ARB_tessellation_shader */
158801e04c3fSmrg   case GL_IS_PER_PATCH:
158901e04c3fSmrg      switch (res->Type) {
159001e04c3fSmrg      case GL_PROGRAM_INPUT:
159101e04c3fSmrg      case GL_PROGRAM_OUTPUT:
159201e04c3fSmrg         *val = RESOURCE_VAR(res)->patch;
159301e04c3fSmrg         return 1;
159401e04c3fSmrg      default:
159501e04c3fSmrg         goto invalid_operation;
159601e04c3fSmrg      }
159701e04c3fSmrg
159801e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX:
159901e04c3fSmrg      VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING);
160001e04c3fSmrg      *val = RESOURCE_XFV(res)->BufferIndex;
160101e04c3fSmrg      return 1;
160201e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE:
160301e04c3fSmrg      VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER);
160401e04c3fSmrg      *val = RESOURCE_XFB(res)->Stride * 4;
160501e04c3fSmrg      return 1;
160601e04c3fSmrg
160701e04c3fSmrg   default:
160801e04c3fSmrg      goto invalid_enum;
160901e04c3fSmrg   }
161001e04c3fSmrg
161101e04c3fSmrg#undef VALIDATE_TYPE
161201e04c3fSmrg#undef VALIDATE_TYPE_2
161301e04c3fSmrg
161401e04c3fSmrginvalid_enum:
16157ec681f3Smrg   _mesa_error_glthread_safe(ctx, GL_INVALID_ENUM, glthread,
16167ec681f3Smrg                             "%s(%s prop %s)", caller,
16177ec681f3Smrg                             _mesa_enum_to_string(res->Type),
16187ec681f3Smrg                             _mesa_enum_to_string(prop));
161901e04c3fSmrg   return 0;
162001e04c3fSmrg
162101e04c3fSmrginvalid_operation:
16227ec681f3Smrg   _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
16237ec681f3Smrg                             "%s(%s prop %s)", caller,
16247ec681f3Smrg                             _mesa_enum_to_string(res->Type),
16257ec681f3Smrg                             _mesa_enum_to_string(prop));
162601e04c3fSmrg   return 0;
162701e04c3fSmrg}
162801e04c3fSmrg
162901e04c3fSmrgextern void
163001e04c3fSmrg_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
163101e04c3fSmrg                             GLenum programInterface, GLuint index, GLsizei propCount,
163201e04c3fSmrg                             const GLenum *props, GLsizei bufSize,
163301e04c3fSmrg                             GLsizei *length, GLint *params)
163401e04c3fSmrg{
163501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
163601e04c3fSmrg   GLint *val = (GLint *) params;
163701e04c3fSmrg   const GLenum *prop = props;
163801e04c3fSmrg   GLsizei amount = 0;
163901e04c3fSmrg
164001e04c3fSmrg   struct gl_program_resource *res =
164101e04c3fSmrg      _mesa_program_resource_find_index(shProg, programInterface, index);
164201e04c3fSmrg
164301e04c3fSmrg   /* No such resource found or bufSize negative. */
164401e04c3fSmrg   if (!res || bufSize < 0) {
164501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
164601e04c3fSmrg                  "glGetProgramResourceiv(%s index %d bufSize %d)",
164701e04c3fSmrg                  _mesa_enum_to_string(programInterface), index, bufSize);
164801e04c3fSmrg      return;
164901e04c3fSmrg   }
165001e04c3fSmrg
165101e04c3fSmrg   /* Write propCount values until error occurs or bufSize reached. */
165201e04c3fSmrg   for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
165301e04c3fSmrg      int props_written =
165401e04c3fSmrg         _mesa_program_resource_prop(shProg, res, index, *prop, val,
16557ec681f3Smrg                                     false, "glGetProgramResourceiv");
165601e04c3fSmrg
165701e04c3fSmrg      /* Error happened. */
165801e04c3fSmrg      if (props_written == 0)
165901e04c3fSmrg         return;
166001e04c3fSmrg
166101e04c3fSmrg      amount += props_written;
166201e04c3fSmrg   }
166301e04c3fSmrg
166401e04c3fSmrg   /* If <length> is not NULL, the actual number of integer values
166501e04c3fSmrg    * written to <params> will be written to <length>.
166601e04c3fSmrg    */
166701e04c3fSmrg   if (length)
166801e04c3fSmrg      *length = amount;
166901e04c3fSmrg}
167001e04c3fSmrg
16717ec681f3Smrgextern void
16727ec681f3Smrg_mesa_get_program_interfaceiv(struct gl_shader_program *shProg,
16737ec681f3Smrg                              GLenum programInterface, GLenum pname,
16747ec681f3Smrg                              GLint *params)
16757ec681f3Smrg{
16767ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
16777ec681f3Smrg   unsigned i;
16787ec681f3Smrg
16797ec681f3Smrg   /* Validate pname against interface. */
16807ec681f3Smrg   switch(pname) {
16817ec681f3Smrg   case GL_ACTIVE_RESOURCES:
16827ec681f3Smrg      for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++)
16837ec681f3Smrg         if (shProg->data->ProgramResourceList[i].Type == programInterface)
16847ec681f3Smrg            (*params)++;
16857ec681f3Smrg      break;
16867ec681f3Smrg   case GL_MAX_NAME_LENGTH:
16877ec681f3Smrg      if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
16887ec681f3Smrg          programInterface == GL_TRANSFORM_FEEDBACK_BUFFER) {
16897ec681f3Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
16907ec681f3Smrg                     "glGetProgramInterfaceiv(%s pname %s)",
16917ec681f3Smrg                     _mesa_enum_to_string(programInterface),
16927ec681f3Smrg                     _mesa_enum_to_string(pname));
16937ec681f3Smrg         return;
16947ec681f3Smrg      }
16957ec681f3Smrg      /* Name length consists of base name, 3 additional chars '[0]' if
16967ec681f3Smrg       * resource is an array and finally 1 char for string terminator.
16977ec681f3Smrg       */
16987ec681f3Smrg      for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
16997ec681f3Smrg         if (shProg->data->ProgramResourceList[i].Type != programInterface)
17007ec681f3Smrg            continue;
17017ec681f3Smrg         unsigned len =
17027ec681f3Smrg            _mesa_program_resource_name_len(&shProg->data->ProgramResourceList[i]);
17037ec681f3Smrg         *params = MAX2((unsigned)*params, len + 1);
17047ec681f3Smrg      }
17057ec681f3Smrg      break;
17067ec681f3Smrg   case GL_MAX_NUM_ACTIVE_VARIABLES:
17077ec681f3Smrg      switch (programInterface) {
17087ec681f3Smrg      case GL_UNIFORM_BLOCK:
17097ec681f3Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
17107ec681f3Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
17117ec681f3Smrg               struct gl_uniform_block *block =
17127ec681f3Smrg                  (struct gl_uniform_block *)
17137ec681f3Smrg                  shProg->data->ProgramResourceList[i].Data;
17147ec681f3Smrg               *params = MAX2((unsigned)*params, block->NumUniforms);
17157ec681f3Smrg            }
17167ec681f3Smrg         }
17177ec681f3Smrg         break;
17187ec681f3Smrg      case GL_SHADER_STORAGE_BLOCK:
17197ec681f3Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
17207ec681f3Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
17217ec681f3Smrg               struct gl_uniform_block *block =
17227ec681f3Smrg                  (struct gl_uniform_block *)
17237ec681f3Smrg                  shProg->data->ProgramResourceList[i].Data;
17247ec681f3Smrg               GLint block_params = 0;
17257ec681f3Smrg               for (unsigned j = 0; j < block->NumUniforms; j++) {
17267ec681f3Smrg                  struct gl_program_resource *uni =
17277ec681f3Smrg                     _mesa_program_resource_find_active_variable(
17287ec681f3Smrg                        shProg,
17297ec681f3Smrg                        GL_BUFFER_VARIABLE,
17307ec681f3Smrg                        block,
17317ec681f3Smrg                        j);
17327ec681f3Smrg                  if (!uni)
17337ec681f3Smrg                     continue;
17347ec681f3Smrg                  block_params++;
17357ec681f3Smrg               }
17367ec681f3Smrg               *params = MAX2(*params, block_params);
17377ec681f3Smrg            }
17387ec681f3Smrg         }
17397ec681f3Smrg         break;
17407ec681f3Smrg      case GL_ATOMIC_COUNTER_BUFFER:
17417ec681f3Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
17427ec681f3Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
17437ec681f3Smrg               struct gl_active_atomic_buffer *buffer =
17447ec681f3Smrg                  (struct gl_active_atomic_buffer *)
17457ec681f3Smrg                  shProg->data->ProgramResourceList[i].Data;
17467ec681f3Smrg               *params = MAX2((unsigned)*params, buffer->NumUniforms);
17477ec681f3Smrg            }
17487ec681f3Smrg         }
17497ec681f3Smrg         break;
17507ec681f3Smrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
17517ec681f3Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
17527ec681f3Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
17537ec681f3Smrg               struct gl_transform_feedback_buffer *buffer =
17547ec681f3Smrg                  (struct gl_transform_feedback_buffer *)
17557ec681f3Smrg                  shProg->data->ProgramResourceList[i].Data;
17567ec681f3Smrg               *params = MAX2((unsigned)*params, buffer->NumVaryings);
17577ec681f3Smrg            }
17587ec681f3Smrg         }
17597ec681f3Smrg         break;
17607ec681f3Smrg      default:
17617ec681f3Smrg        _mesa_error(ctx, GL_INVALID_OPERATION,
17627ec681f3Smrg                    "glGetProgramInterfaceiv(%s pname %s)",
17637ec681f3Smrg                    _mesa_enum_to_string(programInterface),
17647ec681f3Smrg                    _mesa_enum_to_string(pname));
17657ec681f3Smrg      }
17667ec681f3Smrg      break;
17677ec681f3Smrg   case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
17687ec681f3Smrg      switch (programInterface) {
17697ec681f3Smrg      case GL_VERTEX_SUBROUTINE_UNIFORM:
17707ec681f3Smrg      case GL_FRAGMENT_SUBROUTINE_UNIFORM:
17717ec681f3Smrg      case GL_GEOMETRY_SUBROUTINE_UNIFORM:
17727ec681f3Smrg      case GL_COMPUTE_SUBROUTINE_UNIFORM:
17737ec681f3Smrg      case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
17747ec681f3Smrg      case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
17757ec681f3Smrg         for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) {
17767ec681f3Smrg            if (shProg->data->ProgramResourceList[i].Type == programInterface) {
17777ec681f3Smrg               struct gl_uniform_storage *uni =
17787ec681f3Smrg                  (struct gl_uniform_storage *)
17797ec681f3Smrg                  shProg->data->ProgramResourceList[i].Data;
17807ec681f3Smrg               *params = MAX2((unsigned)*params, uni->num_compatible_subroutines);
17817ec681f3Smrg            }
17827ec681f3Smrg         }
17837ec681f3Smrg         break;
17847ec681f3Smrg      }
17857ec681f3Smrg
17867ec681f3Smrg      default:
17877ec681f3Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
17887ec681f3Smrg                     "glGetProgramInterfaceiv(%s pname %s)",
17897ec681f3Smrg                     _mesa_enum_to_string(programInterface),
17907ec681f3Smrg                     _mesa_enum_to_string(pname));
17917ec681f3Smrg      }
17927ec681f3Smrg      break;
17937ec681f3Smrg   default:
17947ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
17957ec681f3Smrg                  "glGetProgramInterfaceiv(pname %s)",
17967ec681f3Smrg                  _mesa_enum_to_string(pname));
17977ec681f3Smrg   }
17987ec681f3Smrg}
17997ec681f3Smrg
180001e04c3fSmrgstatic bool
180101e04c3fSmrgvalidate_io(struct gl_program *producer, struct gl_program *consumer)
180201e04c3fSmrg{
180301e04c3fSmrg   if (producer->sh.data->linked_stages == consumer->sh.data->linked_stages)
180401e04c3fSmrg      return true;
180501e04c3fSmrg
180601e04c3fSmrg   const bool producer_is_array_stage =
180701e04c3fSmrg      producer->info.stage == MESA_SHADER_TESS_CTRL;
180801e04c3fSmrg   const bool consumer_is_array_stage =
180901e04c3fSmrg      consumer->info.stage == MESA_SHADER_GEOMETRY ||
181001e04c3fSmrg      consumer->info.stage == MESA_SHADER_TESS_CTRL ||
181101e04c3fSmrg      consumer->info.stage == MESA_SHADER_TESS_EVAL;
181201e04c3fSmrg
181301e04c3fSmrg   bool valid = true;
181401e04c3fSmrg
181501e04c3fSmrg   gl_shader_variable const **outputs =
181601e04c3fSmrg      (gl_shader_variable const **) calloc(producer->sh.data->NumProgramResourceList,
181701e04c3fSmrg                                           sizeof(gl_shader_variable *));
181801e04c3fSmrg   if (outputs == NULL)
181901e04c3fSmrg      return false;
182001e04c3fSmrg
182101e04c3fSmrg   /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
182201e04c3fSmrg    * says:
182301e04c3fSmrg    *
182401e04c3fSmrg    *    At an interface between program objects, the set of inputs and
182501e04c3fSmrg    *    outputs are considered to match exactly if and only if:
182601e04c3fSmrg    *
182701e04c3fSmrg    *    - Every declared input variable has a matching output, as described
182801e04c3fSmrg    *      above.
182901e04c3fSmrg    *    - There are no user-defined output variables declared without a
183001e04c3fSmrg    *      matching input variable declaration.
183101e04c3fSmrg    *
183201e04c3fSmrg    * Every input has an output, and every output has an input.  Scan the list
183301e04c3fSmrg    * of producer resources once, and generate the list of outputs.  As inputs
183401e04c3fSmrg    * and outputs are matched, remove the matched outputs from the set.  At
183501e04c3fSmrg    * the end, the set must be empty.  If the set is not empty, then there is
183601e04c3fSmrg    * some output that did not have an input.
183701e04c3fSmrg    */
183801e04c3fSmrg   unsigned num_outputs = 0;
183901e04c3fSmrg   for (unsigned i = 0; i < producer->sh.data->NumProgramResourceList; i++) {
184001e04c3fSmrg      struct gl_program_resource *res =
184101e04c3fSmrg         &producer->sh.data->ProgramResourceList[i];
184201e04c3fSmrg
184301e04c3fSmrg      if (res->Type != GL_PROGRAM_OUTPUT)
184401e04c3fSmrg         continue;
184501e04c3fSmrg
184601e04c3fSmrg      gl_shader_variable const *const var = RESOURCE_VAR(res);
184701e04c3fSmrg
184801e04c3fSmrg      /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
184901e04c3fSmrg       * says:
185001e04c3fSmrg       *
185101e04c3fSmrg       *    Built-in inputs or outputs do not affect interface matching.
185201e04c3fSmrg       */
185301e04c3fSmrg      if (is_gl_identifier(var->name))
185401e04c3fSmrg         continue;
185501e04c3fSmrg
185601e04c3fSmrg      outputs[num_outputs++] = var;
185701e04c3fSmrg   }
185801e04c3fSmrg
185901e04c3fSmrg   unsigned match_index = 0;
186001e04c3fSmrg   for (unsigned i = 0; i < consumer->sh.data->NumProgramResourceList; i++) {
186101e04c3fSmrg      struct gl_program_resource *res =
186201e04c3fSmrg         &consumer->sh.data->ProgramResourceList[i];
186301e04c3fSmrg
186401e04c3fSmrg      if (res->Type != GL_PROGRAM_INPUT)
186501e04c3fSmrg         continue;
186601e04c3fSmrg
186701e04c3fSmrg      gl_shader_variable const *const consumer_var = RESOURCE_VAR(res);
186801e04c3fSmrg      gl_shader_variable const *producer_var = NULL;
186901e04c3fSmrg
187001e04c3fSmrg      if (is_gl_identifier(consumer_var->name))
187101e04c3fSmrg         continue;
187201e04c3fSmrg
187301e04c3fSmrg      /* Inputs with explicit locations match other outputs with explicit
187401e04c3fSmrg       * locations by location instead of by name.
187501e04c3fSmrg       */
187601e04c3fSmrg      if (consumer_var->explicit_location) {
187701e04c3fSmrg         for (unsigned j = 0; j < num_outputs; j++) {
187801e04c3fSmrg            const gl_shader_variable *const var = outputs[j];
187901e04c3fSmrg
188001e04c3fSmrg            if (var->explicit_location &&
188101e04c3fSmrg                consumer_var->location == var->location) {
188201e04c3fSmrg               producer_var = var;
188301e04c3fSmrg               match_index = j;
188401e04c3fSmrg               break;
188501e04c3fSmrg            }
188601e04c3fSmrg         }
188701e04c3fSmrg      } else {
188801e04c3fSmrg         for (unsigned j = 0; j < num_outputs; j++) {
188901e04c3fSmrg            const gl_shader_variable *const var = outputs[j];
189001e04c3fSmrg
189101e04c3fSmrg            if (!var->explicit_location &&
189201e04c3fSmrg                strcmp(consumer_var->name, var->name) == 0) {
189301e04c3fSmrg               producer_var = var;
189401e04c3fSmrg               match_index = j;
189501e04c3fSmrg               break;
189601e04c3fSmrg            }
189701e04c3fSmrg         }
189801e04c3fSmrg      }
189901e04c3fSmrg
190001e04c3fSmrg      /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
190101e04c3fSmrg       * says:
190201e04c3fSmrg       *
190301e04c3fSmrg       *    - An output variable is considered to match an input variable in
190401e04c3fSmrg       *      the subsequent shader if:
190501e04c3fSmrg       *
190601e04c3fSmrg       *      - the two variables match in name, type, and qualification; or
190701e04c3fSmrg       *
190801e04c3fSmrg       *      - the two variables are declared with the same location
190901e04c3fSmrg       *        qualifier and match in type and qualification.
191001e04c3fSmrg       */
191101e04c3fSmrg      if (producer_var == NULL) {
191201e04c3fSmrg         valid = false;
191301e04c3fSmrg         goto out;
191401e04c3fSmrg      }
191501e04c3fSmrg
191601e04c3fSmrg      /* An output cannot match more than one input, so remove the output from
191701e04c3fSmrg       * the set of possible outputs.
191801e04c3fSmrg       */
191901e04c3fSmrg      outputs[match_index] = NULL;
192001e04c3fSmrg      num_outputs--;
192101e04c3fSmrg      if (match_index < num_outputs)
192201e04c3fSmrg         outputs[match_index] = outputs[num_outputs];
192301e04c3fSmrg
192401e04c3fSmrg      /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says:
192501e04c3fSmrg       *
192601e04c3fSmrg       *    "Tessellation control shader per-vertex output variables and
192701e04c3fSmrg       *     blocks and tessellation control, tessellation evaluation, and
192801e04c3fSmrg       *     geometry shader per-vertex input variables and blocks are
192901e04c3fSmrg       *     required to be declared as arrays, with each element representing
193001e04c3fSmrg       *     input or output values for a single vertex of a multi-vertex
193101e04c3fSmrg       *     primitive. For the purposes of interface matching, such variables
193201e04c3fSmrg       *     and blocks are treated as though they were not declared as
193301e04c3fSmrg       *     arrays."
193401e04c3fSmrg       *
193501e04c3fSmrg       * So we unwrap those types before matching.
193601e04c3fSmrg       */
193701e04c3fSmrg      const glsl_type *consumer_type = consumer_var->type;
193801e04c3fSmrg      const glsl_type *consumer_interface_type = consumer_var->interface_type;
193901e04c3fSmrg      const glsl_type *producer_type = producer_var->type;
194001e04c3fSmrg      const glsl_type *producer_interface_type = producer_var->interface_type;
194101e04c3fSmrg
194201e04c3fSmrg      if (consumer_is_array_stage) {
194301e04c3fSmrg         if (consumer_interface_type) {
194401e04c3fSmrg            /* the interface is the array; the underlying types should match */
194501e04c3fSmrg            if (consumer_interface_type->is_array() && !consumer_var->patch)
194601e04c3fSmrg               consumer_interface_type = consumer_interface_type->fields.array;
194701e04c3fSmrg         } else {
194801e04c3fSmrg            if (consumer_type->is_array() && !consumer_var->patch)
194901e04c3fSmrg               consumer_type = consumer_type->fields.array;
195001e04c3fSmrg         }
195101e04c3fSmrg      }
195201e04c3fSmrg
195301e04c3fSmrg      if (producer_is_array_stage) {
195401e04c3fSmrg         if (producer_interface_type) {
195501e04c3fSmrg            /* the interface is the array; the underlying types should match */
195601e04c3fSmrg            if (producer_interface_type->is_array() && !producer_var->patch)
195701e04c3fSmrg               producer_interface_type = producer_interface_type->fields.array;
195801e04c3fSmrg         } else {
195901e04c3fSmrg            if (producer_type->is_array() && !producer_var->patch)
196001e04c3fSmrg               producer_type = producer_type->fields.array;
196101e04c3fSmrg         }
196201e04c3fSmrg      }
196301e04c3fSmrg
196401e04c3fSmrg      if (producer_type != consumer_type) {
196501e04c3fSmrg         valid = false;
196601e04c3fSmrg         goto out;
196701e04c3fSmrg      }
196801e04c3fSmrg
196901e04c3fSmrg      if (producer_interface_type != consumer_interface_type) {
197001e04c3fSmrg         valid = false;
197101e04c3fSmrg         goto out;
197201e04c3fSmrg      }
197301e04c3fSmrg
197401e04c3fSmrg      /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
197501e04c3fSmrg       *
197601e04c3fSmrg       *    Qualifier Class|  Qualifier  |in/out
197701e04c3fSmrg       *    ---------------+-------------+------
197801e04c3fSmrg       *    Storage        |     in      |
197901e04c3fSmrg       *                   |     out     |  N/A
198001e04c3fSmrg       *                   |   uniform   |
198101e04c3fSmrg       *    ---------------+-------------+------
198201e04c3fSmrg       *    Auxiliary      |   centroid  |   No
198301e04c3fSmrg       *    ---------------+-------------+------
198401e04c3fSmrg       *                   |   location  |  Yes
198501e04c3fSmrg       *                   | Block layout|  N/A
198601e04c3fSmrg       *                   |   binding   |  N/A
198701e04c3fSmrg       *                   |   offset    |  N/A
198801e04c3fSmrg       *                   |   format    |  N/A
198901e04c3fSmrg       *    ---------------+-------------+------
199001e04c3fSmrg       *    Interpolation  |   smooth    |
199101e04c3fSmrg       *                   |    flat     |  Yes
199201e04c3fSmrg       *    ---------------+-------------+------
199301e04c3fSmrg       *                   |    lowp     |
199401e04c3fSmrg       *    Precision      |   mediump   |  Yes
199501e04c3fSmrg       *                   |    highp    |
199601e04c3fSmrg       *    ---------------+-------------+------
199701e04c3fSmrg       *    Variance       |  invariant  |   No
199801e04c3fSmrg       *    ---------------+-------------+------
199901e04c3fSmrg       *    Memory         |     all     |  N/A
200001e04c3fSmrg       *
200101e04c3fSmrg       * Note that location mismatches are detected by the loops above that
200201e04c3fSmrg       * find the producer variable that goes with the consumer variable.
200301e04c3fSmrg       */
200401e04c3fSmrg      unsigned producer_interpolation = producer_var->interpolation;
200501e04c3fSmrg      unsigned consumer_interpolation = consumer_var->interpolation;
200601e04c3fSmrg      if (producer_interpolation == INTERP_MODE_NONE)
200701e04c3fSmrg         producer_interpolation = INTERP_MODE_SMOOTH;
200801e04c3fSmrg      if (consumer_interpolation == INTERP_MODE_NONE)
200901e04c3fSmrg         consumer_interpolation = INTERP_MODE_SMOOTH;
201001e04c3fSmrg      if (producer_interpolation != consumer_interpolation) {
201101e04c3fSmrg         valid = false;
201201e04c3fSmrg         goto out;
201301e04c3fSmrg      }
201401e04c3fSmrg
201501e04c3fSmrg      if (producer_var->precision != consumer_var->precision) {
201601e04c3fSmrg         valid = false;
201701e04c3fSmrg         goto out;
201801e04c3fSmrg      }
201901e04c3fSmrg
202001e04c3fSmrg      if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
202101e04c3fSmrg         valid = false;
202201e04c3fSmrg         goto out;
202301e04c3fSmrg      }
202401e04c3fSmrg   }
202501e04c3fSmrg
202601e04c3fSmrg out:
202701e04c3fSmrg   free(outputs);
202801e04c3fSmrg   return valid && num_outputs == 0;
202901e04c3fSmrg}
203001e04c3fSmrg
203101e04c3fSmrg/**
203201e04c3fSmrg * Validate inputs against outputs in a program pipeline.
203301e04c3fSmrg */
203401e04c3fSmrgextern "C" bool
203501e04c3fSmrg_mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline)
203601e04c3fSmrg{
203701e04c3fSmrg   struct gl_program **prog = (struct gl_program **) pipeline->CurrentProgram;
203801e04c3fSmrg
203901e04c3fSmrg   /* Find first active stage in pipeline. */
204001e04c3fSmrg   unsigned idx, prev = 0;
204101e04c3fSmrg   for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
204201e04c3fSmrg      if (prog[idx]) {
204301e04c3fSmrg         prev = idx;
204401e04c3fSmrg         break;
204501e04c3fSmrg      }
204601e04c3fSmrg   }
204701e04c3fSmrg
204801e04c3fSmrg   for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
204901e04c3fSmrg      if (prog[idx]) {
205001e04c3fSmrg         /* Pipeline might include both non-compute and a compute program, do
205101e04c3fSmrg          * not attempt to validate varyings between non-compute and compute
205201e04c3fSmrg          * stage.
205301e04c3fSmrg          */
205401e04c3fSmrg         if (prog[idx]->info.stage == MESA_SHADER_COMPUTE)
205501e04c3fSmrg            break;
205601e04c3fSmrg
205701e04c3fSmrg         if (!validate_io(prog[prev], prog[idx]))
205801e04c3fSmrg            return false;
205901e04c3fSmrg
206001e04c3fSmrg         prev = idx;
206101e04c3fSmrg      }
206201e04c3fSmrg   }
206301e04c3fSmrg   return true;
2064af69d88dSmrg}
20657ec681f3Smrg
20667ec681f3Smrgextern "C" void
20677ec681f3Smrg_mesa_create_program_resource_hash(struct gl_shader_program *shProg)
20687ec681f3Smrg{
20697ec681f3Smrg   /* Rebuild resource hash. */
20707ec681f3Smrg   if (shProg->data->ProgramResourceHash)
20717ec681f3Smrg      _mesa_hash_table_u64_destroy(shProg->data->ProgramResourceHash);
20727ec681f3Smrg
20737ec681f3Smrg   shProg->data->ProgramResourceHash = _mesa_hash_table_u64_create(shProg);
20747ec681f3Smrg
20757ec681f3Smrg   struct gl_program_resource *res = shProg->data->ProgramResourceList;
20767ec681f3Smrg   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
20777ec681f3Smrg      const char *name = _mesa_program_resource_name(res);
20787ec681f3Smrg      if (name) {
20797ec681f3Smrg         uint32_t key = compute_resource_key(res->Type, name, strlen(name));
20807ec681f3Smrg         _mesa_hash_table_u64_insert(shProg->data->ProgramResourceHash, key,
20817ec681f3Smrg                                     res);
20827ec681f3Smrg      }
20837ec681f3Smrg   }
20847ec681f3Smrg}
2085