st_mesa_to_tgsi.c revision 3225bc84932f08a52db7025367ae206a9d2f8fef
1/************************************************************************** 2 * 3 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * 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 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/* 29 * \author 30 * Michal Krol 31 */ 32 33#include "pipe/p_compiler.h" 34#include "pipe/p_shader_tokens.h" 35#include "tgsi/tgsi_parse.h" 36#include "tgsi/tgsi_build.h" 37#include "tgsi/tgsi_util.h" 38#include "tgsi/tgsi_dump.h" 39#include "tgsi/tgsi_sanity.h" 40#include "st_mesa_to_tgsi.h" 41#include "shader/prog_instruction.h" 42#include "shader/prog_parameter.h" 43#include "shader/prog_print.h" 44#include "pipe/p_debug.h" 45 46/* 47 * Map mesa register file to TGSI register file. 48 */ 49static GLuint 50map_register_file( 51 enum register_file file, 52 GLuint index, 53 const GLuint immediateMapping[], 54 GLboolean indirectAccess ) 55{ 56 switch( file ) { 57 case PROGRAM_UNDEFINED: 58 return TGSI_FILE_NULL; 59 case PROGRAM_TEMPORARY: 60 return TGSI_FILE_TEMPORARY; 61 /*case PROGRAM_LOCAL_PARAM:*/ 62 /*case PROGRAM_ENV_PARAM:*/ 63 64 /* Because of the longstanding problem with mesa arb shaders 65 * where constants, immediates and state variables are all 66 * bundled together as PROGRAM_STATE_VAR, we can't tell from the 67 * mesa register file whether this is a CONSTANT or an 68 * IMMEDIATE, hence we need all the other information. 69 */ 70 case PROGRAM_STATE_VAR: 71 case PROGRAM_NAMED_PARAM: 72 case PROGRAM_UNIFORM: 73 if (!indirectAccess && immediateMapping && immediateMapping[index] != ~0) 74 return TGSI_FILE_IMMEDIATE; 75 else 76 return TGSI_FILE_CONSTANT; 77 case PROGRAM_CONSTANT: 78 if (indirectAccess) 79 return TGSI_FILE_CONSTANT; 80 assert(immediateMapping[index] != ~0); 81 return TGSI_FILE_IMMEDIATE; 82 case PROGRAM_INPUT: 83 return TGSI_FILE_INPUT; 84 case PROGRAM_OUTPUT: 85 return TGSI_FILE_OUTPUT; 86 case PROGRAM_ADDRESS: 87 return TGSI_FILE_ADDRESS; 88 default: 89 assert( 0 ); 90 return TGSI_FILE_NULL; 91 } 92} 93 94/** 95 * Map mesa register file index to TGSI index. 96 * Take special care when processing input and output indices. 97 * \param file one of TGSI_FILE_x 98 * \param index the mesa register file index 99 * \param inputMapping maps Mesa input indexes to TGSI input indexes 100 * \param outputMapping maps Mesa output indexes to TGSI output indexes 101 */ 102static GLuint 103map_register_file_index( 104 GLuint file, 105 GLuint index, 106 const GLuint inputMapping[], 107 const GLuint outputMapping[], 108 const GLuint immediateMapping[], 109 GLboolean indirectAccess ) 110{ 111 switch( file ) { 112 case TGSI_FILE_INPUT: 113 /* inputs are mapped according to the user-defined map */ 114 return inputMapping[index]; 115 116 case TGSI_FILE_OUTPUT: 117 return outputMapping[index]; 118 119 case TGSI_FILE_IMMEDIATE: 120 if (indirectAccess) 121 return index; 122 assert(immediateMapping[index] != ~0); 123 return immediateMapping[index]; 124 125 default: 126 return index; 127 } 128} 129 130/* 131 * Map mesa texture target to TGSI texture target. 132 */ 133static GLuint 134map_texture_target( 135 GLuint textarget ) 136{ 137 switch( textarget ) { 138 case TEXTURE_1D_INDEX: 139 return TGSI_TEXTURE_1D; 140 case TEXTURE_2D_INDEX: 141 return TGSI_TEXTURE_2D; 142 case TEXTURE_3D_INDEX: 143 return TGSI_TEXTURE_3D; 144 case TEXTURE_CUBE_INDEX: 145 return TGSI_TEXTURE_CUBE; 146 case TEXTURE_RECT_INDEX: 147 return TGSI_TEXTURE_RECT; 148 default: 149 assert( 0 ); 150 } 151 152 return TGSI_TEXTURE_1D; 153} 154 155static GLuint 156convert_sat( 157 GLuint sat ) 158{ 159 switch( sat ) { 160 case SATURATE_OFF: 161 return TGSI_SAT_NONE; 162 case SATURATE_ZERO_ONE: 163 return TGSI_SAT_ZERO_ONE; 164 case SATURATE_PLUS_MINUS_ONE: 165 return TGSI_SAT_MINUS_PLUS_ONE; 166 default: 167 assert( 0 ); 168 return TGSI_SAT_NONE; 169 } 170} 171 172static GLuint 173convert_writemask( 174 GLuint writemask ) 175{ 176 assert( WRITEMASK_X == TGSI_WRITEMASK_X ); 177 assert( WRITEMASK_Y == TGSI_WRITEMASK_Y ); 178 assert( WRITEMASK_Z == TGSI_WRITEMASK_Z ); 179 assert( WRITEMASK_W == TGSI_WRITEMASK_W ); 180 assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 ); 181 182 return writemask; 183} 184 185static struct tgsi_full_immediate 186make_immediate(const float *value, uint size) 187{ 188 struct tgsi_full_immediate imm; 189 190 imm = tgsi_default_full_immediate(); 191 imm.Immediate.Size += size; 192 imm.Immediate.DataType = TGSI_IMM_FLOAT32; 193 imm.u.Pointer = value; 194 return imm; 195} 196 197static void 198compile_instruction( 199 const struct prog_instruction *inst, 200 struct tgsi_full_instruction *fullinst, 201 const GLuint inputMapping[], 202 const GLuint outputMapping[], 203 const GLuint immediateMapping[], 204 GLboolean indirectAccess, 205 GLuint preamble_size, 206 GLuint processor, 207 GLboolean *insideSubroutine) 208{ 209 GLuint i; 210 struct tgsi_full_dst_register *fulldst; 211 struct tgsi_full_src_register *fullsrc; 212 213 *fullinst = tgsi_default_full_instruction(); 214 215 fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode ); 216 fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode ); 217 fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode ); 218 219 fulldst = &fullinst->FullDstRegisters[0]; 220 fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE ); 221 fulldst->DstRegister.Index = map_register_file_index( 222 fulldst->DstRegister.File, 223 inst->DstReg.Index, 224 inputMapping, 225 outputMapping, 226 NULL, 227 GL_FALSE ); 228 fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask ); 229 230 for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) { 231 GLuint j; 232 233 fullsrc = &fullinst->FullSrcRegisters[i]; 234 fullsrc->SrcRegister.File = map_register_file( 235 inst->SrcReg[i].File, 236 inst->SrcReg[i].Index, 237 immediateMapping, 238 indirectAccess ); 239 fullsrc->SrcRegister.Index = map_register_file_index( 240 fullsrc->SrcRegister.File, 241 inst->SrcReg[i].Index, 242 inputMapping, 243 outputMapping, 244 immediateMapping, 245 indirectAccess ); 246 247 248 /* swizzle (ext swizzle also depends on negation) */ 249 { 250 GLuint swz[4]; 251 GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE && 252 inst->SrcReg[i].NegateBase != NEGATE_XYZW); 253 for( j = 0; j < 4; j++ ) { 254 swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j ); 255 if (swz[j] > SWIZZLE_W) 256 extended = GL_TRUE; 257 } 258 if (extended) { 259 for (j = 0; j < 4; j++) { 260 tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz, 261 swz[j], j); 262 } 263 } 264 else { 265 for (j = 0; j < 4; j++) { 266 tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister, 267 swz[j], j); 268 } 269 } 270 } 271 272 if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) { 273 fullsrc->SrcRegister.Negate = 1; 274 } 275 else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) { 276 if( inst->SrcReg[i].NegateBase & NEGATE_X ) { 277 fullsrc->SrcRegisterExtSwz.NegateX = 1; 278 } 279 if( inst->SrcReg[i].NegateBase & NEGATE_Y ) { 280 fullsrc->SrcRegisterExtSwz.NegateY = 1; 281 } 282 if( inst->SrcReg[i].NegateBase & NEGATE_Z ) { 283 fullsrc->SrcRegisterExtSwz.NegateZ = 1; 284 } 285 if( inst->SrcReg[i].NegateBase & NEGATE_W ) { 286 fullsrc->SrcRegisterExtSwz.NegateW = 1; 287 } 288 } 289 290 if( inst->SrcReg[i].Abs ) { 291 fullsrc->SrcRegisterExtMod.Absolute = 1; 292 } 293 294 if( inst->SrcReg[i].NegateAbs ) { 295 fullsrc->SrcRegisterExtMod.Negate = 1; 296 } 297 298 if( inst->SrcReg[i].RelAddr ) { 299 fullsrc->SrcRegister.Indirect = 1; 300 301 fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS; 302 fullsrc->SrcRegisterInd.Index = 0; 303 } 304 } 305 306 switch( inst->Opcode ) { 307 case OPCODE_ARL: 308 fullinst->Instruction.Opcode = TGSI_OPCODE_ARL; 309 break; 310 case OPCODE_ABS: 311 fullinst->Instruction.Opcode = TGSI_OPCODE_ABS; 312 break; 313 case OPCODE_ADD: 314 fullinst->Instruction.Opcode = TGSI_OPCODE_ADD; 315 break; 316 case OPCODE_BGNLOOP: 317 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2; 318 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 319 break; 320 case OPCODE_BGNSUB: 321 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB; 322 *insideSubroutine = GL_TRUE; 323 break; 324 case OPCODE_BRA: 325 fullinst->Instruction.Opcode = TGSI_OPCODE_BRA; 326 break; 327 case OPCODE_BRK: 328 fullinst->Instruction.Opcode = TGSI_OPCODE_BRK; 329 break; 330 case OPCODE_CAL: 331 fullinst->Instruction.Opcode = TGSI_OPCODE_CAL; 332 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 333 break; 334 case OPCODE_CMP: 335 fullinst->Instruction.Opcode = TGSI_OPCODE_CMP; 336 break; 337 case OPCODE_CONT: 338 fullinst->Instruction.Opcode = TGSI_OPCODE_CONT; 339 break; 340 case OPCODE_COS: 341 fullinst->Instruction.Opcode = TGSI_OPCODE_COS; 342 break; 343 case OPCODE_DDX: 344 fullinst->Instruction.Opcode = TGSI_OPCODE_DDX; 345 break; 346 case OPCODE_DDY: 347 fullinst->Instruction.Opcode = TGSI_OPCODE_DDY; 348 break; 349 case OPCODE_DP3: 350 fullinst->Instruction.Opcode = TGSI_OPCODE_DP3; 351 break; 352 case OPCODE_DP4: 353 fullinst->Instruction.Opcode = TGSI_OPCODE_DP4; 354 break; 355 case OPCODE_DPH: 356 fullinst->Instruction.Opcode = TGSI_OPCODE_DPH; 357 break; 358 case OPCODE_DST: 359 fullinst->Instruction.Opcode = TGSI_OPCODE_DST; 360 break; 361 case OPCODE_ELSE: 362 fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE; 363 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 364 break; 365 case OPCODE_ENDIF: 366 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF; 367 break; 368 case OPCODE_ENDLOOP: 369 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2; 370 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 371 break; 372 case OPCODE_ENDSUB: 373 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB; 374 *insideSubroutine = GL_FALSE; 375 break; 376 case OPCODE_EX2: 377 fullinst->Instruction.Opcode = TGSI_OPCODE_EX2; 378 break; 379 case OPCODE_EXP: 380 fullinst->Instruction.Opcode = TGSI_OPCODE_EXP; 381 break; 382 case OPCODE_FLR: 383 fullinst->Instruction.Opcode = TGSI_OPCODE_FLR; 384 break; 385 case OPCODE_FRC: 386 fullinst->Instruction.Opcode = TGSI_OPCODE_FRC; 387 break; 388 case OPCODE_IF: 389 fullinst->Instruction.Opcode = TGSI_OPCODE_IF; 390 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 391 break; 392 case OPCODE_TRUNC: 393 fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC; 394 break; 395 case OPCODE_KIL: 396 /* conditional */ 397 fullinst->Instruction.Opcode = TGSI_OPCODE_KIL; 398 break; 399 case OPCODE_KIL_NV: 400 /* predicated */ 401 assert(inst->DstReg.CondMask == COND_TR); 402 fullinst->Instruction.Opcode = TGSI_OPCODE_KILP; 403 break; 404 case OPCODE_LG2: 405 fullinst->Instruction.Opcode = TGSI_OPCODE_LG2; 406 break; 407 case OPCODE_LOG: 408 fullinst->Instruction.Opcode = TGSI_OPCODE_LOG; 409 break; 410 case OPCODE_LIT: 411 fullinst->Instruction.Opcode = TGSI_OPCODE_LIT; 412 break; 413 case OPCODE_LRP: 414 fullinst->Instruction.Opcode = TGSI_OPCODE_LRP; 415 break; 416 case OPCODE_MAD: 417 fullinst->Instruction.Opcode = TGSI_OPCODE_MAD; 418 break; 419 case OPCODE_MAX: 420 fullinst->Instruction.Opcode = TGSI_OPCODE_MAX; 421 break; 422 case OPCODE_MIN: 423 fullinst->Instruction.Opcode = TGSI_OPCODE_MIN; 424 break; 425 case OPCODE_MOV: 426 fullinst->Instruction.Opcode = TGSI_OPCODE_MOV; 427 break; 428 case OPCODE_MUL: 429 fullinst->Instruction.Opcode = TGSI_OPCODE_MUL; 430 break; 431 case OPCODE_NOISE1: 432 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1; 433 break; 434 case OPCODE_NOISE2: 435 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2; 436 break; 437 case OPCODE_NOISE3: 438 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3; 439 break; 440 case OPCODE_NOISE4: 441 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4; 442 break; 443 case OPCODE_NOP: 444 fullinst->Instruction.Opcode = TGSI_OPCODE_NOP; 445 break; 446 case OPCODE_POW: 447 fullinst->Instruction.Opcode = TGSI_OPCODE_POW; 448 break; 449 case OPCODE_RCP: 450 fullinst->Instruction.Opcode = TGSI_OPCODE_RCP; 451 break; 452 case OPCODE_RET: 453 /* If RET is used inside main (not a real subroutine) we may want 454 * to execute END instead of RET. TBD... 455 */ 456 if (1 /* *insideSubroutine */) { 457 fullinst->Instruction.Opcode = TGSI_OPCODE_RET; 458 } 459 else { 460 /* inside main() pseudo-function */ 461 fullinst->Instruction.Opcode = TGSI_OPCODE_END; 462 } 463 break; 464 case OPCODE_RSQ: 465 fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ; 466 tgsi_util_set_full_src_register_sign_mode( 467 &fullinst->FullSrcRegisters[0], 468 TGSI_UTIL_SIGN_CLEAR ); 469 break; 470 case OPCODE_SCS: 471 fullinst->Instruction.Opcode = TGSI_OPCODE_SCS; 472 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY; 473 break; 474 case OPCODE_SEQ: 475 fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ; 476 break; 477 case OPCODE_SGE: 478 fullinst->Instruction.Opcode = TGSI_OPCODE_SGE; 479 break; 480 case OPCODE_SGT: 481 fullinst->Instruction.Opcode = TGSI_OPCODE_SGT; 482 break; 483 case OPCODE_SIN: 484 fullinst->Instruction.Opcode = TGSI_OPCODE_SIN; 485 break; 486 case OPCODE_SLE: 487 fullinst->Instruction.Opcode = TGSI_OPCODE_SLE; 488 break; 489 case OPCODE_SLT: 490 fullinst->Instruction.Opcode = TGSI_OPCODE_SLT; 491 break; 492 case OPCODE_SNE: 493 fullinst->Instruction.Opcode = TGSI_OPCODE_SNE; 494 break; 495 case OPCODE_SUB: 496 fullinst->Instruction.Opcode = TGSI_OPCODE_SUB; 497 break; 498 case OPCODE_SWZ: 499 fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ; 500 break; 501 case OPCODE_TEX: 502 /* ordinary texture lookup */ 503 fullinst->Instruction.Opcode = TGSI_OPCODE_TEX; 504 fullinst->Instruction.NumSrcRegs = 2; 505 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 506 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 507 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 508 break; 509 case OPCODE_TXB: 510 /* texture lookup with LOD bias */ 511 fullinst->Instruction.Opcode = TGSI_OPCODE_TXB; 512 fullinst->Instruction.NumSrcRegs = 2; 513 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 514 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 515 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 516 break; 517 case OPCODE_TXD: 518 /* texture lookup with explicit partial derivatives */ 519 fullinst->Instruction.Opcode = TGSI_OPCODE_TXD; 520 fullinst->Instruction.NumSrcRegs = 4; 521 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 522 /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */ 523 fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER; 524 fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit; 525 break; 526 case OPCODE_TXL: 527 /* texture lookup with explicit LOD */ 528 fullinst->Instruction.Opcode = TGSI_OPCODE_TXL; 529 fullinst->Instruction.NumSrcRegs = 2; 530 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 531 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 532 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 533 break; 534 case OPCODE_TXP: 535 /* texture lookup with divide by Q component */ 536 /* convert to TEX w/ special flag for division */ 537 fullinst->Instruction.Opcode = TGSI_OPCODE_TXP; 538 fullinst->Instruction.NumSrcRegs = 2; 539 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 540 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 541 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 542 break; 543 case OPCODE_XPD: 544 fullinst->Instruction.Opcode = TGSI_OPCODE_XPD; 545 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ; 546 break; 547 case OPCODE_END: 548 fullinst->Instruction.Opcode = TGSI_OPCODE_END; 549 break; 550 default: 551 assert( 0 ); 552 } 553} 554 555/** 556 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens 557 */ 558static struct tgsi_full_declaration 559make_input_decl( 560 GLuint index, 561 GLboolean interpolate_info, 562 GLuint interpolate, 563 GLuint usage_mask, 564 GLboolean semantic_info, 565 GLuint semantic_name, 566 GLbitfield semantic_index ) 567{ 568 struct tgsi_full_declaration decl; 569 570 assert(semantic_name < TGSI_SEMANTIC_COUNT); 571 572 decl = tgsi_default_full_declaration(); 573 decl.Declaration.File = TGSI_FILE_INPUT; 574 decl.Declaration.UsageMask = usage_mask; 575 decl.Declaration.Semantic = semantic_info; 576 decl.DeclarationRange.First = index; 577 decl.DeclarationRange.Last = index; 578 if (semantic_info) { 579 decl.Semantic.SemanticName = semantic_name; 580 decl.Semantic.SemanticIndex = semantic_index; 581 } 582 if (interpolate_info) { 583 decl.Declaration.Interpolate = interpolate; 584 } 585 586 return decl; 587} 588 589/** 590 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens 591 */ 592static struct tgsi_full_declaration 593make_output_decl( 594 GLuint index, 595 GLuint semantic_name, 596 GLuint semantic_index, 597 GLbitfield usage_mask ) 598{ 599 struct tgsi_full_declaration decl; 600 601 assert(semantic_name < TGSI_SEMANTIC_COUNT); 602 603 decl = tgsi_default_full_declaration(); 604 decl.Declaration.File = TGSI_FILE_OUTPUT; 605 decl.Declaration.UsageMask = usage_mask; 606 decl.Declaration.Semantic = 1; 607 decl.DeclarationRange.First = index; 608 decl.DeclarationRange.Last = index; 609 decl.Semantic.SemanticName = semantic_name; 610 decl.Semantic.SemanticIndex = semantic_index; 611 612 return decl; 613} 614 615 616static struct tgsi_full_declaration 617make_temp_decl( 618 GLuint start_index, 619 GLuint end_index ) 620{ 621 struct tgsi_full_declaration decl; 622 decl = tgsi_default_full_declaration(); 623 decl.Declaration.File = TGSI_FILE_TEMPORARY; 624 decl.DeclarationRange.First = start_index; 625 decl.DeclarationRange.Last = end_index; 626 return decl; 627} 628 629static struct tgsi_full_declaration 630make_addr_decl( 631 GLuint start_index, 632 GLuint end_index ) 633{ 634 struct tgsi_full_declaration decl; 635 636 decl = tgsi_default_full_declaration(); 637 decl.Declaration.File = TGSI_FILE_ADDRESS; 638 decl.DeclarationRange.First = start_index; 639 decl.DeclarationRange.Last = end_index; 640 return decl; 641} 642 643static struct tgsi_full_declaration 644make_sampler_decl(GLuint index) 645{ 646 struct tgsi_full_declaration decl; 647 decl = tgsi_default_full_declaration(); 648 decl.Declaration.File = TGSI_FILE_SAMPLER; 649 decl.DeclarationRange.First = index; 650 decl.DeclarationRange.Last = index; 651 return decl; 652} 653 654/** Reference into a constant buffer */ 655static struct tgsi_full_declaration 656make_constant_decl(GLuint first, GLuint last) 657{ 658 struct tgsi_full_declaration decl; 659 decl = tgsi_default_full_declaration(); 660 decl.Declaration.File = TGSI_FILE_CONSTANT; 661 decl.DeclarationRange.First = first; 662 decl.DeclarationRange.Last = last; 663 return decl; 664} 665 666 667 668/** 669 * Find the temporaries which are used in the given program. 670 */ 671static void 672find_temporaries(const struct gl_program *program, 673 GLboolean tempsUsed[MAX_PROGRAM_TEMPS]) 674{ 675 GLuint i, j; 676 677 for (i = 0; i < MAX_PROGRAM_TEMPS; i++) 678 tempsUsed[i] = GL_FALSE; 679 680 for (i = 0; i < program->NumInstructions; i++) { 681 const struct prog_instruction *inst = program->Instructions + i; 682 const GLuint n = _mesa_num_inst_src_regs( inst->Opcode ); 683 for (j = 0; j < n; j++) { 684 if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) 685 tempsUsed[inst->SrcReg[j].Index] = GL_TRUE; 686 if (inst->DstReg.File == PROGRAM_TEMPORARY) 687 tempsUsed[inst->DstReg.Index] = GL_TRUE; 688 } 689 } 690} 691 692 693 694 695/** 696 * Translate Mesa program to TGSI format. 697 * \param program the program to translate 698 * \param numInputs number of input registers used 699 * \param inputMapping maps Mesa fragment program inputs to TGSI generic 700 * input indexes 701 * \param inputSemanticName the TGSI_SEMANTIC flag for each input 702 * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input 703 * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input 704 705 * \param numOutputs number of output registers used 706 * \param outputMapping maps Mesa fragment program outputs to TGSI 707 * generic outputs 708 * \param outputSemanticName the TGSI_SEMANTIC flag for each output 709 * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output 710 * \param tokens array to store translated tokens in 711 * \param maxTokens size of the tokens array 712 * 713 * \return number of tokens placed in 'tokens' buffer, or zero if error 714 */ 715GLuint 716st_translate_mesa_program( 717 uint procType, 718 const struct gl_program *program, 719 GLuint numInputs, 720 const GLuint inputMapping[], 721 const ubyte inputSemanticName[], 722 const ubyte inputSemanticIndex[], 723 const GLuint interpMode[], 724 GLuint numOutputs, 725 const GLuint outputMapping[], 726 const ubyte outputSemanticName[], 727 const ubyte outputSemanticIndex[], 728 struct tgsi_token *tokens, 729 GLuint maxTokens ) 730{ 731 GLuint i; 732 GLuint ti; /* token index */ 733 struct tgsi_header *header; 734 struct tgsi_processor *processor; 735 struct tgsi_full_instruction fullinst; 736 GLuint preamble_size = 0; 737 GLuint immediates[1000]; 738 GLuint numImmediates = 0; 739 GLboolean insideSubroutine = GL_FALSE; 740 GLboolean indirectAccess = GL_FALSE; 741 742 assert(procType == TGSI_PROCESSOR_FRAGMENT || 743 procType == TGSI_PROCESSOR_VERTEX); 744 745 *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); 746 747 header = (struct tgsi_header *) &tokens[1]; 748 *header = tgsi_build_header(); 749 750 processor = (struct tgsi_processor *) &tokens[2]; 751 *processor = tgsi_build_processor( procType, header ); 752 753 ti = 3; 754 755 /* 756 * Declare input attributes. 757 */ 758 if (procType == TGSI_PROCESSOR_FRAGMENT) { 759 for (i = 0; i < numInputs; i++) { 760 struct tgsi_full_declaration fulldecl; 761 fulldecl = make_input_decl(i, 762 GL_TRUE, interpMode[i], 763 TGSI_WRITEMASK_XYZW, 764 GL_TRUE, inputSemanticName[i], 765 inputSemanticIndex[i]); 766 ti += tgsi_build_full_declaration(&fulldecl, 767 &tokens[ti], 768 header, 769 maxTokens - ti ); 770 } 771 } 772 else { 773 /* vertex prog */ 774 /* XXX: this could probaby be merged with the clause above. 775 * the only difference is the semantic tags. 776 */ 777 for (i = 0; i < numInputs; i++) { 778 struct tgsi_full_declaration fulldecl; 779 fulldecl = make_input_decl(i, 780 GL_FALSE, 0, 781 TGSI_WRITEMASK_XYZW, 782 GL_FALSE, 0, 0); 783 ti += tgsi_build_full_declaration(&fulldecl, 784 &tokens[ti], 785 header, 786 maxTokens - ti ); 787 } 788 } 789 790 /* 791 * Declare output attributes. 792 */ 793 if (procType == TGSI_PROCESSOR_FRAGMENT) { 794 for (i = 0; i < numOutputs; i++) { 795 struct tgsi_full_declaration fulldecl; 796 switch (outputSemanticName[i]) { 797 case TGSI_SEMANTIC_POSITION: 798 fulldecl = make_output_decl(i, 799 TGSI_SEMANTIC_POSITION, /* Z / Depth */ 800 outputSemanticIndex[i], 801 TGSI_WRITEMASK_Z ); 802 break; 803 case TGSI_SEMANTIC_COLOR: 804 fulldecl = make_output_decl(i, 805 TGSI_SEMANTIC_COLOR, 806 outputSemanticIndex[i], 807 TGSI_WRITEMASK_XYZW ); 808 break; 809 default: 810 assert(0); 811 return 0; 812 } 813 ti += tgsi_build_full_declaration(&fulldecl, 814 &tokens[ti], 815 header, 816 maxTokens - ti ); 817 } 818 } 819 else { 820 /* vertex prog */ 821 for (i = 0; i < numOutputs; i++) { 822 struct tgsi_full_declaration fulldecl; 823 fulldecl = make_output_decl(i, 824 outputSemanticName[i], 825 outputSemanticIndex[i], 826 TGSI_WRITEMASK_XYZW ); 827 ti += tgsi_build_full_declaration(&fulldecl, 828 &tokens[ti], 829 header, 830 maxTokens - ti ); 831 } 832 } 833 834 /* temporary decls */ 835 { 836 GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1]; 837 GLboolean inside_range = GL_FALSE; 838 GLuint start_range = 0; 839 840 find_temporaries(program, tempsUsed); 841 tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE; 842 for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) { 843 if (tempsUsed[i] && !inside_range) { 844 inside_range = GL_TRUE; 845 start_range = i; 846 } 847 else if (!tempsUsed[i] && inside_range) { 848 struct tgsi_full_declaration fulldecl; 849 850 inside_range = GL_FALSE; 851 fulldecl = make_temp_decl( start_range, i - 1 ); 852 ti += tgsi_build_full_declaration( 853 &fulldecl, 854 &tokens[ti], 855 header, 856 maxTokens - ti ); 857 } 858 } 859 } 860 861 /* Declare address register. 862 */ 863 if (program->NumAddressRegs > 0) { 864 struct tgsi_full_declaration fulldecl; 865 866 assert( program->NumAddressRegs == 1 ); 867 868 fulldecl = make_addr_decl( 0, 0 ); 869 ti += tgsi_build_full_declaration( 870 &fulldecl, 871 &tokens[ti], 872 header, 873 maxTokens - ti ); 874 875 indirectAccess = GL_TRUE; 876 } 877 878 /* immediates/literals */ 879 memset(immediates, ~0, sizeof(immediates)); 880 881 /* Emit immediates only when there is no address register in use. 882 * FIXME: Be smarter and recognize param arrays -- indirect addressing is 883 * only valid within the referenced array. 884 */ 885 if (program->Parameters && !indirectAccess) { 886 for (i = 0; i < program->Parameters->NumParameters; i++) { 887 if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) { 888 struct tgsi_full_immediate fullimm; 889 890 fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 ); 891 ti += tgsi_build_full_immediate( 892 &fullimm, 893 &tokens[ti], 894 header, 895 maxTokens - ti ); 896 immediates[i] = numImmediates; 897 numImmediates++; 898 } 899 } 900 } 901 902 /* constant buffer refs */ 903 if (program->Parameters) { 904 GLint start = -1, end = -1; 905 906 for (i = 0; i < program->Parameters->NumParameters; i++) { 907 GLboolean emit = (i == program->Parameters->NumParameters - 1); 908 GLboolean matches; 909 910 switch (program->Parameters->Parameters[i].Type) { 911 case PROGRAM_ENV_PARAM: 912 case PROGRAM_STATE_VAR: 913 case PROGRAM_NAMED_PARAM: 914 case PROGRAM_UNIFORM: 915 matches = GL_TRUE; 916 break; 917 case PROGRAM_CONSTANT: 918 matches = indirectAccess; 919 break; 920 default: 921 matches = GL_FALSE; 922 } 923 924 if (matches) { 925 if (start == -1) { 926 /* begin a sequence */ 927 start = i; 928 end = i; 929 } 930 else { 931 /* continue sequence */ 932 end = i; 933 } 934 } 935 else { 936 if (start != -1) { 937 /* end of sequence */ 938 emit = GL_TRUE; 939 } 940 } 941 942 if (emit && start >= 0) { 943 struct tgsi_full_declaration fulldecl; 944 945 fulldecl = make_constant_decl( start, end ); 946 ti += tgsi_build_full_declaration( 947 &fulldecl, 948 &tokens[ti], 949 header, 950 maxTokens - ti ); 951 start = end = -1; 952 } 953 } 954 } 955 956 /* texture samplers */ 957 for (i = 0; i < 8; i++) { 958 if (program->SamplersUsed & (1 << i)) { 959 struct tgsi_full_declaration fulldecl; 960 961 fulldecl = make_sampler_decl( i ); 962 ti += tgsi_build_full_declaration( 963 &fulldecl, 964 &tokens[ti], 965 header, 966 maxTokens - ti ); 967 } 968 } 969 970 for (i = 0; i < program->NumInstructions; i++) { 971 compile_instruction( 972 &program->Instructions[i], 973 &fullinst, 974 inputMapping, 975 outputMapping, 976 immediates, 977 indirectAccess, 978 preamble_size, 979 procType, 980 &insideSubroutine ); 981 982 ti += tgsi_build_full_instruction( 983 &fullinst, 984 &tokens[ti], 985 header, 986 maxTokens - ti ); 987 } 988 989#if DEBUG 990 if(!tgsi_sanity_check(tokens)) { 991 debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n"); 992 debug_printf("\nOriginal program:\n%s", program->String); 993 debug_printf("\nMesa program:\n"); 994 _mesa_print_program(program); 995 debug_printf("\nTGSI program:\n"); 996 tgsi_dump(tokens, 0); 997 assert(0); 998 } 999#endif 1000 1001 return ti; 1002} 1003