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