program.c revision a894ed82931840713aac25634ed469ac65889bfa
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 tessellation control program object. 290 */ 291struct gl_program * 292_mesa_init_tess_ctrl_program(struct gl_context *ctx, 293 struct gl_tess_ctrl_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 * Initialize a new tessellation evaluation program object. 306 */ 307struct gl_program * 308_mesa_init_tess_eval_program(struct gl_context *ctx, 309 struct gl_tess_eval_program *prog, 310 GLenum target, GLuint id) 311{ 312 if (prog) { 313 init_program_struct(&prog->Base, target, id); 314 return &prog->Base; 315 } 316 return NULL; 317} 318 319 320/** 321 * Initialize a new geometry program object. 322 */ 323struct gl_program * 324_mesa_init_geometry_program(struct gl_context *ctx, 325 struct gl_geometry_program *prog, 326 GLenum target, GLuint id) 327{ 328 if (prog) { 329 init_program_struct(&prog->Base, target, id); 330 return &prog->Base; 331 } 332 return NULL; 333} 334 335 336/** 337 * Allocate and initialize a new fragment/vertex program object but 338 * don't put it into the program hash table. Called via 339 * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a 340 * device driver function to implement OO deriviation with additional 341 * types not understood by this function. 342 * 343 * \param ctx context 344 * \param id program id/number 345 * \param target program target/type 346 * \return pointer to new program object 347 */ 348struct gl_program * 349_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id) 350{ 351 struct gl_program *prog; 352 switch (target) { 353 case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ 354 prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), 355 target, id ); 356 break; 357 case GL_FRAGMENT_PROGRAM_NV: 358 case GL_FRAGMENT_PROGRAM_ARB: 359 prog =_mesa_init_fragment_program(ctx, 360 CALLOC_STRUCT(gl_fragment_program), 361 target, id ); 362 break; 363 case GL_GEOMETRY_PROGRAM_NV: 364 prog = _mesa_init_geometry_program(ctx, 365 CALLOC_STRUCT(gl_geometry_program), 366 target, id); 367 break; 368 case GL_TESS_CONTROL_PROGRAM_NV: 369 prog = _mesa_init_tess_ctrl_program(ctx, 370 CALLOC_STRUCT(gl_tess_ctrl_program), 371 target, id); 372 break; 373 case GL_TESS_EVALUATION_PROGRAM_NV: 374 prog = _mesa_init_tess_eval_program(ctx, 375 CALLOC_STRUCT(gl_tess_eval_program), 376 target, id); 377 break; 378 case GL_COMPUTE_PROGRAM_NV: 379 prog = _mesa_init_compute_program(ctx, 380 CALLOC_STRUCT(gl_compute_program), 381 target, id); 382 break; 383 default: 384 _mesa_problem(ctx, "bad target in _mesa_new_program"); 385 prog = NULL; 386 } 387 return prog; 388} 389 390 391/** 392 * Delete a program and remove it from the hash table, ignoring the 393 * reference count. 394 * Called via ctx->Driver.DeleteProgram. May be wrapped (OO deriviation) 395 * by a device driver function. 396 */ 397void 398_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) 399{ 400 (void) ctx; 401 assert(prog); 402 assert(prog->RefCount==0); 403 404 if (prog == &_mesa_DummyProgram) 405 return; 406 407 free(prog->String); 408 free(prog->LocalParams); 409 410 if (prog->Instructions) { 411 _mesa_free_instructions(prog->Instructions, prog->NumInstructions); 412 } 413 if (prog->Parameters) { 414 _mesa_free_parameter_list(prog->Parameters); 415 } 416 417 if (prog->nir) { 418 ralloc_free(prog->nir); 419 } 420 421 free(prog); 422} 423 424 425/** 426 * Return the gl_program object for a given ID. 427 * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of 428 * casts elsewhere. 429 */ 430struct gl_program * 431_mesa_lookup_program(struct gl_context *ctx, GLuint id) 432{ 433 if (id) 434 return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id); 435 else 436 return NULL; 437} 438 439 440/** 441 * Reference counting for vertex/fragment programs 442 * This is normally only called from the _mesa_reference_program() macro 443 * when there's a real pointer change. 444 */ 445void 446_mesa_reference_program_(struct gl_context *ctx, 447 struct gl_program **ptr, 448 struct gl_program *prog) 449{ 450#ifndef NDEBUG 451 assert(ptr); 452 if (*ptr && prog) { 453 /* sanity check */ 454 if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB) 455 assert(prog->Target == GL_VERTEX_PROGRAM_ARB); 456 else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB) 457 assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB || 458 prog->Target == GL_FRAGMENT_PROGRAM_NV); 459 else if ((*ptr)->Target == GL_GEOMETRY_PROGRAM_NV) 460 assert(prog->Target == GL_GEOMETRY_PROGRAM_NV); 461 } 462#endif 463 464 if (*ptr) { 465 GLboolean deleteFlag; 466 467 /*mtx_lock(&(*ptr)->Mutex);*/ 468#if 0 469 printf("Program %p ID=%u Target=%s Refcount-- to %d\n", 470 *ptr, (*ptr)->Id, 471 ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : 472 ((*ptr)->Target == GL_GEOMETRY_PROGRAM_NV ? "GP" : "FP")), 473 (*ptr)->RefCount - 1); 474#endif 475 assert((*ptr)->RefCount > 0); 476 (*ptr)->RefCount--; 477 478 deleteFlag = ((*ptr)->RefCount == 0); 479 /*mtx_lock(&(*ptr)->Mutex);*/ 480 481 if (deleteFlag) { 482 assert(ctx); 483 ctx->Driver.DeleteProgram(ctx, *ptr); 484 } 485 486 *ptr = NULL; 487 } 488 489 assert(!*ptr); 490 if (prog) { 491 /*mtx_lock(&prog->Mutex);*/ 492 prog->RefCount++; 493#if 0 494 printf("Program %p ID=%u Target=%s Refcount++ to %d\n", 495 prog, prog->Id, 496 (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : 497 (prog->Target == GL_GEOMETRY_PROGRAM_NV ? "GP" : "FP")), 498 prog->RefCount); 499#endif 500 /*mtx_unlock(&prog->Mutex);*/ 501 } 502 503 *ptr = prog; 504} 505 506 507/** 508 * Return a copy of a program. 509 * XXX Problem here if the program object is actually OO-derivation 510 * made by a device driver. 511 */ 512struct gl_program * 513_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog) 514{ 515 struct gl_program *clone; 516 517 clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id); 518 if (!clone) 519 return NULL; 520 521 assert(clone->Target == prog->Target); 522 assert(clone->RefCount == 1); 523 524 clone->String = (GLubyte *) strdup((char *) prog->String); 525 clone->Format = prog->Format; 526 clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions); 527 if (!clone->Instructions) { 528 _mesa_reference_program(ctx, &clone, NULL); 529 return NULL; 530 } 531 _mesa_copy_instructions(clone->Instructions, prog->Instructions, 532 prog->NumInstructions); 533 clone->InputsRead = prog->InputsRead; 534 clone->OutputsWritten = prog->OutputsWritten; 535 clone->SamplersUsed = prog->SamplersUsed; 536 clone->ShadowSamplers = prog->ShadowSamplers; 537 memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed)); 538 539 if (prog->Parameters) 540 clone->Parameters = _mesa_clone_parameter_list(prog->Parameters); 541 if (prog->LocalParams) { 542 clone->LocalParams = malloc(MAX_PROGRAM_LOCAL_PARAMS * 543 sizeof(float[4])); 544 if (!clone->LocalParams) { 545 _mesa_reference_program(ctx, &clone, NULL); 546 return NULL; 547 } 548 memcpy(clone->LocalParams, prog->LocalParams, 549 MAX_PROGRAM_LOCAL_PARAMS * sizeof(float[4])); 550 } 551 clone->IndirectRegisterFiles = prog->IndirectRegisterFiles; 552 clone->NumInstructions = prog->NumInstructions; 553 clone->NumTemporaries = prog->NumTemporaries; 554 clone->NumParameters = prog->NumParameters; 555 clone->NumAttributes = prog->NumAttributes; 556 clone->NumAddressRegs = prog->NumAddressRegs; 557 clone->NumNativeInstructions = prog->NumNativeInstructions; 558 clone->NumNativeTemporaries = prog->NumNativeTemporaries; 559 clone->NumNativeParameters = prog->NumNativeParameters; 560 clone->NumNativeAttributes = prog->NumNativeAttributes; 561 clone->NumNativeAddressRegs = prog->NumNativeAddressRegs; 562 clone->NumAluInstructions = prog->NumAluInstructions; 563 clone->NumTexInstructions = prog->NumTexInstructions; 564 clone->NumTexIndirections = prog->NumTexIndirections; 565 clone->NumNativeAluInstructions = prog->NumNativeAluInstructions; 566 clone->NumNativeTexInstructions = prog->NumNativeTexInstructions; 567 clone->NumNativeTexIndirections = prog->NumNativeTexIndirections; 568 569 switch (prog->Target) { 570 case GL_VERTEX_PROGRAM_ARB: 571 { 572 const struct gl_vertex_program *vp = gl_vertex_program_const(prog); 573 struct gl_vertex_program *vpc = gl_vertex_program(clone); 574 vpc->IsPositionInvariant = vp->IsPositionInvariant; 575 } 576 break; 577 case GL_FRAGMENT_PROGRAM_ARB: 578 { 579 const struct gl_fragment_program *fp = gl_fragment_program_const(prog); 580 struct gl_fragment_program *fpc = gl_fragment_program(clone); 581 fpc->UsesKill = fp->UsesKill; 582 fpc->UsesDFdy = fp->UsesDFdy; 583 fpc->OriginUpperLeft = fp->OriginUpperLeft; 584 fpc->PixelCenterInteger = fp->PixelCenterInteger; 585 } 586 break; 587 case GL_GEOMETRY_PROGRAM_NV: 588 { 589 const struct gl_geometry_program *gp = gl_geometry_program_const(prog); 590 struct gl_geometry_program *gpc = gl_geometry_program(clone); 591 gpc->VerticesOut = gp->VerticesOut; 592 gpc->InputType = gp->InputType; 593 gpc->Invocations = gp->Invocations; 594 gpc->OutputType = gp->OutputType; 595 gpc->UsesEndPrimitive = gp->UsesEndPrimitive; 596 gpc->UsesStreams = gp->UsesStreams; 597 } 598 break; 599 case GL_TESS_CONTROL_PROGRAM_NV: 600 { 601 const struct gl_tess_ctrl_program *tcp = gl_tess_ctrl_program_const(prog); 602 struct gl_tess_ctrl_program *tcpc = gl_tess_ctrl_program(clone); 603 tcpc->VerticesOut = tcp->VerticesOut; 604 } 605 break; 606 case GL_TESS_EVALUATION_PROGRAM_NV: 607 { 608 const struct gl_tess_eval_program *tep = gl_tess_eval_program_const(prog); 609 struct gl_tess_eval_program *tepc = gl_tess_eval_program(clone); 610 tepc->PrimitiveMode = tep->PrimitiveMode; 611 tepc->Spacing = tep->Spacing; 612 tepc->VertexOrder = tep->VertexOrder; 613 tepc->PointMode = tep->PointMode; 614 } 615 break; 616 default: 617 _mesa_problem(NULL, "Unexpected target in _mesa_clone_program"); 618 } 619 620 return clone; 621} 622 623 624/** 625 * Insert 'count' NOP instructions at 'start' in the given program. 626 * Adjust branch targets accordingly. 627 */ 628GLboolean 629_mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) 630{ 631 const GLuint origLen = prog->NumInstructions; 632 const GLuint newLen = origLen + count; 633 struct prog_instruction *newInst; 634 GLuint i; 635 636 /* adjust branches */ 637 for (i = 0; i < prog->NumInstructions; i++) { 638 struct prog_instruction *inst = prog->Instructions + i; 639 if (inst->BranchTarget > 0) { 640 if ((GLuint)inst->BranchTarget >= start) { 641 inst->BranchTarget += count; 642 } 643 } 644 } 645 646 /* Alloc storage for new instructions */ 647 newInst = _mesa_alloc_instructions(newLen); 648 if (!newInst) { 649 return GL_FALSE; 650 } 651 652 /* Copy 'start' instructions into new instruction buffer */ 653 _mesa_copy_instructions(newInst, prog->Instructions, start); 654 655 /* init the new instructions */ 656 _mesa_init_instructions(newInst + start, count); 657 658 /* Copy the remaining/tail instructions to new inst buffer */ 659 _mesa_copy_instructions(newInst + start + count, 660 prog->Instructions + start, 661 origLen - start); 662 663 /* free old instructions */ 664 _mesa_free_instructions(prog->Instructions, origLen); 665 666 /* install new instructions */ 667 prog->Instructions = newInst; 668 prog->NumInstructions = newLen; 669 670 return GL_TRUE; 671} 672 673/** 674 * Delete 'count' instructions at 'start' in the given program. 675 * Adjust branch targets accordingly. 676 */ 677GLboolean 678_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count) 679{ 680 const GLuint origLen = prog->NumInstructions; 681 const GLuint newLen = origLen - count; 682 struct prog_instruction *newInst; 683 GLuint i; 684 685 /* adjust branches */ 686 for (i = 0; i < prog->NumInstructions; i++) { 687 struct prog_instruction *inst = prog->Instructions + i; 688 if (inst->BranchTarget > 0) { 689 if (inst->BranchTarget > (GLint) start) { 690 inst->BranchTarget -= count; 691 } 692 } 693 } 694 695 /* Alloc storage for new instructions */ 696 newInst = _mesa_alloc_instructions(newLen); 697 if (!newInst) { 698 return GL_FALSE; 699 } 700 701 /* Copy 'start' instructions into new instruction buffer */ 702 _mesa_copy_instructions(newInst, prog->Instructions, start); 703 704 /* Copy the remaining/tail instructions to new inst buffer */ 705 _mesa_copy_instructions(newInst + start, 706 prog->Instructions + start + count, 707 newLen - start); 708 709 /* free old instructions */ 710 _mesa_free_instructions(prog->Instructions, origLen); 711 712 /* install new instructions */ 713 prog->Instructions = newInst; 714 prog->NumInstructions = newLen; 715 716 return GL_TRUE; 717} 718 719 720/** 721 * Search instructions for registers that match (oldFile, oldIndex), 722 * replacing them with (newFile, newIndex). 723 */ 724static void 725replace_registers(struct prog_instruction *inst, GLuint numInst, 726 GLuint oldFile, GLuint oldIndex, 727 GLuint newFile, GLuint newIndex) 728{ 729 GLuint i, j; 730 for (i = 0; i < numInst; i++) { 731 /* src regs */ 732 for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) { 733 if (inst[i].SrcReg[j].File == oldFile && 734 inst[i].SrcReg[j].Index == oldIndex) { 735 inst[i].SrcReg[j].File = newFile; 736 inst[i].SrcReg[j].Index = newIndex; 737 } 738 } 739 /* dst reg */ 740 if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) { 741 inst[i].DstReg.File = newFile; 742 inst[i].DstReg.Index = newIndex; 743 } 744 } 745} 746 747 748/** 749 * Search instructions for references to program parameters. When found, 750 * increment the parameter index by 'offset'. 751 * Used when combining programs. 752 */ 753static void 754adjust_param_indexes(struct prog_instruction *inst, GLuint numInst, 755 GLuint offset) 756{ 757 GLuint i, j; 758 for (i = 0; i < numInst; i++) { 759 for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) { 760 GLuint f = inst[i].SrcReg[j].File; 761 if (f == PROGRAM_CONSTANT || 762 f == PROGRAM_UNIFORM || 763 f == PROGRAM_STATE_VAR) { 764 inst[i].SrcReg[j].Index += offset; 765 } 766 } 767 } 768} 769 770 771/** 772 * Combine two programs into one. Fix instructions so the outputs of 773 * the first program go to the inputs of the second program. 774 */ 775struct gl_program * 776_mesa_combine_programs(struct gl_context *ctx, 777 const struct gl_program *progA, 778 const struct gl_program *progB) 779{ 780 struct prog_instruction *newInst; 781 struct gl_program *newProg; 782 const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */ 783 const GLuint lenB = progB->NumInstructions; 784 const GLuint numParamsA = _mesa_num_parameters(progA->Parameters); 785 const GLuint newLength = lenA + lenB; 786 GLboolean usedTemps[MAX_PROGRAM_TEMPS]; 787 GLuint firstTemp = 0; 788 GLbitfield64 inputsB; 789 GLuint i; 790 791 assert(progA->Target == progB->Target); 792 793 newInst = _mesa_alloc_instructions(newLength); 794 if (!newInst) 795 return GL_FALSE; 796 797 _mesa_copy_instructions(newInst, progA->Instructions, lenA); 798 _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB); 799 800 /* adjust branch / instruction addresses for B's instructions */ 801 for (i = 0; i < lenB; i++) { 802 newInst[lenA + i].BranchTarget += lenA; 803 } 804 805 newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0); 806 newProg->Instructions = newInst; 807 newProg->NumInstructions = newLength; 808 809 /* find used temp regs (we may need new temps below) */ 810 _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY, 811 usedTemps, MAX_PROGRAM_TEMPS); 812 813 if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) { 814 const struct gl_fragment_program *fprogA, *fprogB; 815 struct gl_fragment_program *newFprog; 816 GLbitfield64 progB_inputsRead = progB->InputsRead; 817 GLint progB_colorFile, progB_colorIndex; 818 819 fprogA = gl_fragment_program_const(progA); 820 fprogB = gl_fragment_program_const(progB); 821 newFprog = gl_fragment_program(newProg); 822 823 newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill; 824 newFprog->UsesDFdy = fprogA->UsesDFdy || fprogB->UsesDFdy; 825 826 /* We'll do a search and replace for instances 827 * of progB_colorFile/progB_colorIndex below... 828 */ 829 progB_colorFile = PROGRAM_INPUT; 830 progB_colorIndex = VARYING_SLOT_COL0; 831 832 /* 833 * The fragment program may get color from a state var rather than 834 * a fragment input (vertex output) if it's constant. 835 * See the texenvprogram.c code. 836 * So, search the program's parameter list now to see if the program 837 * gets color from a state var instead of a conventional fragment 838 * input register. 839 */ 840 for (i = 0; i < progB->Parameters->NumParameters; i++) { 841 struct gl_program_parameter *p = &progB->Parameters->Parameters[i]; 842 if (p->Type == PROGRAM_STATE_VAR && 843 p->StateIndexes[0] == STATE_INTERNAL && 844 p->StateIndexes[1] == STATE_CURRENT_ATTRIB && 845 (int) p->StateIndexes[2] == (int) VERT_ATTRIB_COLOR0) { 846 progB_inputsRead |= VARYING_BIT_COL0; 847 progB_colorFile = PROGRAM_STATE_VAR; 848 progB_colorIndex = i; 849 break; 850 } 851 } 852 853 /* Connect color outputs of fprogA to color inputs of fprogB, via a 854 * new temporary register. 855 */ 856 if ((progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) && 857 (progB_inputsRead & VARYING_BIT_COL0)) { 858 GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS, 859 firstTemp); 860 if (tempReg < 0) { 861 _mesa_problem(ctx, "No free temp regs found in " 862 "_mesa_combine_programs(), using 31"); 863 tempReg = 31; 864 } 865 firstTemp = tempReg + 1; 866 867 /* replace writes to result.color[0] with tempReg */ 868 replace_registers(newInst, lenA, 869 PROGRAM_OUTPUT, FRAG_RESULT_COLOR, 870 PROGRAM_TEMPORARY, tempReg); 871 /* replace reads from the input color with tempReg */ 872 replace_registers(newInst + lenA, lenB, 873 progB_colorFile, progB_colorIndex, /* search for */ 874 PROGRAM_TEMPORARY, tempReg /* replace with */ ); 875 } 876 877 /* compute combined program's InputsRead */ 878 inputsB = progB_inputsRead; 879 if (progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) { 880 inputsB &= ~(1 << VARYING_SLOT_COL0); 881 } 882 newProg->InputsRead = progA->InputsRead | inputsB; 883 newProg->OutputsWritten = progB->OutputsWritten; 884 newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed; 885 } 886 else { 887 /* vertex program */ 888 assert(0); /* XXX todo */ 889 } 890 891 /* 892 * Merge parameters (uniforms, constants, etc) 893 */ 894 newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters, 895 progB->Parameters); 896 897 adjust_param_indexes(newInst + lenA, lenB, numParamsA); 898 899 900 return newProg; 901} 902 903 904/** 905 * Populate the 'used' array with flags indicating which registers (TEMPs, 906 * INPUTs, OUTPUTs, etc, are used by the given program. 907 * \param file type of register to scan for 908 * \param used returns true/false flags for in use / free 909 * \param usedSize size of the 'used' array 910 */ 911void 912_mesa_find_used_registers(const struct gl_program *prog, 913 gl_register_file file, 914 GLboolean used[], GLuint usedSize) 915{ 916 GLuint i, j; 917 918 memset(used, 0, usedSize); 919 920 for (i = 0; i < prog->NumInstructions; i++) { 921 const struct prog_instruction *inst = prog->Instructions + i; 922 const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); 923 924 if (inst->DstReg.File == file) { 925 assert(inst->DstReg.Index < usedSize); 926 if(inst->DstReg.Index < usedSize) 927 used[inst->DstReg.Index] = GL_TRUE; 928 } 929 930 for (j = 0; j < n; j++) { 931 if (inst->SrcReg[j].File == file) { 932 assert(inst->SrcReg[j].Index < (GLint) usedSize); 933 if (inst->SrcReg[j].Index < (GLint) usedSize) 934 used[inst->SrcReg[j].Index] = GL_TRUE; 935 } 936 } 937 } 938} 939 940 941/** 942 * Scan the given 'used' register flag array for the first entry 943 * that's >= firstReg. 944 * \param used vector of flags indicating registers in use (as returned 945 * by _mesa_find_used_registers()) 946 * \param usedSize size of the 'used' array 947 * \param firstReg first register to start searching at 948 * \return index of unused register, or -1 if none. 949 */ 950GLint 951_mesa_find_free_register(const GLboolean used[], 952 GLuint usedSize, GLuint firstReg) 953{ 954 GLuint i; 955 956 assert(firstReg < usedSize); 957 958 for (i = firstReg; i < usedSize; i++) 959 if (!used[i]) 960 return i; 961 962 return -1; 963} 964 965 966 967/** 968 * Check if the given register index is valid (doesn't exceed implementation- 969 * dependent limits). 970 * \return GL_TRUE if OK, GL_FALSE if bad index 971 */ 972GLboolean 973_mesa_valid_register_index(const struct gl_context *ctx, 974 gl_shader_stage shaderType, 975 gl_register_file file, GLint index) 976{ 977 const struct gl_program_constants *c; 978 979 assert(0 <= shaderType && shaderType < MESA_SHADER_STAGES); 980 c = &ctx->Const.Program[shaderType]; 981 982 switch (file) { 983 case PROGRAM_UNDEFINED: 984 return GL_TRUE; /* XXX or maybe false? */ 985 986 case PROGRAM_TEMPORARY: 987 return index >= 0 && index < (GLint) c->MaxTemps; 988 989 case PROGRAM_UNIFORM: 990 case PROGRAM_STATE_VAR: 991 /* aka constant buffer */ 992 return index >= 0 && index < (GLint) c->MaxUniformComponents / 4; 993 994 case PROGRAM_CONSTANT: 995 /* constant buffer w/ possible relative negative addressing */ 996 return (index > (int) c->MaxUniformComponents / -4 && 997 index < (int) c->MaxUniformComponents / 4); 998 999 case PROGRAM_INPUT: 1000 if (index < 0) 1001 return GL_FALSE; 1002 1003 switch (shaderType) { 1004 case MESA_SHADER_VERTEX: 1005 return index < VERT_ATTRIB_GENERIC0 + (GLint) c->MaxAttribs; 1006 case MESA_SHADER_FRAGMENT: 1007 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 1008 case MESA_SHADER_GEOMETRY: 1009 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 1010 default: 1011 return GL_FALSE; 1012 } 1013 1014 case PROGRAM_OUTPUT: 1015 if (index < 0) 1016 return GL_FALSE; 1017 1018 switch (shaderType) { 1019 case MESA_SHADER_VERTEX: 1020 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 1021 case MESA_SHADER_FRAGMENT: 1022 return index < FRAG_RESULT_DATA0 + (GLint) ctx->Const.MaxDrawBuffers; 1023 case MESA_SHADER_GEOMETRY: 1024 return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying; 1025 default: 1026 return GL_FALSE; 1027 } 1028 1029 case PROGRAM_ADDRESS: 1030 return index >= 0 && index < (GLint) c->MaxAddressRegs; 1031 1032 default: 1033 _mesa_problem(ctx, 1034 "unexpected register file in _mesa_valid_register_index()"); 1035 return GL_FALSE; 1036 } 1037} 1038 1039 1040 1041/** 1042 * "Post-process" a GPU program. This is intended to be used for debugging. 1043 * Example actions include no-op'ing instructions or changing instruction 1044 * behaviour. 1045 */ 1046void 1047_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog) 1048{ 1049 static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 }; 1050 GLuint i; 1051 GLuint whiteSwizzle; 1052 GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters, 1053 (gl_constant_value *) white, 1054 4, &whiteSwizzle); 1055 1056 (void) whiteIndex; 1057 1058 for (i = 0; i < prog->NumInstructions; i++) { 1059 struct prog_instruction *inst = prog->Instructions + i; 1060 const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); 1061 1062 (void) n; 1063 1064 if (_mesa_is_tex_instruction(inst->Opcode)) { 1065#if 0 1066 /* replace TEX/TXP/TXB with MOV */ 1067 inst->Opcode = OPCODE_MOV; 1068 inst->DstReg.WriteMask = WRITEMASK_XYZW; 1069 inst->SrcReg[0].Swizzle = SWIZZLE_XYZW; 1070 inst->SrcReg[0].Negate = NEGATE_NONE; 1071#endif 1072 1073#if 0 1074 /* disable shadow texture mode */ 1075 inst->TexShadow = 0; 1076#endif 1077 } 1078 1079 if (inst->Opcode == OPCODE_TXP) { 1080#if 0 1081 inst->Opcode = OPCODE_MOV; 1082 inst->DstReg.WriteMask = WRITEMASK_XYZW; 1083 inst->SrcReg[0].File = PROGRAM_CONSTANT; 1084 inst->SrcReg[0].Index = whiteIndex; 1085 inst->SrcReg[0].Swizzle = SWIZZLE_XYZW; 1086 inst->SrcReg[0].Negate = NEGATE_NONE; 1087#endif 1088#if 0 1089 inst->TexShadow = 0; 1090#endif 1091#if 0 1092 inst->Opcode = OPCODE_TEX; 1093 inst->TexShadow = 0; 1094#endif 1095 } 1096 1097 } 1098} 1099 1100/* Gets the minimum number of shader invocations per fragment. 1101 * This function is useful to determine if we need to do per 1102 * sample shading or per fragment shading. 1103 */ 1104GLint 1105_mesa_get_min_invocations_per_fragment(struct gl_context *ctx, 1106 const struct gl_fragment_program *prog, 1107 bool ignore_sample_qualifier) 1108{ 1109 /* From ARB_sample_shading specification: 1110 * "Using gl_SampleID in a fragment shader causes the entire shader 1111 * to be evaluated per-sample." 1112 * 1113 * "Using gl_SamplePosition in a fragment shader causes the entire 1114 * shader to be evaluated per-sample." 1115 * 1116 * "If MULTISAMPLE or SAMPLE_SHADING_ARB is disabled, sample shading 1117 * has no effect." 1118 */ 1119 if (ctx->Multisample.Enabled) { 1120 /* The ARB_gpu_shader5 specification says: 1121 * 1122 * "Use of the "sample" qualifier on a fragment shader input 1123 * forces per-sample shading" 1124 */ 1125 if (prog->IsSample && !ignore_sample_qualifier) 1126 return MAX2(ctx->DrawBuffer->Visual.samples, 1); 1127 1128 if (prog->Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID | 1129 SYSTEM_BIT_SAMPLE_POS)) 1130 return MAX2(ctx->DrawBuffer->Visual.samples, 1); 1131 else if (ctx->Multisample.SampleShading) 1132 return MAX2(ceil(ctx->Multisample.MinSampleShadingValue * 1133 ctx->DrawBuffer->Visual.samples), 1); 1134 else 1135 return 1; 1136 } 1137 return 1; 1138} 1139