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