1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 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 VMWARE 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#ifndef TGSI_TRANSFORM_H 29#define TGSI_TRANSFORM_H 30 31 32#include "pipe/p_defines.h" 33#include "pipe/p_shader_tokens.h" 34#include "tgsi/tgsi_parse.h" 35#include "tgsi/tgsi_build.h" 36 37 38 39/** 40 * Subclass this to add caller-specific data 41 */ 42struct tgsi_transform_context 43{ 44/**** PUBLIC ***/ 45 46 /** 47 * User-defined callbacks invoked per instruction. 48 */ 49 void (*transform_instruction)(struct tgsi_transform_context *ctx, 50 struct tgsi_full_instruction *inst); 51 52 void (*transform_declaration)(struct tgsi_transform_context *ctx, 53 struct tgsi_full_declaration *decl); 54 55 void (*transform_immediate)(struct tgsi_transform_context *ctx, 56 struct tgsi_full_immediate *imm); 57 void (*transform_property)(struct tgsi_transform_context *ctx, 58 struct tgsi_full_property *prop); 59 60 /** 61 * Called after last declaration, before first instruction. This is 62 * where the user might insert new declarations and/or instructions. 63 */ 64 void (*prolog)(struct tgsi_transform_context *ctx); 65 66 /** 67 * Called at end of input program to allow caller to append extra 68 * instructions. 69 */ 70 void (*epilog)(struct tgsi_transform_context *ctx); 71 72 enum pipe_shader_type processor; 73 74/*** PRIVATE ***/ 75 76 /** 77 * These are setup by tgsi_transform_shader() and cannot be overridden. 78 * Meant to be called from in the above user callback functions. 79 */ 80 void (*emit_instruction)(struct tgsi_transform_context *ctx, 81 const struct tgsi_full_instruction *inst); 82 void (*emit_declaration)(struct tgsi_transform_context *ctx, 83 const struct tgsi_full_declaration *decl); 84 void (*emit_immediate)(struct tgsi_transform_context *ctx, 85 const struct tgsi_full_immediate *imm); 86 void (*emit_property)(struct tgsi_transform_context *ctx, 87 const struct tgsi_full_property *prop); 88 89 struct tgsi_header *header; 90 uint max_tokens_out; 91 struct tgsi_token *tokens_out; 92 uint ti; 93 bool fail; 94}; 95 96 97/** 98 * Helper for emitting temporary register declarations. 99 */ 100static inline void 101tgsi_transform_temps_decl(struct tgsi_transform_context *ctx, 102 unsigned firstIdx, unsigned lastIdx) 103{ 104 struct tgsi_full_declaration decl; 105 106 decl = tgsi_default_full_declaration(); 107 decl.Declaration.File = TGSI_FILE_TEMPORARY; 108 decl.Range.First = firstIdx; 109 decl.Range.Last = lastIdx; 110 ctx->emit_declaration(ctx, &decl); 111} 112 113static inline void 114tgsi_transform_temp_decl(struct tgsi_transform_context *ctx, 115 unsigned index) 116{ 117 tgsi_transform_temps_decl(ctx, index, index); 118} 119 120static inline void 121tgsi_transform_const_decl(struct tgsi_transform_context *ctx, 122 unsigned firstIdx, unsigned lastIdx) 123{ 124 struct tgsi_full_declaration decl; 125 126 decl = tgsi_default_full_declaration(); 127 decl.Declaration.File = TGSI_FILE_CONSTANT; 128 decl.Range.First = firstIdx; 129 decl.Range.Last = lastIdx; 130 decl.Declaration.Dimension = 1; 131 /* Dim.Index2D is already 0 */ 132 ctx->emit_declaration(ctx, &decl); 133} 134 135static inline void 136tgsi_transform_input_decl(struct tgsi_transform_context *ctx, 137 unsigned index, 138 unsigned sem_name, unsigned sem_index, 139 unsigned interp) 140{ 141 struct tgsi_full_declaration decl; 142 143 decl = tgsi_default_full_declaration(); 144 decl.Declaration.File = TGSI_FILE_INPUT; 145 decl.Declaration.Interpolate = 1; 146 decl.Declaration.Semantic = 1; 147 decl.Semantic.Name = sem_name; 148 decl.Semantic.Index = sem_index; 149 decl.Range.First = 150 decl.Range.Last = index; 151 decl.Interp.Interpolate = interp; 152 153 ctx->emit_declaration(ctx, &decl); 154} 155 156static inline void 157tgsi_transform_output_decl(struct tgsi_transform_context *ctx, 158 unsigned index, 159 unsigned sem_name, unsigned sem_index, 160 unsigned interp) 161{ 162 struct tgsi_full_declaration decl; 163 164 decl = tgsi_default_full_declaration(); 165 decl.Declaration.File = TGSI_FILE_OUTPUT; 166 decl.Declaration.Interpolate = 1; 167 decl.Declaration.Semantic = 1; 168 decl.Semantic.Name = sem_name; 169 decl.Semantic.Index = sem_index; 170 decl.Range.First = 171 decl.Range.Last = index; 172 decl.Interp.Interpolate = interp; 173 174 ctx->emit_declaration(ctx, &decl); 175} 176 177static inline void 178tgsi_transform_sampler_decl(struct tgsi_transform_context *ctx, 179 unsigned index) 180{ 181 struct tgsi_full_declaration decl; 182 183 decl = tgsi_default_full_declaration(); 184 decl.Declaration.File = TGSI_FILE_SAMPLER; 185 decl.Range.First = 186 decl.Range.Last = index; 187 ctx->emit_declaration(ctx, &decl); 188} 189 190static inline void 191tgsi_transform_sampler_view_decl(struct tgsi_transform_context *ctx, 192 unsigned index, 193 unsigned target, 194 enum tgsi_return_type type) 195{ 196 struct tgsi_full_declaration decl; 197 198 decl = tgsi_default_full_declaration(); 199 decl.Declaration.File = TGSI_FILE_SAMPLER_VIEW; 200 decl.Declaration.UsageMask = TGSI_WRITEMASK_XYZW; 201 decl.Range.First = 202 decl.Range.Last = index; 203 decl.SamplerView.Resource = target; 204 decl.SamplerView.ReturnTypeX = type; 205 decl.SamplerView.ReturnTypeY = type; 206 decl.SamplerView.ReturnTypeZ = type; 207 decl.SamplerView.ReturnTypeW = type; 208 209 ctx->emit_declaration(ctx, &decl); 210} 211 212static inline void 213tgsi_transform_immediate_decl(struct tgsi_transform_context *ctx, 214 float x, float y, float z, float w) 215{ 216 struct tgsi_full_immediate immed; 217 unsigned size = 4; 218 219 immed = tgsi_default_full_immediate(); 220 immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ 221 immed.u[0].Float = x; 222 immed.u[1].Float = y; 223 immed.u[2].Float = z; 224 immed.u[3].Float = w; 225 226 ctx->emit_immediate(ctx, &immed); 227} 228 229static inline void 230tgsi_transform_immediate_int_decl(struct tgsi_transform_context *ctx, 231 int x, int y, int z, int w) 232{ 233 struct tgsi_full_immediate immed; 234 unsigned size = 4; 235 236 immed = tgsi_default_full_immediate(); 237 immed.Immediate.DataType = TGSI_IMM_INT32; 238 immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ 239 immed.u[0].Int = x; 240 immed.u[1].Int = y; 241 immed.u[2].Int = z; 242 immed.u[3].Int = w; 243 244 ctx->emit_immediate(ctx, &immed); 245} 246 247static inline void 248tgsi_transform_dst_reg(struct tgsi_full_dst_register *reg, 249 unsigned file, unsigned index, unsigned writemask) 250{ 251 reg->Register.File = file; 252 reg->Register.Index = index; 253 reg->Register.WriteMask = writemask; 254} 255 256static inline void 257tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register *reg, 258 unsigned file, unsigned index) 259{ 260 reg->Register.File = file; 261 reg->Register.Index = index; 262 if (file == TGSI_FILE_CONSTANT) { 263 reg->Register.Dimension = 1; 264 reg->Dimension.Index = 0; 265 } 266} 267 268static inline void 269tgsi_transform_src_reg(struct tgsi_full_src_register *reg, 270 unsigned file, unsigned index, 271 unsigned swizzleX, unsigned swizzleY, 272 unsigned swizzleZ, unsigned swizzleW) 273{ 274 reg->Register.File = file; 275 reg->Register.Index = index; 276 if (file == TGSI_FILE_CONSTANT) { 277 reg->Register.Dimension = 1; 278 reg->Dimension.Index = 0; 279 } 280 reg->Register.SwizzleX = swizzleX; 281 reg->Register.SwizzleY = swizzleY; 282 reg->Register.SwizzleZ = swizzleZ; 283 reg->Register.SwizzleW = swizzleW; 284} 285 286/** 287 * Helper for emitting 1-operand instructions. 288 */ 289static inline void 290tgsi_transform_op1_inst(struct tgsi_transform_context *ctx, 291 enum tgsi_opcode opcode, 292 unsigned dst_file, 293 unsigned dst_index, 294 unsigned dst_writemask, 295 unsigned src0_file, 296 unsigned src0_index) 297{ 298 struct tgsi_full_instruction inst; 299 300 inst = tgsi_default_full_instruction(); 301 inst.Instruction.Opcode = opcode; 302 inst.Instruction.NumDstRegs = 1; 303 inst.Dst[0].Register.File = dst_file, 304 inst.Dst[0].Register.Index = dst_index; 305 inst.Dst[0].Register.WriteMask = dst_writemask; 306 inst.Instruction.NumSrcRegs = 1; 307 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 308 309 ctx->emit_instruction(ctx, &inst); 310} 311 312 313static inline void 314tgsi_transform_op2_inst(struct tgsi_transform_context *ctx, 315 enum tgsi_opcode opcode, 316 unsigned dst_file, 317 unsigned dst_index, 318 unsigned dst_writemask, 319 unsigned src0_file, 320 unsigned src0_index, 321 unsigned src1_file, 322 unsigned src1_index, 323 bool src1_negate) 324{ 325 struct tgsi_full_instruction inst; 326 327 inst = tgsi_default_full_instruction(); 328 inst.Instruction.Opcode = opcode; 329 inst.Instruction.NumDstRegs = 1; 330 inst.Dst[0].Register.File = dst_file, 331 inst.Dst[0].Register.Index = dst_index; 332 inst.Dst[0].Register.WriteMask = dst_writemask; 333 inst.Instruction.NumSrcRegs = 2; 334 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 335 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 336 inst.Src[1].Register.Negate = src1_negate; 337 338 ctx->emit_instruction(ctx, &inst); 339} 340 341 342static inline void 343tgsi_transform_op3_inst(struct tgsi_transform_context *ctx, 344 enum tgsi_opcode opcode, 345 unsigned dst_file, 346 unsigned dst_index, 347 unsigned dst_writemask, 348 unsigned src0_file, 349 unsigned src0_index, 350 unsigned src1_file, 351 unsigned src1_index, 352 unsigned src2_file, 353 unsigned src2_index) 354{ 355 struct tgsi_full_instruction inst; 356 357 inst = tgsi_default_full_instruction(); 358 inst.Instruction.Opcode = opcode; 359 inst.Instruction.NumDstRegs = 1; 360 inst.Dst[0].Register.File = dst_file, 361 inst.Dst[0].Register.Index = dst_index; 362 inst.Dst[0].Register.WriteMask = dst_writemask; 363 inst.Instruction.NumSrcRegs = 3; 364 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 365 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 366 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index); 367 368 ctx->emit_instruction(ctx, &inst); 369} 370 371 372 373static inline void 374tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx, 375 enum tgsi_opcode opcode, 376 unsigned dst_file, 377 unsigned dst_index, 378 unsigned dst_writemask, 379 unsigned src0_file, 380 unsigned src0_index, 381 unsigned src0_swizzle) 382{ 383 struct tgsi_full_instruction inst; 384 385 inst = tgsi_default_full_instruction(); 386 inst.Instruction.Opcode = opcode; 387 inst.Instruction.NumDstRegs = 1; 388 inst.Dst[0].Register.File = dst_file, 389 inst.Dst[0].Register.Index = dst_index; 390 inst.Dst[0].Register.WriteMask = dst_writemask; 391 inst.Instruction.NumSrcRegs = 1; 392 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 393 switch (dst_writemask) { 394 case TGSI_WRITEMASK_X: 395 inst.Src[0].Register.SwizzleX = src0_swizzle; 396 break; 397 case TGSI_WRITEMASK_Y: 398 inst.Src[0].Register.SwizzleY = src0_swizzle; 399 break; 400 case TGSI_WRITEMASK_Z: 401 inst.Src[0].Register.SwizzleZ = src0_swizzle; 402 break; 403 case TGSI_WRITEMASK_W: 404 inst.Src[0].Register.SwizzleW = src0_swizzle; 405 break; 406 default: 407 ; /* nothing */ 408 } 409 410 ctx->emit_instruction(ctx, &inst); 411} 412 413 414static inline void 415tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx, 416 enum tgsi_opcode opcode, 417 unsigned dst_file, 418 unsigned dst_index, 419 unsigned dst_writemask, 420 unsigned src0_file, 421 unsigned src0_index, 422 unsigned src0_swizzle, 423 unsigned src1_file, 424 unsigned src1_index, 425 unsigned src1_swizzle, 426 bool src1_negate) 427{ 428 struct tgsi_full_instruction inst; 429 430 inst = tgsi_default_full_instruction(); 431 inst.Instruction.Opcode = opcode; 432 inst.Instruction.NumDstRegs = 1; 433 inst.Dst[0].Register.File = dst_file, 434 inst.Dst[0].Register.Index = dst_index; 435 inst.Dst[0].Register.WriteMask = dst_writemask; 436 inst.Instruction.NumSrcRegs = 2; 437 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 438 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 439 inst.Src[1].Register.Negate = src1_negate; 440 switch (dst_writemask) { 441 case TGSI_WRITEMASK_X: 442 inst.Src[0].Register.SwizzleX = src0_swizzle; 443 inst.Src[1].Register.SwizzleX = src1_swizzle; 444 break; 445 case TGSI_WRITEMASK_Y: 446 inst.Src[0].Register.SwizzleY = src0_swizzle; 447 inst.Src[1].Register.SwizzleY = src1_swizzle; 448 break; 449 case TGSI_WRITEMASK_Z: 450 inst.Src[0].Register.SwizzleZ = src0_swizzle; 451 inst.Src[1].Register.SwizzleZ = src1_swizzle; 452 break; 453 case TGSI_WRITEMASK_W: 454 inst.Src[0].Register.SwizzleW = src0_swizzle; 455 inst.Src[1].Register.SwizzleW = src1_swizzle; 456 break; 457 default: 458 ; /* nothing */ 459 } 460 461 ctx->emit_instruction(ctx, &inst); 462} 463 464 465static inline void 466tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx, 467 enum tgsi_opcode opcode, 468 unsigned dst_file, 469 unsigned dst_index, 470 unsigned dst_writemask, 471 unsigned src0_file, 472 unsigned src0_index, 473 unsigned src0_swizzle, 474 unsigned src0_negate, 475 unsigned src1_file, 476 unsigned src1_index, 477 unsigned src1_swizzle, 478 unsigned src2_file, 479 unsigned src2_index, 480 unsigned src2_swizzle) 481{ 482 struct tgsi_full_instruction inst; 483 484 inst = tgsi_default_full_instruction(); 485 inst.Instruction.Opcode = opcode; 486 inst.Instruction.NumDstRegs = 1; 487 inst.Dst[0].Register.File = dst_file, 488 inst.Dst[0].Register.Index = dst_index; 489 inst.Dst[0].Register.WriteMask = dst_writemask; 490 inst.Instruction.NumSrcRegs = 3; 491 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 492 inst.Src[0].Register.Negate = src0_negate; 493 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 494 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index); 495 switch (dst_writemask) { 496 case TGSI_WRITEMASK_X: 497 inst.Src[0].Register.SwizzleX = src0_swizzle; 498 inst.Src[1].Register.SwizzleX = src1_swizzle; 499 inst.Src[2].Register.SwizzleX = src2_swizzle; 500 break; 501 case TGSI_WRITEMASK_Y: 502 inst.Src[0].Register.SwizzleY = src0_swizzle; 503 inst.Src[1].Register.SwizzleY = src1_swizzle; 504 inst.Src[2].Register.SwizzleY = src2_swizzle; 505 break; 506 case TGSI_WRITEMASK_Z: 507 inst.Src[0].Register.SwizzleZ = src0_swizzle; 508 inst.Src[1].Register.SwizzleZ = src1_swizzle; 509 inst.Src[2].Register.SwizzleZ = src2_swizzle; 510 break; 511 case TGSI_WRITEMASK_W: 512 inst.Src[0].Register.SwizzleW = src0_swizzle; 513 inst.Src[1].Register.SwizzleW = src1_swizzle; 514 inst.Src[2].Register.SwizzleW = src2_swizzle; 515 break; 516 default: 517 ; /* nothing */ 518 } 519 520 ctx->emit_instruction(ctx, &inst); 521} 522 523 524static inline void 525tgsi_transform_kill_inst(struct tgsi_transform_context *ctx, 526 unsigned src_file, 527 unsigned src_index, 528 unsigned src_swizzle, 529 boolean negate) 530{ 531 struct tgsi_full_instruction inst; 532 533 inst = tgsi_default_full_instruction(); 534 inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF; 535 inst.Instruction.NumDstRegs = 0; 536 inst.Instruction.NumSrcRegs = 1; 537 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index); 538 inst.Src[0].Register.SwizzleX = 539 inst.Src[0].Register.SwizzleY = 540 inst.Src[0].Register.SwizzleZ = 541 inst.Src[0].Register.SwizzleW = src_swizzle; 542 inst.Src[0].Register.Negate = negate; 543 544 ctx->emit_instruction(ctx, &inst); 545} 546 547 548static inline void 549tgsi_transform_tex_inst(struct tgsi_transform_context *ctx, 550 unsigned dst_file, 551 unsigned dst_index, 552 unsigned src_file, 553 unsigned src_index, 554 unsigned tex_target, 555 unsigned sampler_index) 556{ 557 struct tgsi_full_instruction inst; 558 559 assert(tex_target < TGSI_TEXTURE_COUNT); 560 561 inst = tgsi_default_full_instruction(); 562 inst.Instruction.Opcode = TGSI_OPCODE_TEX; 563 inst.Instruction.NumDstRegs = 1; 564 inst.Dst[0].Register.File = dst_file; 565 inst.Dst[0].Register.Index = dst_index; 566 inst.Instruction.NumSrcRegs = 2; 567 inst.Instruction.Texture = TRUE; 568 inst.Texture.Texture = tex_target; 569 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index); 570 tgsi_transform_src_reg_xyzw(&inst.Src[1], TGSI_FILE_SAMPLER, sampler_index); 571 572 ctx->emit_instruction(ctx, &inst); 573} 574 575 576extern struct tgsi_token * 577tgsi_transform_shader(const struct tgsi_token *tokens_in, 578 uint initial_tokens_len, 579 struct tgsi_transform_context *ctx); 580 581 582#endif /* TGSI_TRANSFORM_H */ 583