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