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 "main/shaderobj.h" 38 #include "program.h" 39 #include "prog_cache.h" 40 #include "prog_parameter.h" 41 #include "prog_instruction.h" 42 #include "util/ralloc.h" 43 44 45 /** 46 * A pointer to this dummy program is put into the hash table when 47 * glGenPrograms is called. 48 */ 49 struct gl_program _mesa_DummyProgram; 50 51 52 /** 53 * Init context's vertex/fragment program state 54 */ 55 void 56 _mesa_init_program(struct gl_context *ctx) 57 { 58 /* 59 * If this assertion fails, we need to increase the field 60 * size for register indexes (see INST_INDEX_BITS). 61 */ 62 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents / 4 63 <= (1 << INST_INDEX_BITS)); 64 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents / 4 65 <= (1 << INST_INDEX_BITS)); 66 67 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps <= (1 << INST_INDEX_BITS)); 68 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= (1 << INST_INDEX_BITS)); 69 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTemps <= (1 << INST_INDEX_BITS)); 70 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= (1 << INST_INDEX_BITS)); 71 72 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents <= 4 * MAX_UNIFORMS); 73 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents <= 4 * MAX_UNIFORMS); 74 75 assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxAddressOffset <= (1 << INST_INDEX_BITS)); 76 assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAddressOffset <= (1 << INST_INDEX_BITS)); 77 78 /* If this fails, increase prog_instruction::TexSrcUnit size */ 79 STATIC_ASSERT(MAX_TEXTURE_UNITS <= (1 << 5)); 80 81 /* If this fails, increase prog_instruction::TexSrcTarget size */ 82 STATIC_ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4)); 83 84 ctx->Program.ErrorPos = -1; 85 ctx->Program.ErrorString = strdup(""); 86 87 ctx->VertexProgram.Enabled = GL_FALSE; 88 ctx->VertexProgram.PointSizeEnabled = 89 (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE; 90 ctx->VertexProgram.TwoSideEnabled = GL_FALSE; 91 _mesa_reference_program(ctx, &ctx->VertexProgram.Current, 92 ctx->Shared->DefaultVertexProgram); 93 assert(ctx->VertexProgram.Current); 94 ctx->VertexProgram.Cache = _mesa_new_program_cache(); 95 96 ctx->FragmentProgram.Enabled = GL_FALSE; 97 _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, 98 ctx->Shared->DefaultFragmentProgram); 99 assert(ctx->FragmentProgram.Current); 100 ctx->FragmentProgram.Cache = _mesa_new_program_cache(); 101 102 /* XXX probably move this stuff */ 103 ctx->ATIFragmentShader.Enabled = GL_FALSE; 104 ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader; 105 assert(ctx->ATIFragmentShader.Current); 106 ctx->ATIFragmentShader.Current->RefCount++; 107 } 108 109 110 /** 111 * Free a context's vertex/fragment program state 112 */ 113 void 114 _mesa_free_program_data(struct gl_context *ctx) 115 { 116 _mesa_reference_program(ctx, &ctx->VertexProgram.Current, NULL); 117 _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache); 118 _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, NULL); 119 _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache); 120 121 /* XXX probably move this stuff */ 122 if (ctx->ATIFragmentShader.Current) { 123 ctx->ATIFragmentShader.Current->RefCount--; 124 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 125 free(ctx->ATIFragmentShader.Current); 126 } 127 } 128 129 free((void *) ctx->Program.ErrorString); 130 } 131 132 133 /** 134 * Update the default program objects in the given context to reference those 135 * specified in the shared state and release those referencing the old 136 * shared state. 137 */ 138 void 139 _mesa_update_default_objects_program(struct gl_context *ctx) 140 { 141 _mesa_reference_program(ctx, &ctx->VertexProgram.Current, 142 ctx->Shared->DefaultVertexProgram); 143 assert(ctx->VertexProgram.Current); 144 145 _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, 146 ctx->Shared->DefaultFragmentProgram); 147 assert(ctx->FragmentProgram.Current); 148 149 /* XXX probably move this stuff */ 150 if (ctx->ATIFragmentShader.Current) { 151 ctx->ATIFragmentShader.Current->RefCount--; 152 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 153 free(ctx->ATIFragmentShader.Current); 154 } 155 } 156 ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; 157 assert(ctx->ATIFragmentShader.Current); 158 ctx->ATIFragmentShader.Current->RefCount++; 159 } 160 161 162 /** 163 * Set the vertex/fragment program error state (position and error string). 164 * This is generally called from within the parsers. 165 */ 166 void 167 _mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string) 168 { 169 ctx->Program.ErrorPos = pos; 170 free((void *) ctx->Program.ErrorString); 171 if (!string) 172 string = ""; 173 ctx->Program.ErrorString = strdup(string); 174 } 175 176 177 /** 178 * Initialize a new gl_program object. 179 */ 180 struct gl_program * 181 _mesa_init_gl_program(struct gl_program *prog, GLenum target, GLuint id, 182 bool is_arb_asm) 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 prog->info.stage = _mesa_program_enum_to_shader_stage(target); 194 prog->is_arb_asm = is_arb_asm; 195 196 /* Uniforms that lack an initializer in the shader code have an initial 197 * value of zero. This includes sampler uniforms. 198 * 199 * Page 24 (page 30 of the PDF) of the GLSL 1.20 spec says: 200 * 201 * "The link time initial value is either the value of the variable's 202 * initializer, if present, or 0 if no initializer is present. Sampler 203 * types cannot have initializers." 204 * 205 * So we only initialise ARB assembly style programs. 206 */ 207 if (is_arb_asm) { 208 /* default mapping from samplers to texture units */ 209 for (unsigned i = 0; i < MAX_SAMPLERS; i++) 210 prog->SamplerUnits[i] = i; 211 } 212 213 return prog; 214 } 215 216 217 /** 218 * Allocate and initialize a new fragment/vertex program object but 219 * don't put it into the program hash table. Called via 220 * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a 221 * device driver function to implement OO deriviation with additional 222 * types not understood by this function. 223 * 224 * \param ctx context 225 * \param id program id/number 226 * \param target program target/type 227 * \return pointer to new program object 228 */ 229 struct gl_program * 230 _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id, 231 bool is_arb_asm) 232 { 233 switch (target) { 234 case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ 235 case GL_GEOMETRY_PROGRAM_NV: 236 case GL_TESS_CONTROL_PROGRAM_NV: 237 case GL_TESS_EVALUATION_PROGRAM_NV: 238 case GL_FRAGMENT_PROGRAM_ARB: 239 case GL_COMPUTE_PROGRAM_NV: { 240 struct gl_program *prog = rzalloc(NULL, struct gl_program); 241 return _mesa_init_gl_program(prog, target, id, is_arb_asm); 242 } 243 default: 244 _mesa_problem(ctx, "bad target in _mesa_new_program"); 245 return NULL; 246 } 247 } 248 249 250 /** 251 * Delete a program and remove it from the hash table, ignoring the 252 * reference count. 253 * Called via ctx->Driver.DeleteProgram. May be wrapped (OO deriviation) 254 * by a device driver function. 255 */ 256 void 257 _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) 258 { 259 (void) ctx; 260 assert(prog); 261 assert(prog->RefCount==0); 262 263 if (prog == &_mesa_DummyProgram) 264 return; 265 266 if (prog->Parameters) { 267 _mesa_free_parameter_list(prog->Parameters); 268 } 269 270 if (prog->nir) { 271 ralloc_free(prog->nir); 272 } 273 274 mtx_destroy(&prog->Mutex); 275 ralloc_free(prog); 276 } 277 278 279 /** 280 * Return the gl_program object for a given ID. 281 * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of 282 * casts elsewhere. 283 */ 284 struct gl_program * 285 _mesa_lookup_program(struct gl_context *ctx, GLuint id) 286 { 287 if (id) 288 return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id); 289 else 290 return NULL; 291 } 292 293 294 /** 295 * Reference counting for vertex/fragment programs 296 * This is normally only called from the _mesa_reference_program() macro 297 * when there's a real pointer change. 298 */ 299 void 300 _mesa_reference_program_(struct gl_context *ctx, 301 struct gl_program **ptr, 302 struct gl_program *prog) 303 { 304 #ifndef NDEBUG 305 assert(ptr); 306 if (*ptr && prog) { 307 /* sanity check */ 308 if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB) 309 assert(prog->Target == GL_VERTEX_PROGRAM_ARB); 310 else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB) 311 assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB || 312 prog->Target == GL_FRAGMENT_PROGRAM_NV); 313 else if ((*ptr)->Target == GL_GEOMETRY_PROGRAM_NV) 314 assert(prog->Target == GL_GEOMETRY_PROGRAM_NV); 315 } 316 #endif 317 318 if (*ptr) { 319 GLboolean deleteFlag; 320 struct gl_program *oldProg = *ptr; 321 322 mtx_lock(&oldProg->Mutex); 323 assert(oldProg->RefCount > 0); 324 oldProg->RefCount--; 325 326 deleteFlag = (oldProg->RefCount == 0); 327 mtx_unlock(&oldProg->Mutex); 328 329 if (deleteFlag) { 330 assert(ctx); 331 _mesa_reference_shader_program_data(ctx, &oldProg->sh.data, NULL); 332 ctx->Driver.DeleteProgram(ctx, oldProg); 333 } 334 335 *ptr = NULL; 336 } 337 338 assert(!*ptr); 339 if (prog) { 340 mtx_lock(&prog->Mutex); 341 prog->RefCount++; 342 mtx_unlock(&prog->Mutex); 343 } 344 345 *ptr = prog; 346 } 347 348 349 /** 350 * Insert 'count' NOP instructions at 'start' in the given program. 351 * Adjust branch targets accordingly. 352 */ 353 GLboolean 354 _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) 355 { 356 const GLuint origLen = prog->arb.NumInstructions; 357 const GLuint newLen = origLen + count; 358 struct prog_instruction *newInst; 359 GLuint i; 360 361 /* adjust branches */ 362 for (i = 0; i < prog->arb.NumInstructions; i++) { 363 struct prog_instruction *inst = prog->arb.Instructions + i; 364 if (inst->BranchTarget > 0) { 365 if ((GLuint)inst->BranchTarget >= start) { 366 inst->BranchTarget += count; 367 } 368 } 369 } 370 371 /* Alloc storage for new instructions */ 372 newInst = rzalloc_array(prog, struct prog_instruction, newLen); 373 if (!newInst) { 374 return GL_FALSE; 375 } 376 377 /* Copy 'start' instructions into new instruction buffer */ 378 _mesa_copy_instructions(newInst, prog->arb.Instructions, start); 379 380 /* init the new instructions */ 381 _mesa_init_instructions(newInst + start, count); 382 383 /* Copy the remaining/tail instructions to new inst buffer */ 384 _mesa_copy_instructions(newInst + start + count, 385 prog->arb.Instructions + start, 386 origLen - start); 387 388 /* free old instructions */ 389 ralloc_free(prog->arb.Instructions); 390 391 /* install new instructions */ 392 prog->arb.Instructions = newInst; 393 prog->arb.NumInstructions = newLen; 394 395 return GL_TRUE; 396 } 397 398 /** 399 * Delete 'count' instructions at 'start' in the given program. 400 * Adjust branch targets accordingly. 401 */ 402 GLboolean 403 _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count, 404 void *mem_ctx) 405 { 406 const GLuint origLen = prog->arb.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->arb.NumInstructions; i++) { 413 struct prog_instruction *inst = prog->arb.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 = rzalloc_array(mem_ctx, struct prog_instruction, newLen); 423 if (!newInst) { 424 return GL_FALSE; 425 } 426 427 /* Copy 'start' instructions into new instruction buffer */ 428 _mesa_copy_instructions(newInst, prog->arb.Instructions, start); 429 430 /* Copy the remaining/tail instructions to new inst buffer */ 431 _mesa_copy_instructions(newInst + start, 432 prog->arb.Instructions + start + count, 433 newLen - start); 434 435 /* free old instructions */ 436 ralloc_free(prog->arb.Instructions); 437 438 /* install new instructions */ 439 prog->arb.Instructions = newInst; 440 prog->arb.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 */ 453 void 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->arb.NumInstructions; i++) { 463 const struct prog_instruction *inst = prog->arb.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 */ 492 GLint 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 */ 512 GLint 513 _mesa_get_min_invocations_per_fragment(struct gl_context *ctx, 514 const struct gl_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->info.fs.uses_sample_qualifier && !ignore_sample_qualifier) 534 return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1); 535 536 if (prog->info.system_values_read & (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