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