st_mesa_to_tgsi.c revision c5b52b5e0e6f6e47c3953076fa788921b1c5a5e2
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_DP2: 350 fullinst->Instruction.Opcode = TGSI_OPCODE_DP2; 351 break; 352 case OPCODE_DP2A: 353 fullinst->Instruction.Opcode = TGSI_OPCODE_DP2A; 354 break; 355 case OPCODE_DP3: 356 fullinst->Instruction.Opcode = TGSI_OPCODE_DP3; 357 break; 358 case OPCODE_DP4: 359 fullinst->Instruction.Opcode = TGSI_OPCODE_DP4; 360 break; 361 case OPCODE_DPH: 362 fullinst->Instruction.Opcode = TGSI_OPCODE_DPH; 363 break; 364 case OPCODE_DST: 365 fullinst->Instruction.Opcode = TGSI_OPCODE_DST; 366 break; 367 case OPCODE_ELSE: 368 fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE; 369 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 370 break; 371 case OPCODE_ENDIF: 372 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF; 373 break; 374 case OPCODE_ENDLOOP: 375 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2; 376 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 377 break; 378 case OPCODE_ENDSUB: 379 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB; 380 *insideSubroutine = GL_FALSE; 381 break; 382 case OPCODE_EX2: 383 fullinst->Instruction.Opcode = TGSI_OPCODE_EX2; 384 break; 385 case OPCODE_EXP: 386 fullinst->Instruction.Opcode = TGSI_OPCODE_EXP; 387 break; 388 case OPCODE_FLR: 389 fullinst->Instruction.Opcode = TGSI_OPCODE_FLR; 390 break; 391 case OPCODE_FRC: 392 fullinst->Instruction.Opcode = TGSI_OPCODE_FRC; 393 break; 394 case OPCODE_IF: 395 fullinst->Instruction.Opcode = TGSI_OPCODE_IF; 396 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; 397 break; 398 case OPCODE_TRUNC: 399 fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC; 400 break; 401 case OPCODE_KIL: 402 /* conditional */ 403 fullinst->Instruction.Opcode = TGSI_OPCODE_KIL; 404 break; 405 case OPCODE_KIL_NV: 406 /* predicated */ 407 assert(inst->DstReg.CondMask == COND_TR); 408 fullinst->Instruction.Opcode = TGSI_OPCODE_KILP; 409 break; 410 case OPCODE_LG2: 411 fullinst->Instruction.Opcode = TGSI_OPCODE_LG2; 412 break; 413 case OPCODE_LOG: 414 fullinst->Instruction.Opcode = TGSI_OPCODE_LOG; 415 break; 416 case OPCODE_LIT: 417 fullinst->Instruction.Opcode = TGSI_OPCODE_LIT; 418 break; 419 case OPCODE_LRP: 420 fullinst->Instruction.Opcode = TGSI_OPCODE_LRP; 421 break; 422 case OPCODE_MAD: 423 fullinst->Instruction.Opcode = TGSI_OPCODE_MAD; 424 break; 425 case OPCODE_MAX: 426 fullinst->Instruction.Opcode = TGSI_OPCODE_MAX; 427 break; 428 case OPCODE_MIN: 429 fullinst->Instruction.Opcode = TGSI_OPCODE_MIN; 430 break; 431 case OPCODE_MOV: 432 fullinst->Instruction.Opcode = TGSI_OPCODE_MOV; 433 break; 434 case OPCODE_MUL: 435 fullinst->Instruction.Opcode = TGSI_OPCODE_MUL; 436 break; 437 case OPCODE_NOISE1: 438 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1; 439 break; 440 case OPCODE_NOISE2: 441 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2; 442 break; 443 case OPCODE_NOISE3: 444 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3; 445 break; 446 case OPCODE_NOISE4: 447 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4; 448 break; 449 case OPCODE_NOP: 450 fullinst->Instruction.Opcode = TGSI_OPCODE_NOP; 451 break; 452 case OPCODE_NRM3: 453 fullinst->Instruction.Opcode = TGSI_OPCODE_NRM; 454 break; 455 case OPCODE_NRM4: 456 fullinst->Instruction.Opcode = TGSI_OPCODE_NRM4; 457 break; 458 case OPCODE_POW: 459 fullinst->Instruction.Opcode = TGSI_OPCODE_POW; 460 break; 461 case OPCODE_RCP: 462 fullinst->Instruction.Opcode = TGSI_OPCODE_RCP; 463 break; 464 case OPCODE_RET: 465 /* If RET is used inside main (not a real subroutine) we may want 466 * to execute END instead of RET. TBD... 467 */ 468 if (1 /* *insideSubroutine */) { 469 fullinst->Instruction.Opcode = TGSI_OPCODE_RET; 470 } 471 else { 472 /* inside main() pseudo-function */ 473 fullinst->Instruction.Opcode = TGSI_OPCODE_END; 474 } 475 break; 476 case OPCODE_RSQ: 477 fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ; 478 tgsi_util_set_full_src_register_sign_mode( 479 &fullinst->FullSrcRegisters[0], 480 TGSI_UTIL_SIGN_CLEAR ); 481 break; 482 case OPCODE_SCS: 483 fullinst->Instruction.Opcode = TGSI_OPCODE_SCS; 484 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY; 485 break; 486 case OPCODE_SEQ: 487 fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ; 488 break; 489 case OPCODE_SGE: 490 fullinst->Instruction.Opcode = TGSI_OPCODE_SGE; 491 break; 492 case OPCODE_SGT: 493 fullinst->Instruction.Opcode = TGSI_OPCODE_SGT; 494 break; 495 case OPCODE_SIN: 496 fullinst->Instruction.Opcode = TGSI_OPCODE_SIN; 497 break; 498 case OPCODE_SLE: 499 fullinst->Instruction.Opcode = TGSI_OPCODE_SLE; 500 break; 501 case OPCODE_SLT: 502 fullinst->Instruction.Opcode = TGSI_OPCODE_SLT; 503 break; 504 case OPCODE_SNE: 505 fullinst->Instruction.Opcode = TGSI_OPCODE_SNE; 506 break; 507 case OPCODE_SSG: 508 fullinst->Instruction.Opcode = TGSI_OPCODE_SSG; 509 break; 510 case OPCODE_SUB: 511 fullinst->Instruction.Opcode = TGSI_OPCODE_SUB; 512 break; 513 case OPCODE_SWZ: 514 fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ; 515 break; 516 case OPCODE_TEX: 517 /* ordinary texture lookup */ 518 fullinst->Instruction.Opcode = TGSI_OPCODE_TEX; 519 fullinst->Instruction.NumSrcRegs = 2; 520 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 521 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 522 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 523 break; 524 case OPCODE_TXB: 525 /* texture lookup with LOD bias */ 526 fullinst->Instruction.Opcode = TGSI_OPCODE_TXB; 527 fullinst->Instruction.NumSrcRegs = 2; 528 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 529 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 530 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 531 break; 532 case OPCODE_TXD: 533 /* texture lookup with explicit partial derivatives */ 534 fullinst->Instruction.Opcode = TGSI_OPCODE_TXD; 535 fullinst->Instruction.NumSrcRegs = 4; 536 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 537 /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */ 538 fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER; 539 fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit; 540 break; 541 case OPCODE_TXL: 542 /* texture lookup with explicit LOD */ 543 fullinst->Instruction.Opcode = TGSI_OPCODE_TXL; 544 fullinst->Instruction.NumSrcRegs = 2; 545 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 546 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 547 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 548 break; 549 case OPCODE_TXP: 550 /* texture lookup with divide by Q component */ 551 /* convert to TEX w/ special flag for division */ 552 fullinst->Instruction.Opcode = TGSI_OPCODE_TXP; 553 fullinst->Instruction.NumSrcRegs = 2; 554 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget ); 555 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; 556 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit; 557 break; 558 case OPCODE_XPD: 559 fullinst->Instruction.Opcode = TGSI_OPCODE_XPD; 560 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ; 561 break; 562 case OPCODE_END: 563 fullinst->Instruction.Opcode = TGSI_OPCODE_END; 564 break; 565 default: 566 assert( 0 ); 567 } 568} 569 570/** 571 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens 572 */ 573static struct tgsi_full_declaration 574make_input_decl( 575 GLuint index, 576 GLboolean interpolate_info, 577 GLuint interpolate, 578 GLuint usage_mask, 579 GLboolean semantic_info, 580 GLuint semantic_name, 581 GLbitfield semantic_index, 582 GLbitfield input_flags) 583{ 584 struct tgsi_full_declaration decl; 585 586 assert(semantic_name < TGSI_SEMANTIC_COUNT); 587 588 decl = tgsi_default_full_declaration(); 589 decl.Declaration.File = TGSI_FILE_INPUT; 590 decl.Declaration.UsageMask = usage_mask; 591 decl.Declaration.Semantic = semantic_info; 592 decl.DeclarationRange.First = index; 593 decl.DeclarationRange.Last = index; 594 if (semantic_info) { 595 decl.Semantic.SemanticName = semantic_name; 596 decl.Semantic.SemanticIndex = semantic_index; 597 } 598 if (interpolate_info) { 599 decl.Declaration.Interpolate = interpolate; 600 } 601 if (input_flags & PROG_PARAM_BIT_CENTROID) 602 decl.Declaration.Centroid = 1; 603 if (input_flags & PROG_PARAM_BIT_INVARIANT) 604 decl.Declaration.Invariant = 1; 605 606 return decl; 607} 608 609/** 610 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens 611 */ 612static struct tgsi_full_declaration 613make_output_decl( 614 GLuint index, 615 GLuint semantic_name, 616 GLuint semantic_index, 617 GLuint usage_mask, 618 GLbitfield output_flags) 619{ 620 struct tgsi_full_declaration decl; 621 622 assert(semantic_name < TGSI_SEMANTIC_COUNT); 623 624 decl = tgsi_default_full_declaration(); 625 decl.Declaration.File = TGSI_FILE_OUTPUT; 626 decl.Declaration.UsageMask = usage_mask; 627 decl.Declaration.Semantic = 1; 628 decl.DeclarationRange.First = index; 629 decl.DeclarationRange.Last = index; 630 decl.Semantic.SemanticName = semantic_name; 631 decl.Semantic.SemanticIndex = semantic_index; 632 if (output_flags & PROG_PARAM_BIT_CENTROID) 633 decl.Declaration.Centroid = 1; 634 if (output_flags & PROG_PARAM_BIT_INVARIANT) 635 decl.Declaration.Invariant = 1; 636 637 return decl; 638} 639 640 641static struct tgsi_full_declaration 642make_temp_decl( 643 GLuint start_index, 644 GLuint end_index ) 645{ 646 struct tgsi_full_declaration decl; 647 decl = tgsi_default_full_declaration(); 648 decl.Declaration.File = TGSI_FILE_TEMPORARY; 649 decl.DeclarationRange.First = start_index; 650 decl.DeclarationRange.Last = end_index; 651 return decl; 652} 653 654static struct tgsi_full_declaration 655make_addr_decl( 656 GLuint start_index, 657 GLuint end_index ) 658{ 659 struct tgsi_full_declaration decl; 660 661 decl = tgsi_default_full_declaration(); 662 decl.Declaration.File = TGSI_FILE_ADDRESS; 663 decl.DeclarationRange.First = start_index; 664 decl.DeclarationRange.Last = end_index; 665 return decl; 666} 667 668static struct tgsi_full_declaration 669make_sampler_decl(GLuint index) 670{ 671 struct tgsi_full_declaration decl; 672 decl = tgsi_default_full_declaration(); 673 decl.Declaration.File = TGSI_FILE_SAMPLER; 674 decl.DeclarationRange.First = index; 675 decl.DeclarationRange.Last = index; 676 return decl; 677} 678 679/** Reference into a constant buffer */ 680static struct tgsi_full_declaration 681make_constant_decl(GLuint first, GLuint last) 682{ 683 struct tgsi_full_declaration decl; 684 decl = tgsi_default_full_declaration(); 685 decl.Declaration.File = TGSI_FILE_CONSTANT; 686 decl.DeclarationRange.First = first; 687 decl.DeclarationRange.Last = last; 688 return decl; 689} 690 691 692 693/** 694 * Find the temporaries which are used in the given program. 695 */ 696static void 697find_temporaries(const struct gl_program *program, 698 GLboolean tempsUsed[MAX_PROGRAM_TEMPS]) 699{ 700 GLuint i, j; 701 702 for (i = 0; i < MAX_PROGRAM_TEMPS; i++) 703 tempsUsed[i] = GL_FALSE; 704 705 for (i = 0; i < program->NumInstructions; i++) { 706 const struct prog_instruction *inst = program->Instructions + i; 707 const GLuint n = _mesa_num_inst_src_regs( inst->Opcode ); 708 for (j = 0; j < n; j++) { 709 if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) 710 tempsUsed[inst->SrcReg[j].Index] = GL_TRUE; 711 if (inst->DstReg.File == PROGRAM_TEMPORARY) 712 tempsUsed[inst->DstReg.Index] = GL_TRUE; 713 } 714 } 715} 716 717 718 719 720/** 721 * Translate Mesa program to TGSI format. 722 * \param program the program to translate 723 * \param numInputs number of input registers used 724 * \param inputMapping maps Mesa fragment program inputs to TGSI generic 725 * input indexes 726 * \param inputSemanticName the TGSI_SEMANTIC flag for each input 727 * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input 728 * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input 729 730 * \param numOutputs number of output registers used 731 * \param outputMapping maps Mesa fragment program outputs to TGSI 732 * generic outputs 733 * \param outputSemanticName the TGSI_SEMANTIC flag for each output 734 * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output 735 * \param tokens array to store translated tokens in 736 * \param maxTokens size of the tokens array 737 * 738 * \return number of tokens placed in 'tokens' buffer, or zero if error 739 */ 740GLuint 741st_translate_mesa_program( 742 uint procType, 743 const struct gl_program *program, 744 GLuint numInputs, 745 const GLuint inputMapping[], 746 const ubyte inputSemanticName[], 747 const ubyte inputSemanticIndex[], 748 const GLuint interpMode[], 749 const GLbitfield inputFlags[], 750 GLuint numOutputs, 751 const GLuint outputMapping[], 752 const ubyte outputSemanticName[], 753 const ubyte outputSemanticIndex[], 754 const GLbitfield outputFlags[], 755 struct tgsi_token *tokens, 756 GLuint maxTokens ) 757{ 758 GLuint i; 759 GLuint ti; /* token index */ 760 struct tgsi_header *header; 761 struct tgsi_processor *processor; 762 struct tgsi_full_instruction fullinst; 763 GLuint preamble_size = 0; 764 GLuint immediates[1000]; 765 GLuint numImmediates = 0; 766 GLboolean insideSubroutine = GL_FALSE; 767 GLboolean indirectAccess = GL_FALSE; 768 769 assert(procType == TGSI_PROCESSOR_FRAGMENT || 770 procType == TGSI_PROCESSOR_VERTEX); 771 772 *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); 773 774 header = (struct tgsi_header *) &tokens[1]; 775 *header = tgsi_build_header(); 776 777 processor = (struct tgsi_processor *) &tokens[2]; 778 *processor = tgsi_build_processor( procType, header ); 779 780 ti = 3; 781 782 /* 783 * Declare input attributes. 784 */ 785 if (procType == TGSI_PROCESSOR_FRAGMENT) { 786 for (i = 0; i < numInputs; i++) { 787 struct tgsi_full_declaration fulldecl; 788 fulldecl = make_input_decl(i, 789 GL_TRUE, interpMode[i], 790 TGSI_WRITEMASK_XYZW, 791 GL_TRUE, inputSemanticName[i], 792 inputSemanticIndex[i], 793 inputFlags[i]); 794 ti += tgsi_build_full_declaration(&fulldecl, 795 &tokens[ti], 796 header, 797 maxTokens - ti ); 798 } 799 } 800 else { 801 /* vertex prog */ 802 /* XXX: this could probaby be merged with the clause above. 803 * the only difference is the semantic tags. 804 */ 805 for (i = 0; i < numInputs; i++) { 806 struct tgsi_full_declaration fulldecl; 807 fulldecl = make_input_decl(i, 808 GL_FALSE, 0, 809 TGSI_WRITEMASK_XYZW, 810 GL_FALSE, 0, 0, 811 inputFlags[i]); 812 ti += tgsi_build_full_declaration(&fulldecl, 813 &tokens[ti], 814 header, 815 maxTokens - ti ); 816 } 817 } 818 819 /* 820 * Declare output attributes. 821 */ 822 if (procType == TGSI_PROCESSOR_FRAGMENT) { 823 for (i = 0; i < numOutputs; i++) { 824 struct tgsi_full_declaration fulldecl; 825 switch (outputSemanticName[i]) { 826 case TGSI_SEMANTIC_POSITION: 827 fulldecl = make_output_decl(i, 828 TGSI_SEMANTIC_POSITION, /* Z / Depth */ 829 outputSemanticIndex[i], 830 TGSI_WRITEMASK_Z, 831 outputFlags[i]); 832 break; 833 case TGSI_SEMANTIC_COLOR: 834 fulldecl = make_output_decl(i, 835 TGSI_SEMANTIC_COLOR, 836 outputSemanticIndex[i], 837 TGSI_WRITEMASK_XYZW, 838 outputFlags[i]); 839 break; 840 default: 841 assert(0); 842 return 0; 843 } 844 ti += tgsi_build_full_declaration(&fulldecl, 845 &tokens[ti], 846 header, 847 maxTokens - ti ); 848 } 849 } 850 else { 851 /* vertex prog */ 852 for (i = 0; i < numOutputs; i++) { 853 struct tgsi_full_declaration fulldecl; 854 fulldecl = make_output_decl(i, 855 outputSemanticName[i], 856 outputSemanticIndex[i], 857 TGSI_WRITEMASK_XYZW, 858 outputFlags[i]); 859 ti += tgsi_build_full_declaration(&fulldecl, 860 &tokens[ti], 861 header, 862 maxTokens - ti ); 863 } 864 } 865 866 /* temporary decls */ 867 { 868 GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1]; 869 GLboolean inside_range = GL_FALSE; 870 GLuint start_range = 0; 871 872 find_temporaries(program, tempsUsed); 873 tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE; 874 for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) { 875 if (tempsUsed[i] && !inside_range) { 876 inside_range = GL_TRUE; 877 start_range = i; 878 } 879 else if (!tempsUsed[i] && inside_range) { 880 struct tgsi_full_declaration fulldecl; 881 882 inside_range = GL_FALSE; 883 fulldecl = make_temp_decl( start_range, i - 1 ); 884 ti += tgsi_build_full_declaration( 885 &fulldecl, 886 &tokens[ti], 887 header, 888 maxTokens - ti ); 889 } 890 } 891 } 892 893 /* Declare address register. 894 */ 895 if (program->NumAddressRegs > 0) { 896 struct tgsi_full_declaration fulldecl; 897 898 assert( program->NumAddressRegs == 1 ); 899 900 fulldecl = make_addr_decl( 0, 0 ); 901 ti += tgsi_build_full_declaration( 902 &fulldecl, 903 &tokens[ti], 904 header, 905 maxTokens - ti ); 906 907 indirectAccess = GL_TRUE; 908 } 909 910 /* immediates/literals */ 911 memset(immediates, ~0, sizeof(immediates)); 912 913 /* Emit immediates only when there is no address register in use. 914 * FIXME: Be smarter and recognize param arrays -- indirect addressing is 915 * only valid within the referenced array. 916 */ 917 if (program->Parameters && !indirectAccess) { 918 for (i = 0; i < program->Parameters->NumParameters; i++) { 919 if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) { 920 struct tgsi_full_immediate fullimm; 921 922 fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 ); 923 ti += tgsi_build_full_immediate( 924 &fullimm, 925 &tokens[ti], 926 header, 927 maxTokens - ti ); 928 immediates[i] = numImmediates; 929 numImmediates++; 930 } 931 } 932 } 933 934 /* constant buffer refs */ 935 if (program->Parameters) { 936 GLint start = -1, end = -1; 937 938 for (i = 0; i < program->Parameters->NumParameters; i++) { 939 GLboolean emit = (i == program->Parameters->NumParameters - 1); 940 GLboolean matches; 941 942 switch (program->Parameters->Parameters[i].Type) { 943 case PROGRAM_ENV_PARAM: 944 case PROGRAM_STATE_VAR: 945 case PROGRAM_NAMED_PARAM: 946 case PROGRAM_UNIFORM: 947 matches = GL_TRUE; 948 break; 949 case PROGRAM_CONSTANT: 950 matches = indirectAccess; 951 break; 952 default: 953 matches = GL_FALSE; 954 } 955 956 if (matches) { 957 if (start == -1) { 958 /* begin a sequence */ 959 start = i; 960 end = i; 961 } 962 else { 963 /* continue sequence */ 964 end = i; 965 } 966 } 967 else { 968 if (start != -1) { 969 /* end of sequence */ 970 emit = GL_TRUE; 971 } 972 } 973 974 if (emit && start >= 0) { 975 struct tgsi_full_declaration fulldecl; 976 977 fulldecl = make_constant_decl( start, end ); 978 ti += tgsi_build_full_declaration( 979 &fulldecl, 980 &tokens[ti], 981 header, 982 maxTokens - ti ); 983 start = end = -1; 984 } 985 } 986 } 987 988 /* texture samplers */ 989 for (i = 0; i < 8; i++) { 990 if (program->SamplersUsed & (1 << i)) { 991 struct tgsi_full_declaration fulldecl; 992 993 fulldecl = make_sampler_decl( i ); 994 ti += tgsi_build_full_declaration( 995 &fulldecl, 996 &tokens[ti], 997 header, 998 maxTokens - ti ); 999 } 1000 } 1001 1002 for (i = 0; i < program->NumInstructions; i++) { 1003 compile_instruction( 1004 &program->Instructions[i], 1005 &fullinst, 1006 inputMapping, 1007 outputMapping, 1008 immediates, 1009 indirectAccess, 1010 preamble_size, 1011 procType, 1012 &insideSubroutine ); 1013 1014 ti += tgsi_build_full_instruction( 1015 &fullinst, 1016 &tokens[ti], 1017 header, 1018 maxTokens - ti ); 1019 } 1020 1021#if DEBUG 1022 if(!tgsi_sanity_check(tokens)) { 1023 debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n"); 1024 debug_printf("\nOriginal program:\n%s", program->String); 1025 debug_printf("\nMesa program:\n"); 1026 _mesa_print_program(program); 1027 debug_printf("\nTGSI program:\n"); 1028 tgsi_dump(tokens, 0); 1029 assert(0); 1030 } 1031#endif 1032 1033 return ti; 1034} 1035