program.c revision 67c2d80a839614e4638d6cff390627122f8148ca
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/framebuffer.h" 35#include "main/hash.h" 36#include "main/macros.h" 37#include "program.h" 38#include "prog_cache.h" 39#include "prog_parameter.h" 40#include "prog_instruction.h" 41#include "util/ralloc.h" 42 43 44/** 45 * A pointer to this dummy program is put into the hash table when 46 * glGenPrograms is called. 47 */ 48struct gl_program _mesa_DummyProgram; 49 50 51/** 52 * Init context's vertex/fragment program state 53 */ 54void 55_mesa_init_program(struct gl_context *ctx) 56{ 57 /* 58 * If this assertion fails, we need to increase the field 59 * size for register indexes (see INST_INDEX_BITS). 60 */ 61 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents / 4 62 <= (1 << INST_INDEX_BITS)); 63 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents / 4 64 <= (1 << INST_INDEX_BITS)); 65 66 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps <= (1 << INST_INDEX_BITS)); 67 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= (1 << INST_INDEX_BITS)); 68 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTemps <= (1 << INST_INDEX_BITS)); 69 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= (1 << INST_INDEX_BITS)); 70 71 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents <= 4 * MAX_UNIFORMS); 72 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents <= 4 * MAX_UNIFORMS); 73 74 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxAddressOffset <= (1 << INST_INDEX_BITS)); 75 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAddressOffset <= (1 << INST_INDEX_BITS)); 76 77 /* If this fails, increase prog_instruction::TexSrcUnit size */ 78 STATIC_ASSERT(MAX_TEXTURE_UNITS <= (1 << 5)); 79 80 /* If this fails, increase prog_instruction::TexSrcTarget size */ 81 STATIC_ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4)); 82 83 ctx->Program.ErrorPos = -1; 84 ctx->Program.ErrorString = strdup(""); 85 86 ctx->VertexProgram.Enabled = GL_FALSE; 87 ctx->VertexProgram.PointSizeEnabled = 88 (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE; 89 ctx->VertexProgram.TwoSideEnabled = GL_FALSE; 90 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 91 ctx->Shared->DefaultVertexProgram); 92 assert(ctx->VertexProgram.Current); 93 ctx->VertexProgram.Cache = _mesa_new_program_cache(); 94 95 ctx->FragmentProgram.Enabled = GL_FALSE; 96 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 97 ctx->Shared->DefaultFragmentProgram); 98 assert(ctx->FragmentProgram.Current); 99 ctx->FragmentProgram.Cache = _mesa_new_program_cache(); 100 101 /* XXX probably move this stuff */ 102 ctx->ATIFragmentShader.Enabled = GL_FALSE; 103 ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader; 104 assert(ctx->ATIFragmentShader.Current); 105 ctx->ATIFragmentShader.Current->RefCount++; 106} 107 108 109/** 110 * Free a context's vertex/fragment program state 111 */ 112void 113_mesa_free_program_data(struct gl_context *ctx) 114{ 115 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); 116 _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache); 117 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); 118 _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache); 119 120 /* XXX probably move this stuff */ 121 if (ctx->ATIFragmentShader.Current) { 122 ctx->ATIFragmentShader.Current->RefCount--; 123 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 124 free(ctx->ATIFragmentShader.Current); 125 } 126 } 127 128 free((void *) ctx->Program.ErrorString); 129} 130 131 132/** 133 * Update the default program objects in the given context to reference those 134 * specified in the shared state and release those referencing the old 135 * shared state. 136 */ 137void 138_mesa_update_default_objects_program(struct gl_context *ctx) 139{ 140 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 141 ctx->Shared->DefaultVertexProgram); 142 assert(ctx->VertexProgram.Current); 143 144 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 145 ctx->Shared->DefaultFragmentProgram); 146 assert(ctx->FragmentProgram.Current); 147 148 /* XXX probably move this stuff */ 149 if (ctx->ATIFragmentShader.Current) { 150 ctx->ATIFragmentShader.Current->RefCount--; 151 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 152 free(ctx->ATIFragmentShader.Current); 153 } 154 } 155 ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; 156 assert(ctx->ATIFragmentShader.Current); 157 ctx->ATIFragmentShader.Current->RefCount++; 158} 159 160 161/** 162 * Set the vertex/fragment program error state (position and error string). 163 * This is generally called from within the parsers. 164 */ 165void 166_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string) 167{ 168 ctx->Program.ErrorPos = pos; 169 free((void *) ctx->Program.ErrorString); 170 if (!string) 171 string = ""; 172 ctx->Program.ErrorString = strdup(string); 173} 174 175 176/** 177 * Initialize a new gl_program object. 178 */ 179struct gl_program * 180_mesa_init_gl_program(struct gl_program *prog, GLenum target, GLuint id) 181{ 182 GLuint i; 183 184 if (!prog) 185 return NULL; 186 187 memset(prog, 0, sizeof(*prog)); 188 mtx_init(&prog->Mutex, mtx_plain); 189 prog->Id = id; 190 prog->Target = target; 191 prog->RefCount = 1; 192 prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB; 193 194 /* default mapping from samplers to texture units */ 195 for (i = 0; i < MAX_SAMPLERS; i++) 196 prog->SamplerUnits[i] = i; 197 198 return prog; 199} 200 201 202/** 203 * Allocate and initialize a new fragment/vertex program object but 204 * don't put it into the program hash table. Called via 205 * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a 206 * device driver function to implement OO deriviation with additional 207 * types not understood by this function. 208 * 209 * \param ctx context 210 * \param id program id/number 211 * \param target program target/type 212 * \return pointer to new program object 213 */ 214struct gl_program * 215_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id) 216{ 217 switch (target) { 218 case GL_VERTEX_PROGRAM_ARB: { /* == GL_VERTEX_PROGRAM_NV */ 219 struct gl_vertex_program *prog = CALLOC_STRUCT(gl_vertex_program); 220 return _mesa_init_gl_program(&prog->Base, target, id); 221 } 222 case GL_FRAGMENT_PROGRAM_ARB: { 223 struct gl_fragment_program *prog = CALLOC_STRUCT(gl_fragment_program); 224 return _mesa_init_gl_program(&prog->Base, target, id); 225 } 226 case GL_GEOMETRY_PROGRAM_NV: { 227 struct gl_geometry_program *prog = CALLOC_STRUCT(gl_geometry_program); 228 return _mesa_init_gl_program(&prog->Base, target, id); 229 } 230 case GL_TESS_CONTROL_PROGRAM_NV: 231 case GL_TESS_EVALUATION_PROGRAM_NV: { 232 struct gl_program *prog = CALLOC_STRUCT(gl_program); 233 return _mesa_init_gl_program(prog, target, id); 234 } 235 case GL_COMPUTE_PROGRAM_NV: { 236 struct gl_compute_program *prog = CALLOC_STRUCT(gl_compute_program); 237 return _mesa_init_gl_program(&prog->Base, target, id); 238 } 239 default: 240 _mesa_problem(ctx, "bad target in _mesa_new_program"); 241 return NULL; 242 } 243} 244 245 246/** 247 * Delete a program and remove it from the hash table, ignoring the 248 * reference count. 249 * Called via ctx->Driver.DeleteProgram. May be wrapped (OO deriviation) 250 * by a device driver function. 251 */ 252void 253_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) 254{ 255 (void) ctx; 256 assert(prog); 257 assert(prog->RefCount==0); 258 259 if (prog == &_mesa_DummyProgram) 260 return; 261 262 free(prog->String); 263 free(prog->LocalParams); 264 265 if (prog->Instructions) { 266 _mesa_free_instructions(prog->Instructions, prog->NumInstructions); 267 } 268 if (prog->Parameters) { 269 _mesa_free_parameter_list(prog->Parameters); 270 } 271 272 if (prog->nir) { 273 ralloc_free(prog->nir); 274 } 275 276 mtx_destroy(&prog->Mutex); 277 free(prog); 278} 279 280 281/** 282 * Return the gl_program object for a given ID. 283 * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of 284 * casts elsewhere. 285 */ 286struct gl_program * 287_mesa_lookup_program(struct gl_context *ctx, GLuint id) 288{ 289 if (id) 290 return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id); 291 else 292 return NULL; 293} 294 295 296/** 297 * Reference counting for vertex/fragment programs 298 * This is normally only called from the _mesa_reference_program() macro 299 * when there's a real pointer change. 300 */ 301void 302_mesa_reference_program_(struct gl_context *ctx, 303 struct gl_program **ptr, 304 struct gl_program *prog) 305{ 306#ifndef NDEBUG 307 assert(ptr); 308 if (*ptr && prog) { 309 /* sanity check */ 310 if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB) 311 assert(prog->Target == GL_VERTEX_PROGRAM_ARB); 312 else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB) 313 assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB || 314 prog->Target == GL_FRAGMENT_PROGRAM_NV); 315 else if ((*ptr)->Target == GL_GEOMETRY_PROGRAM_NV) 316 assert(prog->Target == GL_GEOMETRY_PROGRAM_NV); 317 } 318#endif 319 320 if (*ptr) { 321 GLboolean deleteFlag; 322 struct gl_program *oldProg = *ptr; 323 324 mtx_lock(&oldProg->Mutex); 325 assert(oldProg->RefCount > 0); 326 oldProg->RefCount--; 327 328 deleteFlag = (oldProg->RefCount == 0); 329 mtx_unlock(&oldProg->Mutex); 330 331 if (deleteFlag) { 332 assert(ctx); 333 ctx->Driver.DeleteProgram(ctx, oldProg); 334 } 335 336 *ptr = NULL; 337 } 338 339 assert(!*ptr); 340 if (prog) { 341 mtx_lock(&prog->Mutex); 342 prog->RefCount++; 343 mtx_unlock(&prog->Mutex); 344 } 345 346 *ptr = prog; 347} 348 349 350/** 351 * Insert 'count' NOP instructions at 'start' in the given program. 352 * Adjust branch targets accordingly. 353 */ 354GLboolean 355_mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) 356{ 357 const GLuint origLen = prog->NumInstructions; 358 const GLuint newLen = origLen + count; 359 struct prog_instruction *newInst; 360 GLuint i; 361 362 /* adjust branches */ 363 for (i = 0; i < prog->NumInstructions; i++) { 364 struct prog_instruction *inst = prog->Instructions + i; 365 if (inst->BranchTarget > 0) { 366 if ((GLuint)inst->BranchTarget >= start) { 367 inst->BranchTarget += count; 368 } 369 } 370 } 371 372 /* Alloc storage for new instructions */ 373 newInst = _mesa_alloc_instructions(newLen); 374 if (!newInst) { 375 return GL_FALSE; 376 } 377 378 /* Copy 'start' instructions into new instruction buffer */ 379 _mesa_copy_instructions(newInst, prog->Instructions, start); 380 381 /* init the new instructions */ 382 _mesa_init_instructions(newInst + start, count); 383 384 /* Copy the remaining/tail instructions to new inst buffer */ 385 _mesa_copy_instructions(newInst + start + count, 386 prog->Instructions + start, 387 origLen - start); 388 389 /* free old instructions */ 390 _mesa_free_instructions(prog->Instructions, origLen); 391 392 /* install new instructions */ 393 prog->Instructions = newInst; 394 prog->NumInstructions = newLen; 395 396 return GL_TRUE; 397} 398 399/** 400 * Delete 'count' instructions at 'start' in the given program. 401 * Adjust branch targets accordingly. 402 */ 403GLboolean 404_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count) 405{ 406 const GLuint origLen = prog->NumInstructions; 407 const GLuint newLen = origLen - count; 408 struct prog_instruction *newInst; 409 GLuint i; 410 411 /* adjust branches */ 412 for (i = 0; i < prog->NumInstructions; i++) { 413 struct prog_instruction *inst = prog->Instructions + i; 414 if (inst->BranchTarget > 0) { 415 if (inst->BranchTarget > (GLint) start) { 416 inst->BranchTarget -= count; 417 } 418 } 419 } 420 421 /* Alloc storage for new instructions */ 422 newInst = _mesa_alloc_instructions(newLen); 423 if (!newInst) { 424 return GL_FALSE; 425 } 426 427 /* Copy 'start' instructions into new instruction buffer */ 428 _mesa_copy_instructions(newInst, prog->Instructions, start); 429 430 /* Copy the remaining/tail instructions to new inst buffer */ 431 _mesa_copy_instructions(newInst + start, 432 prog->Instructions + start + count, 433 newLen - start); 434 435 /* free old instructions */ 436 _mesa_free_instructions(prog->Instructions, origLen); 437 438 /* install new instructions */ 439 prog->Instructions = newInst; 440 prog->NumInstructions = newLen; 441 442 return GL_TRUE; 443} 444 445 446/** 447 * Populate the 'used' array with flags indicating which registers (TEMPs, 448 * INPUTs, OUTPUTs, etc, are used by the given program. 449 * \param file type of register to scan for 450 * \param used returns true/false flags for in use / free 451 * \param usedSize size of the 'used' array 452 */ 453void 454_mesa_find_used_registers(const struct gl_program *prog, 455 gl_register_file file, 456 GLboolean used[], GLuint usedSize) 457{ 458 GLuint i, j; 459 460 memset(used, 0, usedSize); 461 462 for (i = 0; i < prog->NumInstructions; i++) { 463 const struct prog_instruction *inst = prog->Instructions + i; 464 const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); 465 466 if (inst->DstReg.File == file) { 467 assert(inst->DstReg.Index < usedSize); 468 if(inst->DstReg.Index < usedSize) 469 used[inst->DstReg.Index] = GL_TRUE; 470 } 471 472 for (j = 0; j < n; j++) { 473 if (inst->SrcReg[j].File == file) { 474 assert(inst->SrcReg[j].Index < (GLint) usedSize); 475 if (inst->SrcReg[j].Index < (GLint) usedSize) 476 used[inst->SrcReg[j].Index] = GL_TRUE; 477 } 478 } 479 } 480} 481 482 483/** 484 * Scan the given 'used' register flag array for the first entry 485 * that's >= firstReg. 486 * \param used vector of flags indicating registers in use (as returned 487 * by _mesa_find_used_registers()) 488 * \param usedSize size of the 'used' array 489 * \param firstReg first register to start searching at 490 * \return index of unused register, or -1 if none. 491 */ 492GLint 493_mesa_find_free_register(const GLboolean used[], 494 GLuint usedSize, GLuint firstReg) 495{ 496 GLuint i; 497 498 assert(firstReg < usedSize); 499 500 for (i = firstReg; i < usedSize; i++) 501 if (!used[i]) 502 return i; 503 504 return -1; 505} 506 507 508/* Gets the minimum number of shader invocations per fragment. 509 * This function is useful to determine if we need to do per 510 * sample shading or per fragment shading. 511 */ 512GLint 513_mesa_get_min_invocations_per_fragment(struct gl_context *ctx, 514 const struct gl_fragment_program *prog, 515 bool ignore_sample_qualifier) 516{ 517 /* From ARB_sample_shading specification: 518 * "Using gl_SampleID in a fragment shader causes the entire shader 519 * to be evaluated per-sample." 520 * 521 * "Using gl_SamplePosition in a fragment shader causes the entire 522 * shader to be evaluated per-sample." 523 * 524 * "If MULTISAMPLE or SAMPLE_SHADING_ARB is disabled, sample shading 525 * has no effect." 526 */ 527 if (ctx->Multisample.Enabled) { 528 /* The ARB_gpu_shader5 specification says: 529 * 530 * "Use of the "sample" qualifier on a fragment shader input 531 * forces per-sample shading" 532 */ 533 if (prog->IsSample && !ignore_sample_qualifier) 534 return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1); 535 536 if (prog->Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID | 537 SYSTEM_BIT_SAMPLE_POS)) 538 return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1); 539 else if (ctx->Multisample.SampleShading) 540 return MAX2(ceil(ctx->Multisample.MinSampleShadingValue * 541 _mesa_geometric_samples(ctx->DrawBuffer)), 1); 542 else 543 return 1; 544 } 545 return 1; 546} 547