program.c revision b7ef7903b8f582438172ef1bdc72788be3aa0860
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/** 26 * \file program.c 27 * Vertex and fragment program support functions. 28 * \author Brian Paul 29 */ 30 31 32#include "main/glheader.h" 33#include "main/context.h" 34#include "main/hash.h" 35#include "main/macros.h" 36#include "program.h" 37#include "prog_cache.h" 38#include "prog_parameter.h" 39#include "prog_instruction.h" 40#include "util/ralloc.h" 41 42 43/** 44 * A pointer to this dummy program is put into the hash table when 45 * glGenPrograms is called. 46 */ 47struct gl_program _mesa_DummyProgram; 48 49 50/** 51 * Init context's vertex/fragment program state 52 */ 53void 54_mesa_init_program(struct gl_context *ctx) 55{ 56 /* 57 * If this assertion fails, we need to increase the field 58 * size for register indexes (see INST_INDEX_BITS). 59 */ 60 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents / 4 61 <= (1 << INST_INDEX_BITS)); 62 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents / 4 63 <= (1 << INST_INDEX_BITS)); 64 65 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps <= (1 << INST_INDEX_BITS)); 66 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= (1 << INST_INDEX_BITS)); 67 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTemps <= (1 << INST_INDEX_BITS)); 68 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= (1 << INST_INDEX_BITS)); 69 70 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents <= 4 * MAX_UNIFORMS); 71 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents <= 4 * MAX_UNIFORMS); 72 73 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxAddressOffset <= (1 << INST_INDEX_BITS)); 74 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAddressOffset <= (1 << INST_INDEX_BITS)); 75 76 /* If this fails, increase prog_instruction::TexSrcUnit size */ 77 STATIC_ASSERT(MAX_TEXTURE_UNITS <= (1 << 5)); 78 79 /* If this fails, increase prog_instruction::TexSrcTarget size */ 80 STATIC_ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4)); 81 82 ctx->Program.ErrorPos = -1; 83 ctx->Program.ErrorString = strdup(""); 84 85 ctx->VertexProgram.Enabled = GL_FALSE; 86 ctx->VertexProgram.PointSizeEnabled = 87 (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE; 88 ctx->VertexProgram.TwoSideEnabled = GL_FALSE; 89 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 90 ctx->Shared->DefaultVertexProgram); 91 assert(ctx->VertexProgram.Current); 92 ctx->VertexProgram.Cache = _mesa_new_program_cache(); 93 94 ctx->FragmentProgram.Enabled = GL_FALSE; 95 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 96 ctx->Shared->DefaultFragmentProgram); 97 assert(ctx->FragmentProgram.Current); 98 ctx->FragmentProgram.Cache = _mesa_new_program_cache(); 99 100 /* XXX probably move this stuff */ 101 ctx->ATIFragmentShader.Enabled = GL_FALSE; 102 ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader; 103 assert(ctx->ATIFragmentShader.Current); 104 ctx->ATIFragmentShader.Current->RefCount++; 105} 106 107 108/** 109 * Free a context's vertex/fragment program state 110 */ 111void 112_mesa_free_program_data(struct gl_context *ctx) 113{ 114 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); 115 _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache); 116 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); 117 _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache); 118 119 /* XXX probably move this stuff */ 120 if (ctx->ATIFragmentShader.Current) { 121 ctx->ATIFragmentShader.Current->RefCount--; 122 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 123 free(ctx->ATIFragmentShader.Current); 124 } 125 } 126 127 free((void *) ctx->Program.ErrorString); 128} 129 130 131/** 132 * Update the default program objects in the given context to reference those 133 * specified in the shared state and release those referencing the old 134 * shared state. 135 */ 136void 137_mesa_update_default_objects_program(struct gl_context *ctx) 138{ 139 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 140 ctx->Shared->DefaultVertexProgram); 141 assert(ctx->VertexProgram.Current); 142 143 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 144 ctx->Shared->DefaultFragmentProgram); 145 assert(ctx->FragmentProgram.Current); 146 147 /* XXX probably move this stuff */ 148 if (ctx->ATIFragmentShader.Current) { 149 ctx->ATIFragmentShader.Current->RefCount--; 150 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 151 free(ctx->ATIFragmentShader.Current); 152 } 153 } 154 ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; 155 assert(ctx->ATIFragmentShader.Current); 156 ctx->ATIFragmentShader.Current->RefCount++; 157} 158 159 160/** 161 * Set the vertex/fragment program error state (position and error string). 162 * This is generally called from within the parsers. 163 */ 164void 165_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string) 166{ 167 ctx->Program.ErrorPos = pos; 168 free((void *) ctx->Program.ErrorString); 169 if (!string) 170 string = ""; 171 ctx->Program.ErrorString = strdup(string); 172} 173 174 175/** 176 * Find the line number and column for 'pos' within 'string'. 177 * Return a copy of the line which contains 'pos'. Free the line with 178 * free(). 179 * \param string the program string 180 * \param pos the position within the string 181 * \param line returns the line number corresponding to 'pos'. 182 * \param col returns the column number corresponding to 'pos'. 183 * \return copy of the line containing 'pos'. 184 */ 185const GLubyte * 186_mesa_find_line_column(const GLubyte *string, const GLubyte *pos, 187 GLint *line, GLint *col) 188{ 189 const GLubyte *lineStart = string; 190 const GLubyte *p = string; 191 GLubyte *s; 192 int len; 193 194 *line = 1; 195 196 while (p != pos) { 197 if (*p == (GLubyte) '\n') { 198 (*line)++; 199 lineStart = p + 1; 200 } 201 p++; 202 } 203 204 *col = (pos - lineStart) + 1; 205 206 /* return copy of this line */ 207 while (*p != 0 && *p != '\n') 208 p++; 209 len = p - lineStart; 210 s = malloc(len + 1); 211 memcpy(s, lineStart, len); 212 s[len] = 0; 213 214 return s; 215} 216 217 218/** 219 * Initialize a new gl_program object. 220 */ 221static void 222init_program_struct(struct gl_program *prog, GLenum target, GLuint id) 223{ 224 GLuint i; 225 226 assert(prog); 227 228 memset(prog, 0, sizeof(*prog)); 229 prog->Id = id; 230 prog->Target = target; 231 prog->RefCount = 1; 232 prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB; 233 234 /* default mapping from samplers to texture units */ 235 for (i = 0; i < MAX_SAMPLERS; i++) 236 prog->SamplerUnits[i] = i; 237} 238 239 240/** 241 * Initialize a new fragment program object. 242 */ 243struct gl_program * 244_mesa_init_fragment_program(struct gl_context *ctx, 245 struct gl_fragment_program *prog, 246 GLenum target, GLuint id) 247{ 248 if (prog) { 249 init_program_struct(&prog->Base, target, id); 250 return &prog->Base; 251 } 252 return NULL; 253} 254 255 256/** 257 * Initialize a new vertex program object. 258 */ 259struct gl_program * 260_mesa_init_vertex_program(struct gl_context *ctx, 261 struct gl_vertex_program *prog, 262 GLenum target, GLuint id) 263{ 264 if (prog) { 265 init_program_struct(&prog->Base, target, id); 266 return &prog->Base; 267 } 268 return NULL; 269} 270 271 272/** 273 * Initialize a new compute program object. 274 */ 275struct gl_program * 276_mesa_init_compute_program(struct gl_context *ctx, 277 struct gl_compute_program *prog, 278 GLenum target, GLuint id) 279{ 280 if (prog) { 281 init_program_struct(&prog->Base, target, id); 282 return &prog->Base; 283 } 284 return NULL; 285} 286 287 288/** 289 * Initialize a new geometry program object. 290 */ 291struct gl_program * 292_mesa_init_geometry_program(struct gl_context *ctx, 293 struct gl_geometry_program *prog, 294 GLenum target, GLuint id) 295{ 296 if (prog) { 297 init_program_struct(&prog->Base, target, id); 298 return &prog->Base; 299 } 300 return NULL; 301} 302 303 304/** 305 * Allocate and initialize a new fragment/vertex program object but 306 * don't put it into the program hash table. Called via 307 * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a 308 * device driver function to implement OO deriviation with additional 309 * types not understood by this function. 310 * 311 * \param ctx context 312 * \param id program id/number 313 * \param target program target/type 314 * \return pointer to new program object 315 */ 316struct gl_program * 317_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id) 318{ 319 struct gl_program *prog; 320 switch (target) { 321 case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ 322 prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), 323 target, id ); 324 break; 325 case GL_FRAGMENT_PROGRAM_NV: 326 case GL_FRAGMENT_PROGRAM_ARB: 327 prog =_mesa_init_fragment_program(ctx, 328 CALLOC_STRUCT(gl_fragment_program), 329 target, id ); 330 break; 331 case MESA_GEOMETRY_PROGRAM: 332 prog = _mesa_init_geometry_program(ctx, 333 CALLOC_STRUCT(gl_geometry_program), 334 target, id); 335 break; 336 case GL_COMPUTE_PROGRAM_NV: 337 prog = _mesa_init_compute_program(ctx, 338 CALLOC_STRUCT(gl_compute_program), 339 target, id); 340 break; 341 default: 342 _mesa_problem(ctx, "bad target in _mesa_new_program"); 343 prog = NULL; 344 } 345 return prog; 346} 347 348 349/** 350 * Delete a program and remove it from the hash table, ignoring the 351 * reference count. 352 * Called via ctx->Driver.DeleteProgram. May be wrapped (OO deriviation) 353 * by a device driver function. 354 */ 355void 356_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) 357{ 358 (void) ctx; 359 assert(prog); 360 assert(prog->RefCount==0); 361 362 if (prog == &_mesa_DummyProgram) 363 return; 364 365 free(prog->String); 366 free(prog->LocalParams); 367 368 if (prog->Instructions) { 369 _mesa_free_instructions(prog->Instructions, prog->NumInstructions); 370 } 371 if (prog->Parameters) { 372 _mesa_free_parameter_list(prog->Parameters); 373 } 374 375 if (prog->nir) { 376 ralloc_free(prog->nir); 377 } 378 379 free(prog); 380} 381 382 383/** 384 * Return the gl_program object for a given ID. 385 * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of 386 * casts elsewhere. 387 */ 388struct gl_program * 389_mesa_lookup_program(struct gl_context *ctx, GLuint id) 390{ 391 if (id) 392 return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id); 393 else 394 return NULL; 395} 396 397 398/** 399 * Reference counting for vertex/fragment programs 400 * This is normally only called from the _mesa_reference_program() macro 401 * when there's a real pointer change. 402 */ 403void 404_mesa_reference_program_(struct gl_context *ctx, 405 struct gl_program **ptr, 406 struct gl_program *prog) 407{ 408#ifndef NDEBUG 409 assert(ptr); 410 if (*ptr && prog) { 411 /* sanity check */ 412 if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB) 413 assert(prog->Target == GL_VERTEX_PROGRAM_ARB); 414 else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB) 415 assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB || 416 prog->Target == GL_FRAGMENT_PROGRAM_NV); 417 else if ((*ptr)->Target == MESA_GEOMETRY_PROGRAM) 418 assert(prog->Target == MESA_GEOMETRY_PROGRAM); 419 } 420#endif 421 422 if (*ptr) { 423 GLboolean deleteFlag; 424 425 /*mtx_lock(&(*ptr)->Mutex);*/ 426#if 0 427 printf("Program %p ID=%u Target=%s Refcount-- to %d\n", 428 *ptr, (*ptr)->Id, 429 ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : 430 ((*ptr)->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")), 431 (*ptr)->RefCount - 1); 432#endif 433 assert((*ptr)->RefCount > 0); 434 (*ptr)->RefCount--; 435 436 deleteFlag = ((*ptr)->RefCount == 0); 437 /*mtx_lock(&(*ptr)->Mutex);*/ 438 439 if (deleteFlag) { 440 assert(ctx); 441 ctx->Driver.DeleteProgram(ctx, *ptr); 442 } 443 444 *ptr = NULL; 445 } 446 447 assert(!*ptr); 448 if (prog) { 449 /*mtx_lock(&prog->Mutex);*/ 450 prog->RefCount++; 451#if 0 452 printf("Program %p ID=%u Target=%s Refcount++ to %d\n", 453 prog, prog->Id, 454 (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : 455 (prog->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")), 456 prog->RefCount); 457#endif 458 /*mtx_unlock(&prog->Mutex);*/ 459 } 460 461 *ptr = prog; 462} 463 464 465/** 466 * Return a copy of a program. 467 * XXX Problem here if the program object is actually OO-derivation 468 * made by a device driver. 469 */ 470struct gl_program * 471_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog) 472{ 473 struct gl_program *clone; 474 475 clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id); 476 if (!clone) 477 return NULL; 478 479 assert(clone->Target == prog->Target); 480 assert(clone->RefCount == 1); 481 482 clone->String = (GLubyte *) strdup((char *) prog->String); 483 clone->Format = prog->Format; 484 clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions); 485 if (!clone->Instructions) { 486 _mesa_reference_program(ctx, &clone, NULL); 487 return NULL; 488 } 489 _mesa_copy_instructions(clone->Instructions, prog->Instructions, 490 prog->NumInstructions); 491 clone->InputsRead = prog->InputsRead; 492 clone->OutputsWritten = prog->OutputsWritten; 493 clone->SamplersUsed = prog->SamplersUsed; 494 clone->ShadowSamplers = prog->ShadowSamplers; 495 memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed)); 496 497 if (prog->Parameters) 498 clone->Parameters = _mesa_clone_parameter_list(prog->Parameters); 499 if (prog->LocalParams) { 500 clone->LocalParams = malloc(MAX_PROGRAM_LOCAL_PARAMS * 501 sizeof(float[4])); 502 if (!clone->LocalParams) { 503 _mesa_reference_program(ctx, &clone, NULL); 504 return NULL; 505 } 506 memcpy(clone->LocalParams, prog->LocalParams, 507 MAX_PROGRAM_LOCAL_PARAMS * sizeof(float[4])); 508 } 509 clone->IndirectRegisterFiles = prog->IndirectRegisterFiles; 510 clone->NumInstructions = prog->NumInstructions; 511 clone->NumTemporaries = prog->NumTemporaries; 512 clone->NumParameters = prog->NumParameters; 513 clone->NumAttributes = prog->NumAttributes; 514 clone->NumAddressRegs = prog->NumAddressRegs; 515 clone->NumNativeInstructions = prog->NumNativeInstructions; 516 clone->NumNativeTemporaries = prog->NumNativeTemporaries; 517 clone->NumNativeParameters = prog->NumNativeParameters; 518 clone->NumNativeAttributes = prog->NumNativeAttributes; 519 clone->NumNativeAddressRegs = prog->NumNativeAddressRegs; 520 clone->NumAluInstructions = prog->NumAluInstructions; 521 clone->NumTexInstructions = prog->NumTexInstructions; 522 clone->NumTexIndirections = prog->NumTexIndirections; 523 clone->NumNativeAluInstructions = prog->NumNativeAluInstructions; 524 clone->NumNativeTexInstructions = prog->NumNativeTexInstructions; 525 clone->NumNativeTexIndirections = prog->NumNativeTexIndirections; 526 527 switch (prog->Target) { 528 case GL_VERTEX_PROGRAM_ARB: 529 { 530 const struct gl_vertex_program *vp = gl_vertex_program_const(prog); 531 struct gl_vertex_program *vpc = gl_vertex_program(clone); 532 vpc->IsPositionInvariant = vp->IsPositionInvariant; 533 } 534 break; 535 case GL_FRAGMENT_PROGRAM_ARB: 536 { 537 const struct gl_fragment_program *fp = gl_fragment_program_const(prog); 538 struct gl_fragment_program *fpc = gl_fragment_program(clone); 539 fpc->UsesKill = fp->UsesKill; 540 fpc->UsesDFdy = fp->UsesDFdy; 541 fpc->OriginUpperLeft = fp->OriginUpperLeft; 542 fpc->PixelCenterInteger = fp->PixelCenterInteger; 543 } 544 break; 545 case MESA_GEOMETRY_PROGRAM: 546 { 547 const struct gl_geometry_program *gp = gl_geometry_program_const(prog); 548 struct gl_geometry_program *gpc = gl_geometry_program(clone); 549 gpc->VerticesOut = gp->VerticesOut; 550 gpc->InputType = gp->InputType; 551 gpc->Invocations = gp->Invocations; 552 gpc->OutputType = gp->OutputType; 553 gpc->UsesEndPrimitive = gp->UsesEndPrimitive; 554 gpc->UsesStreams = gp->UsesStreams; 555 } 556 break; 557 default: 558 _mesa_problem(NULL, "Unexpected target in _mesa_clone_program"); 559 } 560 561 return clone; 562} 563 564 565/** 566 * Insert 'count' NOP instructions at 'start' in the given program. 567 * Adjust branch targets accordingly. 568 */ 569GLboolean 570_mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) 571{ 572 const GLuint origLen = prog->NumInstructions; 573 const GLuint newLen = origLen + count; 574 struct prog_instruction *newInst; 575 GLuint i; 576 577 /* adjust branches */ 578 for (i = 0; i < prog->NumInstructions; i++) { 579 struct prog_instruction *inst = prog->Instructions + i; 580 if (inst->BranchTarget > 0) { 581 if ((GLuint)inst->BranchTarget >= start) { 582 inst->BranchTarget += count; 583 } 584 } 585 } 586 587 /* Alloc storage for new instructions */ 588 newInst = _mesa_alloc_instructions(newLen); 589 if (!newInst) { 590 return GL_FALSE; 591 } 592 593 /* Copy 'start' instructions into new instruction buffer */ 594 _mesa_copy_instructions(newInst, prog->Instructions, start); 595 596 /* init the new instructions */ 597 _mesa_init_instructions(newInst + start, count); 598 599 /* Copy the remaining/tail instructions to new inst buffer */ 600 _mesa_copy_instructions(newInst + start + count, 601 prog->Instructions + start, 602 origLen - start); 603 604 /* free old instructions */ 605 _mesa_free_instructions(prog->Instructions, origLen); 606 607 /* install new instructions */ 608 prog->Instructions = newInst; 609 prog->NumInstructions = newLen; 610 611 return GL_TRUE; 612} 613 614/** 615 * Delete 'count' instructions at 'start' in the given program. 616 * Adjust branch targets accordingly. 617 */ 618GLboolean 619_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count) 620{ 621 const GLuint origLen = prog->NumInstructions; 622 const GLuint newLen = origLen - count; 623 struct prog_instruction *newInst; 624 GLuint i; 625 626 /* adjust branches */ 627 for (i = 0; i < prog->NumInstructions; i++) { 628 struct prog_instruction *inst = prog->Instructions + i; 629 if (inst->BranchTarget > 0) { 630 if (inst->BranchTarget > (GLint) start) { 631 inst->BranchTarget -= count; 632 } 633 } 634 } 635 636 /* Alloc storage for new instructions */ 637 newInst = _mesa_alloc_instructions(newLen); 638 if (!newInst) { 639 return GL_FALSE; 640 } 641 642 /* Copy 'start' instructions into new instruction buffer */ 643 _mesa_copy_instructions(newInst, prog->Instructions, start); 644 645 /* Copy the remaining/tail instructions to new inst buffer */ 646 _mesa_copy_instructions(newInst + start, 647 prog->Instructions + start + count, 648 newLen - start); 649 650 /* free old instructions */ 651 _mesa_free_instructions(prog->Instructions, origLen); 652 653 /* install new instructions */ 654 prog->Instructions = newInst; 655 prog->NumInstructions = newLen; 656 657 return GL_TRUE; 658} 659 660 661/** 662 * Search instructions for registers that match (oldFile, oldIndex), 663 * replacing them with (newFile, newIndex). 664 */ 665static void 666replace_registers(struct prog_instruction *inst, GLuint numInst, 667 GLuint oldFile, GLuint oldIndex, 668 GLuint newFile, GLuint newIndex) 669{ 670 GLuint i, j; 671 for (i = 0; i < numInst; i++) { 672 /* src regs */ 673 for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) { 674 if (inst[i].SrcReg[j].File == oldFile && 675 inst[i].SrcReg[j].Index == oldIndex) { 676 inst[i].SrcReg[j].File = newFile; 677 inst[i].SrcReg[j].Index = newIndex; 678 } 679 } 680 /* dst reg */ 681 if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) { 682 inst[i].DstReg.File = newFile; 683 inst[i].DstReg.Index = newIndex; 684 } 685 } 686} 687 688 689/** 690 * Search instructions for references to program parameters. When found, 691 * increment the parameter index by 'offset'. 692 * Used when combining programs. 693 */ 694static void 695adjust_param_indexes(struct prog_instruction *inst, GLuint numInst, 696 GLuint offset) 697{ 698 GLuint i, j; 699 for (i = 0; i < numInst; i++) { 700 for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) { 701 GLuint f = inst[i].SrcReg[j].File; 702 if (f == PROGRAM_CONSTANT || 703 f == PROGRAM_UNIFORM || 704 f == PROGRAM_STATE_VAR) { 705 inst[i].SrcReg[j].Index += offset; 706 } 707 } 708 } 709} 710 711 712/** 713 * Combine two programs into one. Fix instructions so the outputs of 714 * the first program go to the inputs of the second program. 715 */ 716struct gl_program * 717_mesa_combine_programs(struct gl_context *ctx, 718 const struct gl_program *progA, 719 const struct gl_program *progB) 720{ 721 struct prog_instruction *newInst; 722 struct gl_program *newProg; 723 const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */ 724 const GLuint lenB = progB->NumInstructions; 725 const GLuint numParamsA = _mesa_num_parameters(progA->Parameters); 726 const GLuint newLength = lenA + lenB; 727 GLboolean usedTemps[MAX_PROGRAM_TEMPS]; 728 GLuint firstTemp = 0; 729 GLbitfield64 inputsB; 730 GLuint i; 731 732 assert(progA->Target == progB->Target); 733 734 newInst = _mesa_alloc_instructions(newLength); 735 if (!newInst) 736 return GL_FALSE; 737 738 _mesa_copy_instructions(newInst, progA->Instructions, lenA); 739 _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB); 740 741 /* adjust branch / instruction addresses for B's instructions */ 742 for (i = 0; i < lenB; i++) { 743 newInst[lenA + i].BranchTarget += lenA; 744 } 745 746 newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0); 747 newProg->Instructions = newInst; 748 newProg->NumInstructions = newLength; 749 750 /* find used temp regs (we may need new temps below) */ 751 _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY, 752 usedTemps, MAX_PROGRAM_TEMPS); 753 754 if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) { 755 const struct gl_fragment_program *fprogA, *fprogB; 756 struct gl_fragment_program *newFprog; 757 GLbitfield64 progB_inputsRead = progB->InputsRead; 758 GLint progB_colorFile, progB_colorIndex; 759 760 fprogA = gl_fragment_program_const(progA); 761 fprogB = gl_fragment_program_const(progB); 762 newFprog = gl_fragment_program(newProg); 763 764 newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill; 765 newFprog->UsesDFdy = fprogA->UsesDFdy || fprogB->UsesDFdy; 766 767 /* We'll do a search and replace for instances 768 * of progB_colorFile/progB_colorIndex below... 769 */ 770 progB_colorFile = PROGRAM_INPUT; 771 progB_colorIndex = VARYING_SLOT_COL0; 772 773 /* 774 * The fragment program may get color from a state var rather than 775 * a fragment input (vertex output) if it's constant. 776 * See the texenvprogram.c code. 777 * So, search the program's parameter list now to see if the program 778 * gets color from a state var instead of a conventional fragment 779 * input register. 780 */ 781 for (i = 0; i < progB->Parameters->NumParameters; i++) { 782 struct gl_program_parameter *p = &progB->Parameters->Parameters[i]; 783 if (p->Type == PROGRAM_STATE_VAR && 784 p->StateIndexes[0] == STATE_INTERNAL && 785 p->StateIndexes[1] == STATE_CURRENT_ATTRIB && 786 (int) p->StateIndexes[2] == (int) VERT_ATTRIB_COLOR0) { 787 progB_inputsRead |= VARYING_BIT_COL0; 788 progB_colorFile = PROGRAM_STATE_VAR; 789 progB_colorIndex = i; 790 break; 791 } 792 } 793 794 /* Connect color outputs of fprogA to color inputs of fprogB, via a 795 * new temporary register. 796 */ 797 if ((progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) && 798 (progB_inputsRead & VARYING_BIT_COL0)) { 799 GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS, 800 firstTemp); 801 if (tempReg < 0) { 802 _mesa_problem(ctx, "No free temp regs found in " 803 "_mesa_combine_programs(), using 31"); 804 tempReg = 31; 805 } 806 firstTemp = tempReg + 1; 807 808 /* replace writes to result.color[0] with tempReg */ 809 replace_registers(newInst, lenA, 810 PROGRAM_OUTPUT, FRAG_RESULT_COLOR, 811 PROGRAM_TEMPORARY, tempReg); 812 /* replace reads from the input color with tempReg */ 813 replace_registers(newInst + lenA, lenB, 814 progB_colorFile, progB_colorIndex, /* search for */ 815 PROGRAM_TEMPORARY, tempReg /* replace with */ ); 816 } 817 818 /* compute combined program's InputsRead */ 819 inputsB = progB_inputsRead; 820 if (progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) { 821 inputsB &= ~(1 << VARYING_SLOT_COL0); 822 } 823 newProg->InputsRead = progA->InputsRead | inputsB; 824 newProg->OutputsWritten = progB->OutputsWritten; 825 newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed; 826 } 827 else { 828 /* vertex program */ 829 assert(0); /* XXX todo */ 830 } 831 832 /* 833 * Merge parameters (uniforms, constants, etc) 834 */ 835 newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters, 836 progB->Parameters); 837 838 adjust_param_indexes(newInst + lenA, lenB, numParamsA); 839 840 841 return newProg; 842} 843 844 845/** 846 * Populate the 'used' array with flags indicating which registers (TEMPs, 847 * INPUTs, OUTPUTs, etc, are used by the given program. 848 * \param file type of register to scan for 849 * \param used returns true/false flags for in use / free 850 * \param usedSize size of the 'used' array 851 */ 852void 853_mesa_find_used_registers(const struct gl_program *prog, 854 gl_register_file file, 855 GLboolean used[], GLuint usedSize) 856{ 857 GLuint i, j; 858 859 memset(used, 0, usedSize); 860 861 for (i = 0; i < prog->NumInstructions; i++) { 862 const struct prog_instruction *inst = prog->Instructions + i; 863 const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); 864 865 if (inst->DstReg.File == file) { 866 assert(inst->DstReg.Index < usedSize); 867 if(inst->DstReg.Index < usedSize) 868 used[inst->DstReg.Index] = GL_TRUE; 869 } 870 871 for (j = 0; j < n; j++) { 872 if (inst->SrcReg[j].File == file) { 873 assert(inst->SrcReg[j].Index < (GLint) usedSize); 874 if (inst->SrcReg[j].Index < (GLint) usedSize) 875 used[inst->SrcReg[j].Index] = GL_TRUE; 876 } 877 } 878 } 879} 880 881 882/** 883 * Scan the given 'used' register flag array for the first entry 884 * that's >= firstReg. 885 * \param used vector of flags indicating registers in use (as returned 886 * by _mesa_find_used_registers()) 887 * \param usedSize size of the 'used' array 888 * \param firstReg first register to start searching at 889 * \return index of unused register, or -1 if none. 890 */ 891GLint 892_mesa_find_free_register(const GLboolean used[], 893 GLuint usedSize, GLuint firstReg) 894{ 895 GLuint i; 896 897 assert(firstReg < usedSize); 898 899 for (i = firstReg; i < usedSize; i++) 900 if (!used[i]) 901 return i; 902 903 return -1; 904} 905 906 907 908/** 909 * Check if the given register index is valid (doesn't exceed implementation- 910 * dependent limits). 911 * \return GL_TRUE if OK, GL_FALSE if bad index 912 */ 913GLboolean 914_mesa_valid_register_index(const struct gl_context *ctx, 915 gl_shader_stage shaderType, 916 gl_register_file file, GLint index) 917{ 918 const struct gl_program_constants *c; 919 920 assert(0 <= shaderType && shaderType < MESA_SHADER_STAGES); 921 c = &ctx->Const.Program[shaderType]; 922 923 switch (file) { 924 case PROGRAM_UNDEFINED: 925 return GL_TRUE; /* XXX or maybe false? */ 926 927 case PROGRAM_TEMPORARY: 928 return index >= 0 && index < (GLint) c->MaxTemps; 929 930 case PROGRAM_UNIFORM: 931 case PROGRAM_STATE_VAR: 932 /* aka constant buffer */ 933 return index >= 0 && index < (GLint) c->MaxUniformComponents / 4; 934 935 case PROGRAM_CONSTANT: 936 /* constant buffer w/ possible relative negative addressing */ 937 return (index > (int) c->MaxUniformComponents / -4 && 938 index < (int) c->MaxUniformComponents / 4); 939 940 case PROGRAM_INPUT: 941 if (index < 0) 942 return GL_FALSE; 943 944 switch (shaderType) { 945 case MESA_SHADER_VERTEX: 946 return index < VERT_ATTRIB_GENERIC0 + (GLint) c->MaxAttribs; 947 case MESA_SHADER_FRAGMENT: 948 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 949 case MESA_SHADER_GEOMETRY: 950 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 951 default: 952 return GL_FALSE; 953 } 954 955 case PROGRAM_OUTPUT: 956 if (index < 0) 957 return GL_FALSE; 958 959 switch (shaderType) { 960 case MESA_SHADER_VERTEX: 961 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 962 case MESA_SHADER_FRAGMENT: 963 return index < FRAG_RESULT_DATA0 + (GLint) ctx->Const.MaxDrawBuffers; 964 case MESA_SHADER_GEOMETRY: 965 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 966 default: 967 return GL_FALSE; 968 } 969 970 case PROGRAM_ADDRESS: 971 return index >= 0 && index < (GLint) c->MaxAddressRegs; 972 973 default: 974 _mesa_problem(ctx, 975 "unexpected register file in _mesa_valid_register_index()"); 976 return GL_FALSE; 977 } 978} 979 980 981 982/** 983 * "Post-process" a GPU program. This is intended to be used for debugging. 984 * Example actions include no-op'ing instructions or changing instruction 985 * behaviour. 986 */ 987void 988_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog) 989{ 990 static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 }; 991 GLuint i; 992 GLuint whiteSwizzle; 993 GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters, 994 (gl_constant_value *) white, 995 4, &whiteSwizzle); 996 997 (void) whiteIndex; 998 999 for (i = 0; i < prog->NumInstructions; i++) { 1000 struct prog_instruction *inst = prog->Instructions + i; 1001 const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); 1002 1003 (void) n; 1004 1005 if (_mesa_is_tex_instruction(inst->Opcode)) { 1006#if 0 1007 /* replace TEX/TXP/TXB with MOV */ 1008 inst->Opcode = OPCODE_MOV; 1009 inst->DstReg.WriteMask = WRITEMASK_XYZW; 1010 inst->SrcReg[0].Swizzle = SWIZZLE_XYZW; 1011 inst->SrcReg[0].Negate = NEGATE_NONE; 1012#endif 1013 1014#if 0 1015 /* disable shadow texture mode */ 1016 inst->TexShadow = 0; 1017#endif 1018 } 1019 1020 if (inst->Opcode == OPCODE_TXP) { 1021#if 0 1022 inst->Opcode = OPCODE_MOV; 1023 inst->DstReg.WriteMask = WRITEMASK_XYZW; 1024 inst->SrcReg[0].File = PROGRAM_CONSTANT; 1025 inst->SrcReg[0].Index = whiteIndex; 1026 inst->SrcReg[0].Swizzle = SWIZZLE_XYZW; 1027 inst->SrcReg[0].Negate = NEGATE_NONE; 1028#endif 1029#if 0 1030 inst->TexShadow = 0; 1031#endif 1032#if 0 1033 inst->Opcode = OPCODE_TEX; 1034 inst->TexShadow = 0; 1035#endif 1036 } 1037 1038 } 1039} 1040 1041/* Gets the minimum number of shader invocations per fragment. 1042 * This function is useful to determine if we need to do per 1043 * sample shading or per fragment shading. 1044 */ 1045GLint 1046_mesa_get_min_invocations_per_fragment(struct gl_context *ctx, 1047 const struct gl_fragment_program *prog, 1048 bool ignore_sample_qualifier) 1049{ 1050 /* From ARB_sample_shading specification: 1051 * "Using gl_SampleID in a fragment shader causes the entire shader 1052 * to be evaluated per-sample." 1053 * 1054 * "Using gl_SamplePosition in a fragment shader causes the entire 1055 * shader to be evaluated per-sample." 1056 * 1057 * "If MULTISAMPLE or SAMPLE_SHADING_ARB is disabled, sample shading 1058 * has no effect." 1059 */ 1060 if (ctx->Multisample.Enabled) { 1061 /* The ARB_gpu_shader5 specification says: 1062 * 1063 * "Use of the "sample" qualifier on a fragment shader input 1064 * forces per-sample shading" 1065 */ 1066 if (prog->IsSample && !ignore_sample_qualifier) 1067 return MAX2(ctx->DrawBuffer->Visual.samples, 1); 1068 1069 if (prog->Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID | 1070 SYSTEM_BIT_SAMPLE_POS)) 1071 return MAX2(ctx->DrawBuffer->Visual.samples, 1); 1072 else if (ctx->Multisample.SampleShading) 1073 return MAX2(ceil(ctx->Multisample.MinSampleShadingValue * 1074 ctx->DrawBuffer->Visual.samples), 1); 1075 else 1076 return 1; 1077 } 1078 return 1; 1079} 1080