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