1848b8605Smrg/* 2848b8605Smrg * Copyright © 2011 Intel Corporation 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21848b8605Smrg * DEALINGS IN THE SOFTWARE. 22848b8605Smrg */ 23848b8605Smrg 24848b8605Smrg/** 25848b8605Smrg * \file shader_query.cpp 26848b8605Smrg * C-to-C++ bridge functions to query GLSL shader data 27848b8605Smrg * 28848b8605Smrg * \author Ian Romanick <ian.d.romanick@intel.com> 29848b8605Smrg */ 30848b8605Smrg 31b8e80941Smrg#include "main/context.h" 32b8e80941Smrg#include "main/enums.h" 33b8e80941Smrg#include "main/shaderapi.h" 34b8e80941Smrg#include "main/shaderobj.h" 35b8e80941Smrg#include "main/uniforms.h" 36b8e80941Smrg#include "compiler/glsl/glsl_symbol_table.h" 37b8e80941Smrg#include "compiler/glsl/ir.h" 38b8e80941Smrg#include "compiler/glsl/program.h" 39b8e80941Smrg#include "compiler/glsl/string_to_uint_map.h" 40848b8605Smrg 41848b8605Smrg 42b8e80941Smrgstatic GLint 43b8e80941Smrgprogram_resource_location(struct gl_program_resource *res, 44b8e80941Smrg unsigned array_index); 45848b8605Smrg 46b8e80941Smrg/** 47b8e80941Smrg * Declare convenience functions to return resource data in a given type. 48b8e80941Smrg * Warning! this is not type safe so be *very* careful when using these. 49b8e80941Smrg */ 50b8e80941Smrg#define DECL_RESOURCE_FUNC(name, type) \ 51b8e80941Smrgconst type * RESOURCE_ ## name (gl_program_resource *res) { \ 52b8e80941Smrg assert(res->Data); \ 53b8e80941Smrg return (type *) res->Data; \ 54b8e80941Smrg} 55848b8605Smrg 56b8e80941SmrgDECL_RESOURCE_FUNC(VAR, gl_shader_variable); 57b8e80941SmrgDECL_RESOURCE_FUNC(UBO, gl_uniform_block); 58b8e80941SmrgDECL_RESOURCE_FUNC(UNI, gl_uniform_storage); 59b8e80941SmrgDECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer); 60b8e80941SmrgDECL_RESOURCE_FUNC(XFV, gl_transform_feedback_varying_info); 61b8e80941SmrgDECL_RESOURCE_FUNC(XFB, gl_transform_feedback_buffer); 62b8e80941SmrgDECL_RESOURCE_FUNC(SUB, gl_subroutine_function); 63b8e80941Smrg 64b8e80941Smrgstatic void 65b8e80941Smrgbind_attrib_location(struct gl_context *ctx, 66b8e80941Smrg struct gl_shader_program *const shProg, GLuint index, 67b8e80941Smrg const GLchar *name, bool no_error) 68b8e80941Smrg{ 69848b8605Smrg if (!name) 70848b8605Smrg return; 71848b8605Smrg 72b8e80941Smrg if (!no_error) { 73b8e80941Smrg if (strncmp(name, "gl_", 3) == 0) { 74b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 75b8e80941Smrg "glBindAttribLocation(illegal name)"); 76b8e80941Smrg return; 77b8e80941Smrg } 78848b8605Smrg 79b8e80941Smrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 80b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(%u >= %u)", 81b8e80941Smrg index, ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs); 82b8e80941Smrg return; 83b8e80941Smrg } 84848b8605Smrg } 85848b8605Smrg 86848b8605Smrg /* Replace the current value if it's already in the list. Add 87848b8605Smrg * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates 88848b8605Smrg * between built-in attributes and user-defined attributes. 89848b8605Smrg */ 90848b8605Smrg shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name); 91848b8605Smrg 92848b8605Smrg /* 93848b8605Smrg * Note that this attribute binding won't go into effect until 94848b8605Smrg * glLinkProgram is called again. 95848b8605Smrg */ 96848b8605Smrg} 97848b8605Smrg 98b8e80941Smrgvoid GLAPIENTRY 99b8e80941Smrg_mesa_BindAttribLocation_no_error(GLuint program, GLuint index, 100b8e80941Smrg const GLchar *name) 101848b8605Smrg{ 102b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 103848b8605Smrg 104b8e80941Smrg struct gl_shader_program *const shProg = 105b8e80941Smrg _mesa_lookup_shader_program(ctx, program); 106b8e80941Smrg bind_attrib_location(ctx, shProg, index, name, true); 107b8e80941Smrg} 108848b8605Smrg 109b8e80941Smrgvoid GLAPIENTRY 110b8e80941Smrg_mesa_BindAttribLocation(GLuint program, GLuint index, 111b8e80941Smrg const GLchar *name) 112b8e80941Smrg{ 113b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 114848b8605Smrg 115b8e80941Smrg struct gl_shader_program *const shProg = 116b8e80941Smrg _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation"); 117b8e80941Smrg if (!shProg) 118b8e80941Smrg return; 119b8e80941Smrg 120b8e80941Smrg bind_attrib_location(ctx, shProg, index, name, false); 121848b8605Smrg} 122848b8605Smrg 123848b8605Smrgvoid GLAPIENTRY 124b8e80941Smrg_mesa_GetActiveAttrib(GLuint program, GLuint desired_index, 125b8e80941Smrg GLsizei maxLength, GLsizei * length, GLint * size, 126b8e80941Smrg GLenum * type, GLchar * name) 127848b8605Smrg{ 128848b8605Smrg GET_CURRENT_CONTEXT(ctx); 129848b8605Smrg struct gl_shader_program *shProg; 130848b8605Smrg 131b8e80941Smrg if (maxLength < 0) { 132b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(maxLength < 0)"); 133b8e80941Smrg return; 134b8e80941Smrg } 135b8e80941Smrg 136848b8605Smrg shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); 137848b8605Smrg if (!shProg) 138848b8605Smrg return; 139848b8605Smrg 140b8e80941Smrg if (!shProg->data->LinkStatus) { 141848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 142848b8605Smrg "glGetActiveAttrib(program not linked)"); 143848b8605Smrg return; 144848b8605Smrg } 145848b8605Smrg 146848b8605Smrg if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 147848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)"); 148848b8605Smrg return; 149848b8605Smrg } 150848b8605Smrg 151b8e80941Smrg struct gl_program_resource *res = 152b8e80941Smrg _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT, 153b8e80941Smrg desired_index); 154848b8605Smrg 155b8e80941Smrg /* User asked for index that does not exist. */ 156b8e80941Smrg if (!res) { 157b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); 158b8e80941Smrg return; 159848b8605Smrg } 160848b8605Smrg 161b8e80941Smrg const gl_shader_variable *const var = RESOURCE_VAR(res); 162848b8605Smrg 163b8e80941Smrg const char *var_name = var->name; 164848b8605Smrg 165b8e80941Smrg _mesa_copy_string(name, maxLength, length, var_name); 166848b8605Smrg 167b8e80941Smrg if (size) 168b8e80941Smrg _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE, 169b8e80941Smrg size, "glGetActiveAttrib"); 170848b8605Smrg 171b8e80941Smrg if (type) 172b8e80941Smrg _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE, 173b8e80941Smrg (GLint *) type, "glGetActiveAttrib"); 174848b8605Smrg} 175848b8605Smrg 176848b8605SmrgGLint GLAPIENTRY 177b8e80941Smrg_mesa_GetAttribLocation(GLuint program, const GLchar * name) 178848b8605Smrg{ 179848b8605Smrg GET_CURRENT_CONTEXT(ctx); 180848b8605Smrg struct gl_shader_program *const shProg = 181848b8605Smrg _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); 182848b8605Smrg 183848b8605Smrg if (!shProg) { 184848b8605Smrg return -1; 185848b8605Smrg } 186848b8605Smrg 187b8e80941Smrg if (!shProg->data->LinkStatus) { 188848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 189848b8605Smrg "glGetAttribLocation(program not linked)"); 190848b8605Smrg return -1; 191848b8605Smrg } 192848b8605Smrg 193848b8605Smrg if (!name) 194848b8605Smrg return -1; 195848b8605Smrg 196848b8605Smrg /* Not having a vertex shader is not an error. 197848b8605Smrg */ 198848b8605Smrg if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) 199848b8605Smrg return -1; 200848b8605Smrg 201b8e80941Smrg unsigned array_index = 0; 202b8e80941Smrg struct gl_program_resource *res = 203b8e80941Smrg _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name, 204b8e80941Smrg &array_index); 205848b8605Smrg 206b8e80941Smrg if (!res) 207b8e80941Smrg return -1; 208848b8605Smrg 209b8e80941Smrg return program_resource_location(res, array_index); 210848b8605Smrg} 211848b8605Smrg 212848b8605Smrgunsigned 213848b8605Smrg_mesa_count_active_attribs(struct gl_shader_program *shProg) 214848b8605Smrg{ 215b8e80941Smrg if (!shProg->data->LinkStatus 216848b8605Smrg || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 217848b8605Smrg return 0; 218848b8605Smrg } 219848b8605Smrg 220b8e80941Smrg struct gl_program_resource *res = shProg->data->ProgramResourceList; 221b8e80941Smrg unsigned count = 0; 222b8e80941Smrg for (unsigned j = 0; j < shProg->data->NumProgramResourceList; 223b8e80941Smrg j++, res++) { 224b8e80941Smrg if (res->Type == GL_PROGRAM_INPUT && 225b8e80941Smrg res->StageReferences & (1 << MESA_SHADER_VERTEX)) 226b8e80941Smrg count++; 227848b8605Smrg } 228b8e80941Smrg return count; 229848b8605Smrg} 230848b8605Smrg 231848b8605Smrg 232848b8605Smrgsize_t 233848b8605Smrg_mesa_longest_attribute_name_length(struct gl_shader_program *shProg) 234848b8605Smrg{ 235b8e80941Smrg if (!shProg->data->LinkStatus 236848b8605Smrg || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 237848b8605Smrg return 0; 238848b8605Smrg } 239848b8605Smrg 240b8e80941Smrg struct gl_program_resource *res = shProg->data->ProgramResourceList; 241848b8605Smrg size_t longest = 0; 242b8e80941Smrg for (unsigned j = 0; j < shProg->data->NumProgramResourceList; 243b8e80941Smrg j++, res++) { 244b8e80941Smrg if (res->Type == GL_PROGRAM_INPUT && 245b8e80941Smrg res->StageReferences & (1 << MESA_SHADER_VERTEX)) { 246b8e80941Smrg 247b8e80941Smrg const size_t length = strlen(RESOURCE_VAR(res)->name); 248b8e80941Smrg if (length >= longest) 249b8e80941Smrg longest = length + 1; 250b8e80941Smrg } 251848b8605Smrg } 252848b8605Smrg 253848b8605Smrg return longest; 254848b8605Smrg} 255848b8605Smrg 256b8e80941Smrgvoid static 257b8e80941Smrgbind_frag_data_location(struct gl_shader_program *const shProg, 258b8e80941Smrg const char *name, unsigned colorNumber, 259b8e80941Smrg unsigned index) 260b8e80941Smrg{ 261b8e80941Smrg /* Replace the current value if it's already in the list. Add 262b8e80941Smrg * FRAG_RESULT_DATA0 because that's how the linker differentiates 263b8e80941Smrg * between built-in attributes and user-defined attributes. 264b8e80941Smrg */ 265b8e80941Smrg shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name); 266b8e80941Smrg shProg->FragDataIndexBindings->put(index, name); 267b8e80941Smrg 268b8e80941Smrg /* 269b8e80941Smrg * Note that this binding won't go into effect until 270b8e80941Smrg * glLinkProgram is called again. 271b8e80941Smrg */ 272b8e80941Smrg} 273b8e80941Smrg 274848b8605Smrgvoid GLAPIENTRY 275848b8605Smrg_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, 276848b8605Smrg const GLchar *name) 277848b8605Smrg{ 278848b8605Smrg _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name); 279848b8605Smrg} 280848b8605Smrg 281b8e80941Smrgvoid GLAPIENTRY 282b8e80941Smrg_mesa_BindFragDataLocation_no_error(GLuint program, GLuint colorNumber, 283b8e80941Smrg const GLchar *name) 284b8e80941Smrg{ 285b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 286b8e80941Smrg 287b8e80941Smrg if (!name) 288b8e80941Smrg return; 289b8e80941Smrg 290b8e80941Smrg struct gl_shader_program *const shProg = 291b8e80941Smrg _mesa_lookup_shader_program(ctx, program); 292b8e80941Smrg 293b8e80941Smrg bind_frag_data_location(shProg, name, colorNumber, 0); 294b8e80941Smrg} 295b8e80941Smrg 296848b8605Smrgvoid GLAPIENTRY 297848b8605Smrg_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber, 298848b8605Smrg GLuint index, const GLchar *name) 299848b8605Smrg{ 300848b8605Smrg GET_CURRENT_CONTEXT(ctx); 301848b8605Smrg 302848b8605Smrg struct gl_shader_program *const shProg = 303848b8605Smrg _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed"); 304848b8605Smrg if (!shProg) 305848b8605Smrg return; 306848b8605Smrg 307848b8605Smrg if (!name) 308848b8605Smrg return; 309848b8605Smrg 310848b8605Smrg if (strncmp(name, "gl_", 3) == 0) { 311848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)"); 312848b8605Smrg return; 313848b8605Smrg } 314848b8605Smrg 315848b8605Smrg if (index > 1) { 316848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)"); 317848b8605Smrg return; 318848b8605Smrg } 319848b8605Smrg 320848b8605Smrg if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) { 321848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)"); 322848b8605Smrg return; 323848b8605Smrg } 324848b8605Smrg 325848b8605Smrg if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) { 326848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)"); 327848b8605Smrg return; 328848b8605Smrg } 329848b8605Smrg 330b8e80941Smrg bind_frag_data_location(shProg, name, colorNumber, index); 331b8e80941Smrg} 332848b8605Smrg 333b8e80941Smrgvoid GLAPIENTRY 334b8e80941Smrg_mesa_BindFragDataLocationIndexed_no_error(GLuint program, GLuint colorNumber, 335b8e80941Smrg GLuint index, const GLchar *name) 336b8e80941Smrg{ 337b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 338b8e80941Smrg 339b8e80941Smrg if (!name) 340b8e80941Smrg return; 341b8e80941Smrg 342b8e80941Smrg struct gl_shader_program *const shProg = 343b8e80941Smrg _mesa_lookup_shader_program(ctx, program); 344b8e80941Smrg 345b8e80941Smrg bind_frag_data_location(shProg, name, colorNumber, index); 346848b8605Smrg} 347848b8605Smrg 348848b8605SmrgGLint GLAPIENTRY 349848b8605Smrg_mesa_GetFragDataIndex(GLuint program, const GLchar *name) 350848b8605Smrg{ 351848b8605Smrg GET_CURRENT_CONTEXT(ctx); 352848b8605Smrg struct gl_shader_program *const shProg = 353848b8605Smrg _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex"); 354848b8605Smrg 355848b8605Smrg if (!shProg) { 356848b8605Smrg return -1; 357848b8605Smrg } 358848b8605Smrg 359b8e80941Smrg if (!shProg->data->LinkStatus) { 360848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 361848b8605Smrg "glGetFragDataIndex(program not linked)"); 362848b8605Smrg return -1; 363848b8605Smrg } 364848b8605Smrg 365848b8605Smrg if (!name) 366848b8605Smrg return -1; 367848b8605Smrg 368848b8605Smrg if (strncmp(name, "gl_", 3) == 0) { 369848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 370848b8605Smrg "glGetFragDataIndex(illegal name)"); 371848b8605Smrg return -1; 372848b8605Smrg } 373848b8605Smrg 374848b8605Smrg /* Not having a fragment shader is not an error. 375848b8605Smrg */ 376848b8605Smrg if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) 377848b8605Smrg return -1; 378848b8605Smrg 379b8e80941Smrg return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, 380b8e80941Smrg name); 381848b8605Smrg} 382848b8605Smrg 383848b8605SmrgGLint GLAPIENTRY 384848b8605Smrg_mesa_GetFragDataLocation(GLuint program, const GLchar *name) 385848b8605Smrg{ 386848b8605Smrg GET_CURRENT_CONTEXT(ctx); 387848b8605Smrg struct gl_shader_program *const shProg = 388848b8605Smrg _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation"); 389848b8605Smrg 390848b8605Smrg if (!shProg) { 391848b8605Smrg return -1; 392848b8605Smrg } 393848b8605Smrg 394b8e80941Smrg if (!shProg->data->LinkStatus) { 395848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 396848b8605Smrg "glGetFragDataLocation(program not linked)"); 397848b8605Smrg return -1; 398848b8605Smrg } 399848b8605Smrg 400848b8605Smrg if (!name) 401848b8605Smrg return -1; 402848b8605Smrg 403848b8605Smrg if (strncmp(name, "gl_", 3) == 0) { 404848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 405848b8605Smrg "glGetFragDataLocation(illegal name)"); 406848b8605Smrg return -1; 407848b8605Smrg } 408848b8605Smrg 409848b8605Smrg /* Not having a fragment shader is not an error. 410848b8605Smrg */ 411848b8605Smrg if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) 412848b8605Smrg return -1; 413848b8605Smrg 414b8e80941Smrg unsigned array_index = 0; 415b8e80941Smrg struct gl_program_resource *res = 416b8e80941Smrg _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name, 417b8e80941Smrg &array_index); 418b8e80941Smrg 419b8e80941Smrg if (!res) 420b8e80941Smrg return -1; 421b8e80941Smrg 422b8e80941Smrg return program_resource_location(res, array_index); 423b8e80941Smrg} 424b8e80941Smrg 425b8e80941Smrgconst char* 426b8e80941Smrg_mesa_program_resource_name(struct gl_program_resource *res) 427b8e80941Smrg{ 428b8e80941Smrg switch (res->Type) { 429b8e80941Smrg case GL_UNIFORM_BLOCK: 430b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 431b8e80941Smrg return RESOURCE_UBO(res)->Name; 432b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 433b8e80941Smrg return RESOURCE_XFV(res)->Name; 434b8e80941Smrg case GL_PROGRAM_INPUT: 435b8e80941Smrg case GL_PROGRAM_OUTPUT: 436b8e80941Smrg return RESOURCE_VAR(res)->name; 437b8e80941Smrg case GL_UNIFORM: 438b8e80941Smrg case GL_BUFFER_VARIABLE: 439b8e80941Smrg return RESOURCE_UNI(res)->name; 440b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 441b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 442b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 443b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 444b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 445b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 446b8e80941Smrg return RESOURCE_UNI(res)->name + MESA_SUBROUTINE_PREFIX_LEN; 447b8e80941Smrg case GL_VERTEX_SUBROUTINE: 448b8e80941Smrg case GL_GEOMETRY_SUBROUTINE: 449b8e80941Smrg case GL_FRAGMENT_SUBROUTINE: 450b8e80941Smrg case GL_COMPUTE_SUBROUTINE: 451b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE: 452b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE: 453b8e80941Smrg return RESOURCE_SUB(res)->name; 454b8e80941Smrg default: 455b8e80941Smrg assert(!"support for resource type not implemented"); 456b8e80941Smrg } 457b8e80941Smrg return NULL; 458b8e80941Smrg} 459b8e80941Smrg 460b8e80941Smrg 461b8e80941Smrgunsigned 462b8e80941Smrg_mesa_program_resource_array_size(struct gl_program_resource *res) 463b8e80941Smrg{ 464b8e80941Smrg switch (res->Type) { 465b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 466b8e80941Smrg return RESOURCE_XFV(res)->Size > 1 ? 467b8e80941Smrg RESOURCE_XFV(res)->Size : 0; 468b8e80941Smrg case GL_PROGRAM_INPUT: 469b8e80941Smrg case GL_PROGRAM_OUTPUT: 470b8e80941Smrg return RESOURCE_VAR(res)->type->length; 471b8e80941Smrg case GL_UNIFORM: 472b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 473b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 474b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 475b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 476b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 477b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 478b8e80941Smrg return RESOURCE_UNI(res)->array_elements; 479b8e80941Smrg case GL_BUFFER_VARIABLE: 480b8e80941Smrg /* Unsized arrays */ 481b8e80941Smrg if (RESOURCE_UNI(res)->array_stride > 0 && 482b8e80941Smrg RESOURCE_UNI(res)->array_elements == 0) 483b8e80941Smrg return 1; 484b8e80941Smrg else 485b8e80941Smrg return RESOURCE_UNI(res)->array_elements; 486b8e80941Smrg case GL_VERTEX_SUBROUTINE: 487b8e80941Smrg case GL_GEOMETRY_SUBROUTINE: 488b8e80941Smrg case GL_FRAGMENT_SUBROUTINE: 489b8e80941Smrg case GL_COMPUTE_SUBROUTINE: 490b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE: 491b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE: 492b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 493b8e80941Smrg case GL_UNIFORM_BLOCK: 494b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 495b8e80941Smrg return 0; 496b8e80941Smrg default: 497b8e80941Smrg assert(!"support for resource type not implemented"); 498b8e80941Smrg } 499b8e80941Smrg return 0; 500b8e80941Smrg} 501b8e80941Smrg 502b8e80941Smrg/** 503b8e80941Smrg * Checks if array subscript is valid and if so sets array_index. 504b8e80941Smrg */ 505b8e80941Smrgstatic bool 506b8e80941Smrgvalid_array_index(const GLchar *name, unsigned *array_index) 507b8e80941Smrg{ 508b8e80941Smrg long idx = 0; 509b8e80941Smrg const GLchar *out_base_name_end; 510b8e80941Smrg 511b8e80941Smrg idx = parse_program_resource_name(name, &out_base_name_end); 512b8e80941Smrg if (idx < 0) 513b8e80941Smrg return false; 514b8e80941Smrg 515b8e80941Smrg if (array_index) 516b8e80941Smrg *array_index = idx; 517b8e80941Smrg 518b8e80941Smrg return true; 519b8e80941Smrg} 520b8e80941Smrg 521b8e80941Smrg/* Find a program resource with specific name in given interface. 522b8e80941Smrg */ 523b8e80941Smrgstruct gl_program_resource * 524b8e80941Smrg_mesa_program_resource_find_name(struct gl_shader_program *shProg, 525b8e80941Smrg GLenum programInterface, const char *name, 526b8e80941Smrg unsigned *array_index) 527b8e80941Smrg{ 528b8e80941Smrg struct gl_program_resource *res = shProg->data->ProgramResourceList; 529b8e80941Smrg for (unsigned i = 0; i < shProg->data->NumProgramResourceList; 530b8e80941Smrg i++, res++) { 531b8e80941Smrg if (res->Type != programInterface) 532b8e80941Smrg continue; 533b8e80941Smrg 534b8e80941Smrg /* Resource basename. */ 535b8e80941Smrg const char *rname = _mesa_program_resource_name(res); 536b8e80941Smrg 537b8e80941Smrg /* Since ARB_gl_spirv lack of name reflections is a possibility */ 538b8e80941Smrg if (rname == NULL) 539b8e80941Smrg continue; 540848b8605Smrg 541b8e80941Smrg unsigned baselen = strlen(rname); 542b8e80941Smrg unsigned baselen_without_array_index = baselen; 543b8e80941Smrg const char *rname_last_square_bracket = strrchr(rname, '['); 544b8e80941Smrg bool found = false; 545b8e80941Smrg bool rname_has_array_index_zero = false; 546b8e80941Smrg /* From ARB_program_interface_query spec: 547848b8605Smrg * 548b8e80941Smrg * "uint GetProgramResourceIndex(uint program, enum programInterface, 549b8e80941Smrg * const char *name); 550b8e80941Smrg * [...] 551b8e80941Smrg * If <name> exactly matches the name string of one of the active 552b8e80941Smrg * resources for <programInterface>, the index of the matched resource is 553b8e80941Smrg * returned. Additionally, if <name> would exactly match the name string 554b8e80941Smrg * of an active resource if "[0]" were appended to <name>, the index of 555b8e80941Smrg * the matched resource is returned. [...]" 556848b8605Smrg * 557b8e80941Smrg * "A string provided to GetProgramResourceLocation or 558b8e80941Smrg * GetProgramResourceLocationIndex is considered to match an active variable 559b8e80941Smrg * if: 560b8e80941Smrg * 561b8e80941Smrg * * the string exactly matches the name of the active variable; 562b8e80941Smrg * 563b8e80941Smrg * * if the string identifies the base name of an active array, where the 564b8e80941Smrg * string would exactly match the name of the variable if the suffix 565b8e80941Smrg * "[0]" were appended to the string; [...]" 566848b8605Smrg */ 567b8e80941Smrg /* Remove array's index from interface block name comparison only if 568b8e80941Smrg * array's index is zero and the resulting string length is the same 569b8e80941Smrg * than the provided name's length. 570b8e80941Smrg */ 571b8e80941Smrg if (rname_last_square_bracket) { 572b8e80941Smrg baselen_without_array_index -= strlen(rname_last_square_bracket); 573b8e80941Smrg rname_has_array_index_zero = 574b8e80941Smrg (strcmp(rname_last_square_bracket, "[0]") == 0) && 575b8e80941Smrg (baselen_without_array_index == strlen(name)); 576b8e80941Smrg } 577848b8605Smrg 578b8e80941Smrg if (strncmp(rname, name, baselen) == 0) 579b8e80941Smrg found = true; 580b8e80941Smrg else if (rname_has_array_index_zero && 581b8e80941Smrg strncmp(rname, name, baselen_without_array_index) == 0) 582b8e80941Smrg found = true; 583b8e80941Smrg 584b8e80941Smrg if (found) { 585b8e80941Smrg switch (programInterface) { 586b8e80941Smrg case GL_UNIFORM_BLOCK: 587b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 588b8e80941Smrg /* Basename match, check if array or struct. */ 589b8e80941Smrg if (rname_has_array_index_zero || 590b8e80941Smrg name[baselen] == '\0' || 591b8e80941Smrg name[baselen] == '[' || 592b8e80941Smrg name[baselen] == '.') { 593b8e80941Smrg return res; 594b8e80941Smrg } 595b8e80941Smrg break; 596b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 597b8e80941Smrg case GL_BUFFER_VARIABLE: 598b8e80941Smrg case GL_UNIFORM: 599b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 600b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 601b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 602b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 603b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 604b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 605b8e80941Smrg case GL_VERTEX_SUBROUTINE: 606b8e80941Smrg case GL_GEOMETRY_SUBROUTINE: 607b8e80941Smrg case GL_FRAGMENT_SUBROUTINE: 608b8e80941Smrg case GL_COMPUTE_SUBROUTINE: 609b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE: 610b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE: 611b8e80941Smrg if (name[baselen] == '.') { 612b8e80941Smrg return res; 613b8e80941Smrg } 614b8e80941Smrg /* fall-through */ 615b8e80941Smrg case GL_PROGRAM_INPUT: 616b8e80941Smrg case GL_PROGRAM_OUTPUT: 617b8e80941Smrg if (name[baselen] == '\0') { 618b8e80941Smrg return res; 619b8e80941Smrg } else if (name[baselen] == '[' && 620b8e80941Smrg valid_array_index(name, array_index)) { 621b8e80941Smrg return res; 622b8e80941Smrg } 623b8e80941Smrg break; 624b8e80941Smrg default: 625b8e80941Smrg assert(!"not implemented for given interface"); 626b8e80941Smrg } 627b8e80941Smrg } 628b8e80941Smrg } 629b8e80941Smrg return NULL; 630b8e80941Smrg} 631848b8605Smrg 632b8e80941Smrgstatic GLuint 633b8e80941Smrgcalc_resource_index(struct gl_shader_program *shProg, 634b8e80941Smrg struct gl_program_resource *res) 635b8e80941Smrg{ 636b8e80941Smrg unsigned i; 637b8e80941Smrg GLuint index = 0; 638b8e80941Smrg for (i = 0; i < shProg->data->NumProgramResourceList; i++) { 639b8e80941Smrg if (&shProg->data->ProgramResourceList[i] == res) 640b8e80941Smrg return index; 641b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type == res->Type) 642b8e80941Smrg index++; 643848b8605Smrg } 644b8e80941Smrg return GL_INVALID_INDEX; 645b8e80941Smrg} 646b8e80941Smrg 647b8e80941Smrg/** 648b8e80941Smrg * Calculate index for the given resource. 649b8e80941Smrg */ 650b8e80941SmrgGLuint 651b8e80941Smrg_mesa_program_resource_index(struct gl_shader_program *shProg, 652b8e80941Smrg struct gl_program_resource *res) 653b8e80941Smrg{ 654b8e80941Smrg if (!res) 655b8e80941Smrg return GL_INVALID_INDEX; 656b8e80941Smrg 657b8e80941Smrg switch (res->Type) { 658b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 659b8e80941Smrg return RESOURCE_ATC(res) - shProg->data->AtomicBuffers; 660b8e80941Smrg case GL_VERTEX_SUBROUTINE: 661b8e80941Smrg case GL_GEOMETRY_SUBROUTINE: 662b8e80941Smrg case GL_FRAGMENT_SUBROUTINE: 663b8e80941Smrg case GL_COMPUTE_SUBROUTINE: 664b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE: 665b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE: 666b8e80941Smrg return RESOURCE_SUB(res)->index; 667b8e80941Smrg case GL_UNIFORM_BLOCK: 668b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 669b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER: 670b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 671b8e80941Smrg default: 672b8e80941Smrg return calc_resource_index(shProg, res); 673b8e80941Smrg } 674b8e80941Smrg} 675b8e80941Smrg 676b8e80941Smrg/** 677b8e80941Smrg * Find a program resource that points to given data. 678b8e80941Smrg */ 679b8e80941Smrgstatic struct gl_program_resource* 680b8e80941Smrgprogram_resource_find_data(struct gl_shader_program *shProg, void *data) 681b8e80941Smrg{ 682b8e80941Smrg struct gl_program_resource *res = shProg->data->ProgramResourceList; 683b8e80941Smrg for (unsigned i = 0; i < shProg->data->NumProgramResourceList; 684b8e80941Smrg i++, res++) { 685b8e80941Smrg if (res->Data == data) 686b8e80941Smrg return res; 687b8e80941Smrg } 688b8e80941Smrg return NULL; 689b8e80941Smrg} 690b8e80941Smrg 691b8e80941Smrg/* Find a program resource with specific index in given interface. 692b8e80941Smrg */ 693b8e80941Smrgstruct gl_program_resource * 694b8e80941Smrg_mesa_program_resource_find_index(struct gl_shader_program *shProg, 695b8e80941Smrg GLenum programInterface, GLuint index) 696b8e80941Smrg{ 697b8e80941Smrg struct gl_program_resource *res = shProg->data->ProgramResourceList; 698b8e80941Smrg int idx = -1; 699b8e80941Smrg 700b8e80941Smrg for (unsigned i = 0; i < shProg->data->NumProgramResourceList; 701b8e80941Smrg i++, res++) { 702b8e80941Smrg if (res->Type != programInterface) 703b8e80941Smrg continue; 704b8e80941Smrg 705b8e80941Smrg switch (res->Type) { 706b8e80941Smrg case GL_UNIFORM_BLOCK: 707b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 708b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 709b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER: 710b8e80941Smrg if (_mesa_program_resource_index(shProg, res) == index) 711b8e80941Smrg return res; 712b8e80941Smrg break; 713b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 714b8e80941Smrg case GL_PROGRAM_INPUT: 715b8e80941Smrg case GL_PROGRAM_OUTPUT: 716b8e80941Smrg case GL_UNIFORM: 717b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 718b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 719b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 720b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 721b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 722b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 723b8e80941Smrg case GL_VERTEX_SUBROUTINE: 724b8e80941Smrg case GL_GEOMETRY_SUBROUTINE: 725b8e80941Smrg case GL_FRAGMENT_SUBROUTINE: 726b8e80941Smrg case GL_COMPUTE_SUBROUTINE: 727b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE: 728b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE: 729b8e80941Smrg case GL_BUFFER_VARIABLE: 730b8e80941Smrg if (++idx == (int) index) 731b8e80941Smrg return res; 732b8e80941Smrg break; 733b8e80941Smrg default: 734b8e80941Smrg assert(!"not implemented for given interface"); 735b8e80941Smrg } 736b8e80941Smrg } 737b8e80941Smrg return NULL; 738b8e80941Smrg} 739b8e80941Smrg 740b8e80941Smrg/* Function returns if resource name is expected to have index 741b8e80941Smrg * appended into it. 742b8e80941Smrg * 743b8e80941Smrg * 744b8e80941Smrg * Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0 745b8e80941Smrg * spec says: 746b8e80941Smrg * 747b8e80941Smrg * "If the active uniform is an array, the uniform name returned in 748b8e80941Smrg * name will always be the name of the uniform array appended with 749b8e80941Smrg * "[0]"." 750b8e80941Smrg * 751b8e80941Smrg * The same text also appears in the OpenGL 4.2 spec. It does not, 752b8e80941Smrg * however, appear in any previous spec. Previous specifications are 753b8e80941Smrg * ambiguous in this regard. However, either name can later be passed 754b8e80941Smrg * to glGetUniformLocation (and related APIs), so there shouldn't be any 755b8e80941Smrg * harm in always appending "[0]" to uniform array names. 756b8e80941Smrg */ 757b8e80941Smrgstatic bool 758b8e80941Smrgadd_index_to_name(struct gl_program_resource *res) 759b8e80941Smrg{ 760b8e80941Smrg /* Transform feedback varyings have array index already appended 761b8e80941Smrg * in their names. 762b8e80941Smrg */ 763b8e80941Smrg return res->Type != GL_TRANSFORM_FEEDBACK_VARYING; 764b8e80941Smrg} 765b8e80941Smrg 766b8e80941Smrg/* Get name length of a program resource. This consists of 767b8e80941Smrg * base name + 3 for '[0]' if resource is an array. 768b8e80941Smrg */ 769b8e80941Smrgextern unsigned 770b8e80941Smrg_mesa_program_resource_name_len(struct gl_program_resource *res) 771b8e80941Smrg{ 772b8e80941Smrg unsigned length = strlen(_mesa_program_resource_name(res)); 773b8e80941Smrg if (_mesa_program_resource_array_size(res) && add_index_to_name(res)) 774b8e80941Smrg length += 3; 775b8e80941Smrg return length; 776b8e80941Smrg} 777848b8605Smrg 778b8e80941Smrg/* Get full name of a program resource. 779b8e80941Smrg */ 780b8e80941Smrgbool 781b8e80941Smrg_mesa_get_program_resource_name(struct gl_shader_program *shProg, 782b8e80941Smrg GLenum programInterface, GLuint index, 783b8e80941Smrg GLsizei bufSize, GLsizei *length, 784b8e80941Smrg GLchar *name, const char *caller) 785b8e80941Smrg{ 786b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 787b8e80941Smrg 788b8e80941Smrg /* Find resource with given interface and index. */ 789b8e80941Smrg struct gl_program_resource *res = 790b8e80941Smrg _mesa_program_resource_find_index(shProg, programInterface, index); 791b8e80941Smrg 792b8e80941Smrg /* The error INVALID_VALUE is generated if <index> is greater than 793b8e80941Smrg * or equal to the number of entries in the active resource list for 794b8e80941Smrg * <programInterface>. 795b8e80941Smrg */ 796b8e80941Smrg if (!res) { 797b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index); 798b8e80941Smrg return false; 799b8e80941Smrg } 800b8e80941Smrg 801b8e80941Smrg if (bufSize < 0) { 802b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize); 803b8e80941Smrg return false; 804b8e80941Smrg } 805b8e80941Smrg 806b8e80941Smrg GLsizei localLength; 807b8e80941Smrg 808b8e80941Smrg if (length == NULL) 809b8e80941Smrg length = &localLength; 810b8e80941Smrg 811b8e80941Smrg _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res)); 812b8e80941Smrg 813b8e80941Smrg if (_mesa_program_resource_array_size(res) && add_index_to_name(res)) { 814b8e80941Smrg int i; 815b8e80941Smrg 816b8e80941Smrg /* The comparison is strange because *length does *NOT* include the 817b8e80941Smrg * terminating NUL, but maxLength does. 818b8e80941Smrg */ 819b8e80941Smrg for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++) 820b8e80941Smrg name[*length + i] = "[0]"[i]; 821b8e80941Smrg 822b8e80941Smrg name[*length + i] = '\0'; 823b8e80941Smrg *length += i; 824b8e80941Smrg } 825b8e80941Smrg return true; 826b8e80941Smrg} 827b8e80941Smrg 828b8e80941Smrgstatic GLint 829b8e80941Smrgprogram_resource_location(struct gl_program_resource *res, unsigned array_index) 830b8e80941Smrg{ 831b8e80941Smrg switch (res->Type) { 832b8e80941Smrg case GL_PROGRAM_INPUT: { 833b8e80941Smrg const gl_shader_variable *var = RESOURCE_VAR(res); 834b8e80941Smrg 835b8e80941Smrg if (var->location == -1) 836b8e80941Smrg return -1; 837b8e80941Smrg 838b8e80941Smrg /* If the input is an array, fail if the index is out of bounds. */ 839b8e80941Smrg if (array_index > 0 840b8e80941Smrg && array_index >= var->type->length) { 841b8e80941Smrg return -1; 842b8e80941Smrg } 843b8e80941Smrg return var->location + 844b8e80941Smrg (array_index * var->type->without_array()->matrix_columns); 845b8e80941Smrg } 846b8e80941Smrg case GL_PROGRAM_OUTPUT: 847b8e80941Smrg if (RESOURCE_VAR(res)->location == -1) 848b8e80941Smrg return -1; 849b8e80941Smrg 850b8e80941Smrg /* If the output is an array, fail if the index is out of bounds. */ 851b8e80941Smrg if (array_index > 0 852b8e80941Smrg && array_index >= RESOURCE_VAR(res)->type->length) { 853b8e80941Smrg return -1; 854b8e80941Smrg } 855b8e80941Smrg return RESOURCE_VAR(res)->location + array_index; 856b8e80941Smrg case GL_UNIFORM: 857b8e80941Smrg /* If the uniform is built-in, fail. */ 858b8e80941Smrg if (RESOURCE_UNI(res)->builtin) 859b8e80941Smrg return -1; 860b8e80941Smrg 861b8e80941Smrg /* From page 79 of the OpenGL 4.2 spec: 862b8e80941Smrg * 863b8e80941Smrg * "A valid name cannot be a structure, an array of structures, or any 864b8e80941Smrg * portion of a single vector or a matrix." 865b8e80941Smrg */ 866b8e80941Smrg if (RESOURCE_UNI(res)->type->without_array()->is_struct()) 867b8e80941Smrg return -1; 868b8e80941Smrg 869b8e80941Smrg /* From the GL_ARB_uniform_buffer_object spec: 870b8e80941Smrg * 871b8e80941Smrg * "The value -1 will be returned if <name> does not correspond to an 872b8e80941Smrg * active uniform variable name in <program>, if <name> is associated 873b8e80941Smrg * with a named uniform block, or if <name> starts with the reserved 874b8e80941Smrg * prefix "gl_"." 875b8e80941Smrg */ 876b8e80941Smrg if (RESOURCE_UNI(res)->block_index != -1 || 877b8e80941Smrg RESOURCE_UNI(res)->atomic_buffer_index != -1) 878b8e80941Smrg return -1; 879b8e80941Smrg 880b8e80941Smrg /* fallthrough */ 881b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 882b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 883b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 884b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 885b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 886b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 887b8e80941Smrg /* If the uniform is an array, fail if the index is out of bounds. */ 888b8e80941Smrg if (array_index > 0 889b8e80941Smrg && array_index >= RESOURCE_UNI(res)->array_elements) { 890b8e80941Smrg return -1; 891b8e80941Smrg } 892b8e80941Smrg 893b8e80941Smrg /* location in remap table + array element offset */ 894b8e80941Smrg return RESOURCE_UNI(res)->remap_location + array_index; 895b8e80941Smrg default: 896b8e80941Smrg return -1; 897b8e80941Smrg } 898b8e80941Smrg} 899b8e80941Smrg 900b8e80941Smrg/** 901b8e80941Smrg * Function implements following location queries: 902b8e80941Smrg * glGetUniformLocation 903b8e80941Smrg */ 904b8e80941SmrgGLint 905b8e80941Smrg_mesa_program_resource_location(struct gl_shader_program *shProg, 906b8e80941Smrg GLenum programInterface, const char *name) 907b8e80941Smrg{ 908b8e80941Smrg unsigned array_index = 0; 909b8e80941Smrg struct gl_program_resource *res = 910b8e80941Smrg _mesa_program_resource_find_name(shProg, programInterface, name, 911b8e80941Smrg &array_index); 912b8e80941Smrg 913b8e80941Smrg /* Resource not found. */ 914b8e80941Smrg if (!res) 915b8e80941Smrg return -1; 916b8e80941Smrg 917b8e80941Smrg return program_resource_location(res, array_index); 918b8e80941Smrg} 919b8e80941Smrg 920b8e80941Smrg/** 921b8e80941Smrg * Function implements following index queries: 922b8e80941Smrg * glGetFragDataIndex 923b8e80941Smrg */ 924b8e80941SmrgGLint 925b8e80941Smrg_mesa_program_resource_location_index(struct gl_shader_program *shProg, 926b8e80941Smrg GLenum programInterface, const char *name) 927b8e80941Smrg{ 928b8e80941Smrg struct gl_program_resource *res = 929b8e80941Smrg _mesa_program_resource_find_name(shProg, programInterface, name, NULL); 930b8e80941Smrg 931b8e80941Smrg /* Non-existent variable or resource is not referenced by fragment stage. */ 932b8e80941Smrg if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT))) 933b8e80941Smrg return -1; 934b8e80941Smrg 935b8e80941Smrg /* From OpenGL 4.5 spec, 7.3 Program Objects 936b8e80941Smrg * "The value -1 will be returned by either command... 937b8e80941Smrg * ... or if name identifies an active variable that does not have a 938b8e80941Smrg * valid location assigned. 939b8e80941Smrg */ 940b8e80941Smrg if (RESOURCE_VAR(res)->location == -1) 941b8e80941Smrg return -1; 942b8e80941Smrg return RESOURCE_VAR(res)->index; 943b8e80941Smrg} 944b8e80941Smrg 945b8e80941Smrgstatic uint8_t 946b8e80941Smrgstage_from_enum(GLenum ref) 947b8e80941Smrg{ 948b8e80941Smrg switch (ref) { 949b8e80941Smrg case GL_REFERENCED_BY_VERTEX_SHADER: 950b8e80941Smrg return MESA_SHADER_VERTEX; 951b8e80941Smrg case GL_REFERENCED_BY_TESS_CONTROL_SHADER: 952b8e80941Smrg return MESA_SHADER_TESS_CTRL; 953b8e80941Smrg case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: 954b8e80941Smrg return MESA_SHADER_TESS_EVAL; 955b8e80941Smrg case GL_REFERENCED_BY_GEOMETRY_SHADER: 956b8e80941Smrg return MESA_SHADER_GEOMETRY; 957b8e80941Smrg case GL_REFERENCED_BY_FRAGMENT_SHADER: 958b8e80941Smrg return MESA_SHADER_FRAGMENT; 959b8e80941Smrg case GL_REFERENCED_BY_COMPUTE_SHADER: 960b8e80941Smrg return MESA_SHADER_COMPUTE; 961b8e80941Smrg default: 962b8e80941Smrg assert(!"shader stage not supported"); 963b8e80941Smrg return MESA_SHADER_STAGES; 964b8e80941Smrg } 965b8e80941Smrg} 966b8e80941Smrg 967b8e80941Smrg/** 968b8e80941Smrg * Check if resource is referenced by given 'referenced by' stage enum. 969b8e80941Smrg * ATC and UBO resources hold stage references of their own. 970b8e80941Smrg */ 971b8e80941Smrgstatic bool 972b8e80941Smrgis_resource_referenced(struct gl_shader_program *shProg, 973b8e80941Smrg struct gl_program_resource *res, 974b8e80941Smrg GLuint index, uint8_t stage) 975b8e80941Smrg{ 976b8e80941Smrg /* First, check if we even have such a stage active. */ 977b8e80941Smrg if (!shProg->_LinkedShaders[stage]) 978b8e80941Smrg return false; 979b8e80941Smrg 980b8e80941Smrg if (res->Type == GL_ATOMIC_COUNTER_BUFFER) 981b8e80941Smrg return RESOURCE_ATC(res)->StageReferences[stage]; 982b8e80941Smrg 983b8e80941Smrg if (res->Type == GL_UNIFORM_BLOCK) 984b8e80941Smrg return shProg->data->UniformBlocks[index].stageref & (1 << stage); 985b8e80941Smrg 986b8e80941Smrg if (res->Type == GL_SHADER_STORAGE_BLOCK) 987b8e80941Smrg return shProg->data->ShaderStorageBlocks[index].stageref & (1 << stage); 988b8e80941Smrg 989b8e80941Smrg return res->StageReferences & (1 << stage); 990b8e80941Smrg} 991b8e80941Smrg 992b8e80941Smrgstatic unsigned 993b8e80941Smrgget_buffer_property(struct gl_shader_program *shProg, 994b8e80941Smrg struct gl_program_resource *res, const GLenum prop, 995b8e80941Smrg GLint *val, const char *caller) 996b8e80941Smrg{ 997b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 998b8e80941Smrg if (res->Type != GL_UNIFORM_BLOCK && 999b8e80941Smrg res->Type != GL_ATOMIC_COUNTER_BUFFER && 1000b8e80941Smrg res->Type != GL_SHADER_STORAGE_BLOCK && 1001b8e80941Smrg res->Type != GL_TRANSFORM_FEEDBACK_BUFFER) 1002b8e80941Smrg goto invalid_operation; 1003b8e80941Smrg 1004b8e80941Smrg if (res->Type == GL_UNIFORM_BLOCK) { 1005b8e80941Smrg switch (prop) { 1006b8e80941Smrg case GL_BUFFER_BINDING: 1007b8e80941Smrg *val = RESOURCE_UBO(res)->Binding; 1008b8e80941Smrg return 1; 1009b8e80941Smrg case GL_BUFFER_DATA_SIZE: 1010b8e80941Smrg *val = RESOURCE_UBO(res)->UniformBufferSize; 1011b8e80941Smrg return 1; 1012b8e80941Smrg case GL_NUM_ACTIVE_VARIABLES: 1013b8e80941Smrg *val = 0; 1014b8e80941Smrg for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { 1015b8e80941Smrg const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; 1016b8e80941Smrg struct gl_program_resource *uni = 1017b8e80941Smrg _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname, 1018b8e80941Smrg NULL); 1019b8e80941Smrg if (!uni) 1020b8e80941Smrg continue; 1021b8e80941Smrg (*val)++; 1022b8e80941Smrg } 1023b8e80941Smrg return 1; 1024b8e80941Smrg case GL_ACTIVE_VARIABLES: { 1025b8e80941Smrg unsigned num_values = 0; 1026b8e80941Smrg for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { 1027b8e80941Smrg const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; 1028b8e80941Smrg struct gl_program_resource *uni = 1029b8e80941Smrg _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname, 1030b8e80941Smrg NULL); 1031b8e80941Smrg if (!uni) 1032b8e80941Smrg continue; 1033b8e80941Smrg *val++ = 1034b8e80941Smrg _mesa_program_resource_index(shProg, uni); 1035b8e80941Smrg num_values++; 1036b8e80941Smrg } 1037b8e80941Smrg return num_values; 1038b8e80941Smrg } 1039b8e80941Smrg } 1040b8e80941Smrg } else if (res->Type == GL_SHADER_STORAGE_BLOCK) { 1041b8e80941Smrg switch (prop) { 1042b8e80941Smrg case GL_BUFFER_BINDING: 1043b8e80941Smrg *val = RESOURCE_UBO(res)->Binding; 1044b8e80941Smrg return 1; 1045b8e80941Smrg case GL_BUFFER_DATA_SIZE: 1046b8e80941Smrg *val = RESOURCE_UBO(res)->UniformBufferSize; 1047b8e80941Smrg return 1; 1048b8e80941Smrg case GL_NUM_ACTIVE_VARIABLES: 1049b8e80941Smrg *val = 0; 1050b8e80941Smrg for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { 1051b8e80941Smrg const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; 1052b8e80941Smrg struct gl_program_resource *uni = 1053b8e80941Smrg _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE, 1054b8e80941Smrg iname, NULL); 1055b8e80941Smrg if (!uni) 1056b8e80941Smrg continue; 1057b8e80941Smrg (*val)++; 1058b8e80941Smrg } 1059b8e80941Smrg return 1; 1060b8e80941Smrg case GL_ACTIVE_VARIABLES: { 1061b8e80941Smrg unsigned num_values = 0; 1062b8e80941Smrg for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { 1063b8e80941Smrg const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; 1064b8e80941Smrg struct gl_program_resource *uni = 1065b8e80941Smrg _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE, 1066b8e80941Smrg iname, NULL); 1067b8e80941Smrg if (!uni) 1068b8e80941Smrg continue; 1069b8e80941Smrg *val++ = 1070b8e80941Smrg _mesa_program_resource_index(shProg, uni); 1071b8e80941Smrg num_values++; 1072b8e80941Smrg } 1073b8e80941Smrg return num_values; 1074b8e80941Smrg } 1075b8e80941Smrg } 1076b8e80941Smrg } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) { 1077b8e80941Smrg switch (prop) { 1078b8e80941Smrg case GL_BUFFER_BINDING: 1079b8e80941Smrg *val = RESOURCE_ATC(res)->Binding; 1080b8e80941Smrg return 1; 1081b8e80941Smrg case GL_BUFFER_DATA_SIZE: 1082b8e80941Smrg *val = RESOURCE_ATC(res)->MinimumSize; 1083b8e80941Smrg return 1; 1084b8e80941Smrg case GL_NUM_ACTIVE_VARIABLES: 1085b8e80941Smrg *val = RESOURCE_ATC(res)->NumUniforms; 1086b8e80941Smrg return 1; 1087b8e80941Smrg case GL_ACTIVE_VARIABLES: 1088b8e80941Smrg for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) { 1089b8e80941Smrg /* Active atomic buffer contains index to UniformStorage. Find 1090b8e80941Smrg * out gl_program_resource via data pointer and then calculate 1091b8e80941Smrg * index of that uniform. 1092b8e80941Smrg */ 1093b8e80941Smrg unsigned idx = RESOURCE_ATC(res)->Uniforms[i]; 1094b8e80941Smrg struct gl_program_resource *uni = 1095b8e80941Smrg program_resource_find_data(shProg, 1096b8e80941Smrg &shProg->data->UniformStorage[idx]); 1097b8e80941Smrg assert(uni); 1098b8e80941Smrg *val++ = _mesa_program_resource_index(shProg, uni); 1099b8e80941Smrg } 1100b8e80941Smrg return RESOURCE_ATC(res)->NumUniforms; 1101b8e80941Smrg } 1102b8e80941Smrg } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) { 1103b8e80941Smrg switch (prop) { 1104b8e80941Smrg case GL_BUFFER_BINDING: 1105b8e80941Smrg *val = RESOURCE_XFB(res)->Binding; 1106b8e80941Smrg return 1; 1107b8e80941Smrg case GL_NUM_ACTIVE_VARIABLES: 1108b8e80941Smrg *val = RESOURCE_XFB(res)->NumVaryings; 1109b8e80941Smrg return 1; 1110b8e80941Smrg case GL_ACTIVE_VARIABLES: 1111b8e80941Smrg struct gl_transform_feedback_info *linked_xfb = 1112b8e80941Smrg shProg->last_vert_prog->sh.LinkedTransformFeedback; 1113b8e80941Smrg for (int i = 0; i < linked_xfb->NumVarying; i++) { 1114b8e80941Smrg unsigned index = linked_xfb->Varyings[i].BufferIndex; 1115b8e80941Smrg struct gl_program_resource *buf_res = 1116b8e80941Smrg _mesa_program_resource_find_index(shProg, 1117b8e80941Smrg GL_TRANSFORM_FEEDBACK_BUFFER, 1118b8e80941Smrg index); 1119b8e80941Smrg assert(buf_res); 1120b8e80941Smrg if (res == buf_res) { 1121b8e80941Smrg *val++ = i; 1122b8e80941Smrg } 1123b8e80941Smrg } 1124b8e80941Smrg return RESOURCE_XFB(res)->NumVaryings; 1125b8e80941Smrg } 1126b8e80941Smrg } 1127b8e80941Smrg assert(!"support for property type not implemented"); 1128b8e80941Smrg 1129b8e80941Smrginvalid_operation: 1130b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, 1131b8e80941Smrg _mesa_enum_to_string(res->Type), 1132b8e80941Smrg _mesa_enum_to_string(prop)); 1133b8e80941Smrg 1134b8e80941Smrg return 0; 1135b8e80941Smrg} 1136b8e80941Smrg 1137b8e80941Smrgunsigned 1138b8e80941Smrg_mesa_program_resource_prop(struct gl_shader_program *shProg, 1139b8e80941Smrg struct gl_program_resource *res, GLuint index, 1140b8e80941Smrg const GLenum prop, GLint *val, const char *caller) 1141b8e80941Smrg{ 1142b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1143b8e80941Smrg 1144b8e80941Smrg#define VALIDATE_TYPE(type)\ 1145b8e80941Smrg if (res->Type != type)\ 1146b8e80941Smrg goto invalid_operation; 1147b8e80941Smrg 1148b8e80941Smrg#define VALIDATE_TYPE_2(type1, type2)\ 1149b8e80941Smrg if (res->Type != type1 && res->Type != type2)\ 1150b8e80941Smrg goto invalid_operation; 1151b8e80941Smrg 1152b8e80941Smrg switch(prop) { 1153b8e80941Smrg case GL_NAME_LENGTH: 1154b8e80941Smrg switch (res->Type) { 1155b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 1156b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER: 1157b8e80941Smrg goto invalid_operation; 1158b8e80941Smrg default: 1159b8e80941Smrg /* Resource name length + terminator. */ 1160b8e80941Smrg *val = _mesa_program_resource_name_len(res) + 1; 1161b8e80941Smrg } 1162b8e80941Smrg return 1; 1163b8e80941Smrg case GL_TYPE: 1164b8e80941Smrg switch (res->Type) { 1165b8e80941Smrg case GL_UNIFORM: 1166b8e80941Smrg case GL_BUFFER_VARIABLE: 1167b8e80941Smrg *val = RESOURCE_UNI(res)->type->gl_type; 1168b8e80941Smrg return 1; 1169b8e80941Smrg case GL_PROGRAM_INPUT: 1170b8e80941Smrg case GL_PROGRAM_OUTPUT: 1171b8e80941Smrg *val = RESOURCE_VAR(res)->type->gl_type; 1172b8e80941Smrg return 1; 1173b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 1174b8e80941Smrg *val = RESOURCE_XFV(res)->Type; 1175b8e80941Smrg return 1; 1176b8e80941Smrg default: 1177b8e80941Smrg goto invalid_operation; 1178b8e80941Smrg } 1179b8e80941Smrg case GL_ARRAY_SIZE: 1180b8e80941Smrg switch (res->Type) { 1181b8e80941Smrg case GL_UNIFORM: 1182b8e80941Smrg case GL_BUFFER_VARIABLE: 1183b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 1184b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 1185b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 1186b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 1187b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 1188b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 1189b8e80941Smrg 1190b8e80941Smrg /* Test if a buffer variable is an array or an unsized array. 1191b8e80941Smrg * Unsized arrays return zero as array size. 1192b8e80941Smrg */ 1193b8e80941Smrg if (RESOURCE_UNI(res)->is_shader_storage && 1194b8e80941Smrg RESOURCE_UNI(res)->array_stride > 0) 1195b8e80941Smrg *val = RESOURCE_UNI(res)->array_elements; 1196b8e80941Smrg else 1197b8e80941Smrg *val = MAX2(RESOURCE_UNI(res)->array_elements, 1); 1198b8e80941Smrg return 1; 1199b8e80941Smrg case GL_PROGRAM_INPUT: 1200b8e80941Smrg case GL_PROGRAM_OUTPUT: 1201b8e80941Smrg *val = MAX2(_mesa_program_resource_array_size(res), 1); 1202b8e80941Smrg return 1; 1203b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 1204b8e80941Smrg *val = RESOURCE_XFV(res)->Size; 1205b8e80941Smrg return 1; 1206b8e80941Smrg default: 1207b8e80941Smrg goto invalid_operation; 1208b8e80941Smrg } 1209b8e80941Smrg case GL_OFFSET: 1210b8e80941Smrg switch (res->Type) { 1211b8e80941Smrg case GL_UNIFORM: 1212b8e80941Smrg case GL_BUFFER_VARIABLE: 1213b8e80941Smrg *val = RESOURCE_UNI(res)->offset; 1214b8e80941Smrg return 1; 1215b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 1216b8e80941Smrg *val = RESOURCE_XFV(res)->Offset; 1217b8e80941Smrg return 1; 1218b8e80941Smrg default: 1219b8e80941Smrg goto invalid_operation; 1220b8e80941Smrg } 1221b8e80941Smrg case GL_BLOCK_INDEX: 1222b8e80941Smrg VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); 1223b8e80941Smrg *val = RESOURCE_UNI(res)->block_index; 1224b8e80941Smrg return 1; 1225b8e80941Smrg case GL_ARRAY_STRIDE: 1226b8e80941Smrg VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); 1227b8e80941Smrg *val = RESOURCE_UNI(res)->array_stride; 1228b8e80941Smrg return 1; 1229b8e80941Smrg case GL_MATRIX_STRIDE: 1230b8e80941Smrg VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); 1231b8e80941Smrg *val = RESOURCE_UNI(res)->matrix_stride; 1232b8e80941Smrg return 1; 1233b8e80941Smrg case GL_IS_ROW_MAJOR: 1234b8e80941Smrg VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); 1235b8e80941Smrg *val = RESOURCE_UNI(res)->row_major; 1236b8e80941Smrg return 1; 1237b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER_INDEX: 1238b8e80941Smrg VALIDATE_TYPE(GL_UNIFORM); 1239b8e80941Smrg *val = RESOURCE_UNI(res)->atomic_buffer_index; 1240b8e80941Smrg return 1; 1241b8e80941Smrg case GL_BUFFER_BINDING: 1242b8e80941Smrg case GL_BUFFER_DATA_SIZE: 1243b8e80941Smrg case GL_NUM_ACTIVE_VARIABLES: 1244b8e80941Smrg case GL_ACTIVE_VARIABLES: 1245b8e80941Smrg return get_buffer_property(shProg, res, prop, val, caller); 1246b8e80941Smrg case GL_REFERENCED_BY_COMPUTE_SHADER: 1247b8e80941Smrg if (!_mesa_has_compute_shaders(ctx)) 1248b8e80941Smrg goto invalid_enum; 1249b8e80941Smrg /* fallthrough */ 1250b8e80941Smrg case GL_REFERENCED_BY_VERTEX_SHADER: 1251b8e80941Smrg case GL_REFERENCED_BY_TESS_CONTROL_SHADER: 1252b8e80941Smrg case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: 1253b8e80941Smrg case GL_REFERENCED_BY_GEOMETRY_SHADER: 1254b8e80941Smrg case GL_REFERENCED_BY_FRAGMENT_SHADER: 1255b8e80941Smrg switch (res->Type) { 1256b8e80941Smrg case GL_UNIFORM: 1257b8e80941Smrg case GL_PROGRAM_INPUT: 1258b8e80941Smrg case GL_PROGRAM_OUTPUT: 1259b8e80941Smrg case GL_UNIFORM_BLOCK: 1260b8e80941Smrg case GL_BUFFER_VARIABLE: 1261b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 1262b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 1263b8e80941Smrg *val = is_resource_referenced(shProg, res, index, 1264b8e80941Smrg stage_from_enum(prop)); 1265b8e80941Smrg return 1; 1266b8e80941Smrg default: 1267b8e80941Smrg goto invalid_operation; 1268b8e80941Smrg } 1269b8e80941Smrg case GL_LOCATION: 1270b8e80941Smrg switch (res->Type) { 1271b8e80941Smrg case GL_UNIFORM: 1272b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 1273b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 1274b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 1275b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 1276b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 1277b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 1278b8e80941Smrg case GL_PROGRAM_INPUT: 1279b8e80941Smrg case GL_PROGRAM_OUTPUT: 1280b8e80941Smrg *val = program_resource_location(res, 0); 1281b8e80941Smrg return 1; 1282b8e80941Smrg default: 1283b8e80941Smrg goto invalid_operation; 1284b8e80941Smrg } 1285b8e80941Smrg case GL_LOCATION_COMPONENT: 1286b8e80941Smrg switch (res->Type) { 1287b8e80941Smrg case GL_PROGRAM_INPUT: 1288b8e80941Smrg case GL_PROGRAM_OUTPUT: 1289b8e80941Smrg *val = RESOURCE_VAR(res)->component; 1290b8e80941Smrg return 1; 1291b8e80941Smrg default: 1292b8e80941Smrg goto invalid_operation; 1293b8e80941Smrg } 1294b8e80941Smrg case GL_LOCATION_INDEX: { 1295b8e80941Smrg int tmp; 1296b8e80941Smrg if (res->Type != GL_PROGRAM_OUTPUT) 1297b8e80941Smrg goto invalid_operation; 1298b8e80941Smrg tmp = program_resource_location(res, 0); 1299b8e80941Smrg if (tmp == -1) 1300b8e80941Smrg *val = -1; 1301b8e80941Smrg else 1302b8e80941Smrg *val = _mesa_program_resource_location_index(shProg, res->Type, 1303b8e80941Smrg RESOURCE_VAR(res)->name); 1304b8e80941Smrg return 1; 1305b8e80941Smrg } 1306b8e80941Smrg case GL_NUM_COMPATIBLE_SUBROUTINES: 1307b8e80941Smrg if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM && 1308b8e80941Smrg res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM && 1309b8e80941Smrg res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM && 1310b8e80941Smrg res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM && 1311b8e80941Smrg res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM && 1312b8e80941Smrg res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM) 1313b8e80941Smrg goto invalid_operation; 1314b8e80941Smrg *val = RESOURCE_UNI(res)->num_compatible_subroutines; 1315b8e80941Smrg return 1; 1316b8e80941Smrg case GL_COMPATIBLE_SUBROUTINES: { 1317b8e80941Smrg const struct gl_uniform_storage *uni; 1318b8e80941Smrg struct gl_program *p; 1319b8e80941Smrg unsigned count, i; 1320b8e80941Smrg int j; 1321b8e80941Smrg 1322b8e80941Smrg if (res->Type != GL_VERTEX_SUBROUTINE_UNIFORM && 1323b8e80941Smrg res->Type != GL_FRAGMENT_SUBROUTINE_UNIFORM && 1324b8e80941Smrg res->Type != GL_GEOMETRY_SUBROUTINE_UNIFORM && 1325b8e80941Smrg res->Type != GL_COMPUTE_SUBROUTINE_UNIFORM && 1326b8e80941Smrg res->Type != GL_TESS_CONTROL_SUBROUTINE_UNIFORM && 1327b8e80941Smrg res->Type != GL_TESS_EVALUATION_SUBROUTINE_UNIFORM) 1328b8e80941Smrg goto invalid_operation; 1329b8e80941Smrg uni = RESOURCE_UNI(res); 1330b8e80941Smrg 1331b8e80941Smrg p = shProg->_LinkedShaders[_mesa_shader_stage_from_subroutine_uniform(res->Type)]->Program; 1332b8e80941Smrg count = 0; 1333b8e80941Smrg for (i = 0; i < p->sh.NumSubroutineFunctions; i++) { 1334b8e80941Smrg struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i]; 1335b8e80941Smrg for (j = 0; j < fn->num_compat_types; j++) { 1336b8e80941Smrg if (fn->types[j] == uni->type) { 1337b8e80941Smrg val[count++] = i; 1338b8e80941Smrg break; 1339b8e80941Smrg } 1340b8e80941Smrg } 1341b8e80941Smrg } 1342b8e80941Smrg return count; 1343b8e80941Smrg } 1344b8e80941Smrg 1345b8e80941Smrg case GL_TOP_LEVEL_ARRAY_SIZE: 1346b8e80941Smrg VALIDATE_TYPE(GL_BUFFER_VARIABLE); 1347b8e80941Smrg *val = RESOURCE_UNI(res)->top_level_array_size; 1348b8e80941Smrg return 1; 1349b8e80941Smrg 1350b8e80941Smrg case GL_TOP_LEVEL_ARRAY_STRIDE: 1351b8e80941Smrg VALIDATE_TYPE(GL_BUFFER_VARIABLE); 1352b8e80941Smrg *val = RESOURCE_UNI(res)->top_level_array_stride; 1353b8e80941Smrg return 1; 1354b8e80941Smrg 1355b8e80941Smrg /* GL_ARB_tessellation_shader */ 1356b8e80941Smrg case GL_IS_PER_PATCH: 1357b8e80941Smrg switch (res->Type) { 1358b8e80941Smrg case GL_PROGRAM_INPUT: 1359b8e80941Smrg case GL_PROGRAM_OUTPUT: 1360b8e80941Smrg *val = RESOURCE_VAR(res)->patch; 1361b8e80941Smrg return 1; 1362b8e80941Smrg default: 1363b8e80941Smrg goto invalid_operation; 1364b8e80941Smrg } 1365b8e80941Smrg 1366b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX: 1367b8e80941Smrg VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING); 1368b8e80941Smrg *val = RESOURCE_XFV(res)->BufferIndex; 1369b8e80941Smrg return 1; 1370b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE: 1371b8e80941Smrg VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER); 1372b8e80941Smrg *val = RESOURCE_XFB(res)->Stride * 4; 1373b8e80941Smrg return 1; 1374b8e80941Smrg 1375b8e80941Smrg default: 1376b8e80941Smrg goto invalid_enum; 1377b8e80941Smrg } 1378b8e80941Smrg 1379b8e80941Smrg#undef VALIDATE_TYPE 1380b8e80941Smrg#undef VALIDATE_TYPE_2 1381b8e80941Smrg 1382b8e80941Smrginvalid_enum: 1383b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller, 1384b8e80941Smrg _mesa_enum_to_string(res->Type), 1385b8e80941Smrg _mesa_enum_to_string(prop)); 1386b8e80941Smrg return 0; 1387b8e80941Smrg 1388b8e80941Smrginvalid_operation: 1389b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, 1390b8e80941Smrg _mesa_enum_to_string(res->Type), 1391b8e80941Smrg _mesa_enum_to_string(prop)); 1392b8e80941Smrg return 0; 1393b8e80941Smrg} 1394b8e80941Smrg 1395b8e80941Smrgextern void 1396b8e80941Smrg_mesa_get_program_resourceiv(struct gl_shader_program *shProg, 1397b8e80941Smrg GLenum programInterface, GLuint index, GLsizei propCount, 1398b8e80941Smrg const GLenum *props, GLsizei bufSize, 1399b8e80941Smrg GLsizei *length, GLint *params) 1400b8e80941Smrg{ 1401b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1402b8e80941Smrg GLint *val = (GLint *) params; 1403b8e80941Smrg const GLenum *prop = props; 1404b8e80941Smrg GLsizei amount = 0; 1405b8e80941Smrg 1406b8e80941Smrg struct gl_program_resource *res = 1407b8e80941Smrg _mesa_program_resource_find_index(shProg, programInterface, index); 1408b8e80941Smrg 1409b8e80941Smrg /* No such resource found or bufSize negative. */ 1410b8e80941Smrg if (!res || bufSize < 0) { 1411b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1412b8e80941Smrg "glGetProgramResourceiv(%s index %d bufSize %d)", 1413b8e80941Smrg _mesa_enum_to_string(programInterface), index, bufSize); 1414b8e80941Smrg return; 1415b8e80941Smrg } 1416b8e80941Smrg 1417b8e80941Smrg /* Write propCount values until error occurs or bufSize reached. */ 1418b8e80941Smrg for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) { 1419b8e80941Smrg int props_written = 1420b8e80941Smrg _mesa_program_resource_prop(shProg, res, index, *prop, val, 1421b8e80941Smrg "glGetProgramResourceiv"); 1422b8e80941Smrg 1423b8e80941Smrg /* Error happened. */ 1424b8e80941Smrg if (props_written == 0) 1425b8e80941Smrg return; 1426b8e80941Smrg 1427b8e80941Smrg amount += props_written; 1428b8e80941Smrg } 1429b8e80941Smrg 1430b8e80941Smrg /* If <length> is not NULL, the actual number of integer values 1431b8e80941Smrg * written to <params> will be written to <length>. 1432b8e80941Smrg */ 1433b8e80941Smrg if (length) 1434b8e80941Smrg *length = amount; 1435b8e80941Smrg} 1436b8e80941Smrg 1437b8e80941Smrgstatic bool 1438b8e80941Smrgvalidate_io(struct gl_program *producer, struct gl_program *consumer) 1439b8e80941Smrg{ 1440b8e80941Smrg if (producer->sh.data->linked_stages == consumer->sh.data->linked_stages) 1441b8e80941Smrg return true; 1442b8e80941Smrg 1443b8e80941Smrg const bool producer_is_array_stage = 1444b8e80941Smrg producer->info.stage == MESA_SHADER_TESS_CTRL; 1445b8e80941Smrg const bool consumer_is_array_stage = 1446b8e80941Smrg consumer->info.stage == MESA_SHADER_GEOMETRY || 1447b8e80941Smrg consumer->info.stage == MESA_SHADER_TESS_CTRL || 1448b8e80941Smrg consumer->info.stage == MESA_SHADER_TESS_EVAL; 1449b8e80941Smrg 1450b8e80941Smrg bool valid = true; 1451b8e80941Smrg 1452b8e80941Smrg gl_shader_variable const **outputs = 1453b8e80941Smrg (gl_shader_variable const **) calloc(producer->sh.data->NumProgramResourceList, 1454b8e80941Smrg sizeof(gl_shader_variable *)); 1455b8e80941Smrg if (outputs == NULL) 1456b8e80941Smrg return false; 1457b8e80941Smrg 1458b8e80941Smrg /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec 1459b8e80941Smrg * says: 1460b8e80941Smrg * 1461b8e80941Smrg * At an interface between program objects, the set of inputs and 1462b8e80941Smrg * outputs are considered to match exactly if and only if: 1463b8e80941Smrg * 1464b8e80941Smrg * - Every declared input variable has a matching output, as described 1465b8e80941Smrg * above. 1466b8e80941Smrg * - There are no user-defined output variables declared without a 1467b8e80941Smrg * matching input variable declaration. 1468b8e80941Smrg * 1469b8e80941Smrg * Every input has an output, and every output has an input. Scan the list 1470b8e80941Smrg * of producer resources once, and generate the list of outputs. As inputs 1471b8e80941Smrg * and outputs are matched, remove the matched outputs from the set. At 1472b8e80941Smrg * the end, the set must be empty. If the set is not empty, then there is 1473b8e80941Smrg * some output that did not have an input. 1474b8e80941Smrg */ 1475b8e80941Smrg unsigned num_outputs = 0; 1476b8e80941Smrg for (unsigned i = 0; i < producer->sh.data->NumProgramResourceList; i++) { 1477b8e80941Smrg struct gl_program_resource *res = 1478b8e80941Smrg &producer->sh.data->ProgramResourceList[i]; 1479b8e80941Smrg 1480b8e80941Smrg if (res->Type != GL_PROGRAM_OUTPUT) 1481b8e80941Smrg continue; 1482b8e80941Smrg 1483b8e80941Smrg gl_shader_variable const *const var = RESOURCE_VAR(res); 1484b8e80941Smrg 1485b8e80941Smrg /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec 1486b8e80941Smrg * says: 1487b8e80941Smrg * 1488b8e80941Smrg * Built-in inputs or outputs do not affect interface matching. 1489b8e80941Smrg */ 1490b8e80941Smrg if (is_gl_identifier(var->name)) 1491b8e80941Smrg continue; 1492b8e80941Smrg 1493b8e80941Smrg outputs[num_outputs++] = var; 1494b8e80941Smrg } 1495b8e80941Smrg 1496b8e80941Smrg unsigned match_index = 0; 1497b8e80941Smrg for (unsigned i = 0; i < consumer->sh.data->NumProgramResourceList; i++) { 1498b8e80941Smrg struct gl_program_resource *res = 1499b8e80941Smrg &consumer->sh.data->ProgramResourceList[i]; 1500b8e80941Smrg 1501b8e80941Smrg if (res->Type != GL_PROGRAM_INPUT) 1502b8e80941Smrg continue; 1503b8e80941Smrg 1504b8e80941Smrg gl_shader_variable const *const consumer_var = RESOURCE_VAR(res); 1505b8e80941Smrg gl_shader_variable const *producer_var = NULL; 1506b8e80941Smrg 1507b8e80941Smrg if (is_gl_identifier(consumer_var->name)) 1508b8e80941Smrg continue; 1509b8e80941Smrg 1510b8e80941Smrg /* Inputs with explicit locations match other outputs with explicit 1511b8e80941Smrg * locations by location instead of by name. 1512b8e80941Smrg */ 1513b8e80941Smrg if (consumer_var->explicit_location) { 1514b8e80941Smrg for (unsigned j = 0; j < num_outputs; j++) { 1515b8e80941Smrg const gl_shader_variable *const var = outputs[j]; 1516b8e80941Smrg 1517b8e80941Smrg if (var->explicit_location && 1518b8e80941Smrg consumer_var->location == var->location) { 1519b8e80941Smrg producer_var = var; 1520b8e80941Smrg match_index = j; 1521b8e80941Smrg break; 1522b8e80941Smrg } 1523b8e80941Smrg } 1524b8e80941Smrg } else { 1525b8e80941Smrg for (unsigned j = 0; j < num_outputs; j++) { 1526b8e80941Smrg const gl_shader_variable *const var = outputs[j]; 1527b8e80941Smrg 1528b8e80941Smrg if (!var->explicit_location && 1529b8e80941Smrg strcmp(consumer_var->name, var->name) == 0) { 1530b8e80941Smrg producer_var = var; 1531b8e80941Smrg match_index = j; 1532b8e80941Smrg break; 1533b8e80941Smrg } 1534b8e80941Smrg } 1535b8e80941Smrg } 1536b8e80941Smrg 1537b8e80941Smrg /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec 1538b8e80941Smrg * says: 1539b8e80941Smrg * 1540b8e80941Smrg * - An output variable is considered to match an input variable in 1541b8e80941Smrg * the subsequent shader if: 1542b8e80941Smrg * 1543b8e80941Smrg * - the two variables match in name, type, and qualification; or 1544b8e80941Smrg * 1545b8e80941Smrg * - the two variables are declared with the same location 1546b8e80941Smrg * qualifier and match in type and qualification. 1547b8e80941Smrg */ 1548b8e80941Smrg if (producer_var == NULL) { 1549b8e80941Smrg valid = false; 1550b8e80941Smrg goto out; 1551b8e80941Smrg } 1552b8e80941Smrg 1553b8e80941Smrg /* An output cannot match more than one input, so remove the output from 1554b8e80941Smrg * the set of possible outputs. 1555b8e80941Smrg */ 1556b8e80941Smrg outputs[match_index] = NULL; 1557b8e80941Smrg num_outputs--; 1558b8e80941Smrg if (match_index < num_outputs) 1559b8e80941Smrg outputs[match_index] = outputs[num_outputs]; 1560b8e80941Smrg 1561b8e80941Smrg /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says: 1562b8e80941Smrg * 1563b8e80941Smrg * "Tessellation control shader per-vertex output variables and 1564b8e80941Smrg * blocks and tessellation control, tessellation evaluation, and 1565b8e80941Smrg * geometry shader per-vertex input variables and blocks are 1566b8e80941Smrg * required to be declared as arrays, with each element representing 1567b8e80941Smrg * input or output values for a single vertex of a multi-vertex 1568b8e80941Smrg * primitive. For the purposes of interface matching, such variables 1569b8e80941Smrg * and blocks are treated as though they were not declared as 1570b8e80941Smrg * arrays." 1571b8e80941Smrg * 1572b8e80941Smrg * So we unwrap those types before matching. 1573b8e80941Smrg */ 1574b8e80941Smrg const glsl_type *consumer_type = consumer_var->type; 1575b8e80941Smrg const glsl_type *consumer_interface_type = consumer_var->interface_type; 1576b8e80941Smrg const glsl_type *producer_type = producer_var->type; 1577b8e80941Smrg const glsl_type *producer_interface_type = producer_var->interface_type; 1578b8e80941Smrg 1579b8e80941Smrg if (consumer_is_array_stage) { 1580b8e80941Smrg if (consumer_interface_type) { 1581b8e80941Smrg /* the interface is the array; the underlying types should match */ 1582b8e80941Smrg if (consumer_interface_type->is_array() && !consumer_var->patch) 1583b8e80941Smrg consumer_interface_type = consumer_interface_type->fields.array; 1584b8e80941Smrg } else { 1585b8e80941Smrg if (consumer_type->is_array() && !consumer_var->patch) 1586b8e80941Smrg consumer_type = consumer_type->fields.array; 1587b8e80941Smrg } 1588b8e80941Smrg } 1589b8e80941Smrg 1590b8e80941Smrg if (producer_is_array_stage) { 1591b8e80941Smrg if (producer_interface_type) { 1592b8e80941Smrg /* the interface is the array; the underlying types should match */ 1593b8e80941Smrg if (producer_interface_type->is_array() && !producer_var->patch) 1594b8e80941Smrg producer_interface_type = producer_interface_type->fields.array; 1595b8e80941Smrg } else { 1596b8e80941Smrg if (producer_type->is_array() && !producer_var->patch) 1597b8e80941Smrg producer_type = producer_type->fields.array; 1598b8e80941Smrg } 1599b8e80941Smrg } 1600b8e80941Smrg 1601b8e80941Smrg if (producer_type != consumer_type) { 1602b8e80941Smrg valid = false; 1603b8e80941Smrg goto out; 1604b8e80941Smrg } 1605b8e80941Smrg 1606b8e80941Smrg if (producer_interface_type != consumer_interface_type) { 1607b8e80941Smrg valid = false; 1608b8e80941Smrg goto out; 1609b8e80941Smrg } 1610b8e80941Smrg 1611b8e80941Smrg /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says: 1612b8e80941Smrg * 1613b8e80941Smrg * Qualifier Class| Qualifier |in/out 1614b8e80941Smrg * ---------------+-------------+------ 1615b8e80941Smrg * Storage | in | 1616b8e80941Smrg * | out | N/A 1617b8e80941Smrg * | uniform | 1618b8e80941Smrg * ---------------+-------------+------ 1619b8e80941Smrg * Auxiliary | centroid | No 1620b8e80941Smrg * ---------------+-------------+------ 1621b8e80941Smrg * | location | Yes 1622b8e80941Smrg * | Block layout| N/A 1623b8e80941Smrg * | binding | N/A 1624b8e80941Smrg * | offset | N/A 1625b8e80941Smrg * | format | N/A 1626b8e80941Smrg * ---------------+-------------+------ 1627b8e80941Smrg * Interpolation | smooth | 1628b8e80941Smrg * | flat | Yes 1629b8e80941Smrg * ---------------+-------------+------ 1630b8e80941Smrg * | lowp | 1631b8e80941Smrg * Precision | mediump | Yes 1632b8e80941Smrg * | highp | 1633b8e80941Smrg * ---------------+-------------+------ 1634b8e80941Smrg * Variance | invariant | No 1635b8e80941Smrg * ---------------+-------------+------ 1636b8e80941Smrg * Memory | all | N/A 1637b8e80941Smrg * 1638b8e80941Smrg * Note that location mismatches are detected by the loops above that 1639b8e80941Smrg * find the producer variable that goes with the consumer variable. 1640b8e80941Smrg */ 1641b8e80941Smrg unsigned producer_interpolation = producer_var->interpolation; 1642b8e80941Smrg unsigned consumer_interpolation = consumer_var->interpolation; 1643b8e80941Smrg if (producer_interpolation == INTERP_MODE_NONE) 1644b8e80941Smrg producer_interpolation = INTERP_MODE_SMOOTH; 1645b8e80941Smrg if (consumer_interpolation == INTERP_MODE_NONE) 1646b8e80941Smrg consumer_interpolation = INTERP_MODE_SMOOTH; 1647b8e80941Smrg if (producer_interpolation != consumer_interpolation) { 1648b8e80941Smrg valid = false; 1649b8e80941Smrg goto out; 1650b8e80941Smrg } 1651b8e80941Smrg 1652b8e80941Smrg if (producer_var->precision != consumer_var->precision) { 1653b8e80941Smrg valid = false; 1654b8e80941Smrg goto out; 1655b8e80941Smrg } 1656b8e80941Smrg 1657b8e80941Smrg if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) { 1658b8e80941Smrg valid = false; 1659b8e80941Smrg goto out; 1660b8e80941Smrg } 1661b8e80941Smrg } 1662b8e80941Smrg 1663b8e80941Smrg out: 1664b8e80941Smrg free(outputs); 1665b8e80941Smrg return valid && num_outputs == 0; 1666b8e80941Smrg} 1667b8e80941Smrg 1668b8e80941Smrg/** 1669b8e80941Smrg * Validate inputs against outputs in a program pipeline. 1670b8e80941Smrg */ 1671b8e80941Smrgextern "C" bool 1672b8e80941Smrg_mesa_validate_pipeline_io(struct gl_pipeline_object *pipeline) 1673b8e80941Smrg{ 1674b8e80941Smrg struct gl_program **prog = (struct gl_program **) pipeline->CurrentProgram; 1675b8e80941Smrg 1676b8e80941Smrg /* Find first active stage in pipeline. */ 1677b8e80941Smrg unsigned idx, prev = 0; 1678b8e80941Smrg for (idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) { 1679b8e80941Smrg if (prog[idx]) { 1680b8e80941Smrg prev = idx; 1681b8e80941Smrg break; 1682b8e80941Smrg } 1683b8e80941Smrg } 1684b8e80941Smrg 1685b8e80941Smrg for (idx = prev + 1; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) { 1686b8e80941Smrg if (prog[idx]) { 1687b8e80941Smrg /* Pipeline might include both non-compute and a compute program, do 1688b8e80941Smrg * not attempt to validate varyings between non-compute and compute 1689b8e80941Smrg * stage. 1690b8e80941Smrg */ 1691b8e80941Smrg if (prog[idx]->info.stage == MESA_SHADER_COMPUTE) 1692b8e80941Smrg break; 1693b8e80941Smrg 1694b8e80941Smrg if (!validate_io(prog[prev], prog[idx])) 1695b8e80941Smrg return false; 1696b8e80941Smrg 1697b8e80941Smrg prev = idx; 1698b8e80941Smrg } 1699b8e80941Smrg } 1700b8e80941Smrg return true; 1701848b8605Smrg} 1702