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 */ 41struct 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 */ 97static inline void 98tgsi_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 110static inline void 111tgsi_transform_temp_decl(struct tgsi_transform_context *ctx, 112 unsigned index) 113{ 114 tgsi_transform_temps_decl(ctx, index, index); 115} 116 117static inline void 118tgsi_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 decl.Declaration.Dimension = 1; 128 /* Dim.Index2D is already 0 */ 129 ctx->emit_declaration(ctx, &decl); 130} 131 132static inline void 133tgsi_transform_input_decl(struct tgsi_transform_context *ctx, 134 unsigned index, 135 unsigned sem_name, unsigned sem_index, 136 unsigned interp) 137{ 138 struct tgsi_full_declaration decl; 139 140 decl = tgsi_default_full_declaration(); 141 decl.Declaration.File = TGSI_FILE_INPUT; 142 decl.Declaration.Interpolate = 1; 143 decl.Declaration.Semantic = 1; 144 decl.Semantic.Name = sem_name; 145 decl.Semantic.Index = sem_index; 146 decl.Range.First = 147 decl.Range.Last = index; 148 decl.Interp.Interpolate = interp; 149 150 ctx->emit_declaration(ctx, &decl); 151} 152 153static inline void 154tgsi_transform_output_decl(struct tgsi_transform_context *ctx, 155 unsigned index, 156 unsigned sem_name, unsigned sem_index, 157 unsigned interp) 158{ 159 struct tgsi_full_declaration decl; 160 161 decl = tgsi_default_full_declaration(); 162 decl.Declaration.File = TGSI_FILE_OUTPUT; 163 decl.Declaration.Interpolate = 1; 164 decl.Declaration.Semantic = 1; 165 decl.Semantic.Name = sem_name; 166 decl.Semantic.Index = sem_index; 167 decl.Range.First = 168 decl.Range.Last = index; 169 decl.Interp.Interpolate = interp; 170 171 ctx->emit_declaration(ctx, &decl); 172} 173 174static inline void 175tgsi_transform_sampler_decl(struct tgsi_transform_context *ctx, 176 unsigned index) 177{ 178 struct tgsi_full_declaration decl; 179 180 decl = tgsi_default_full_declaration(); 181 decl.Declaration.File = TGSI_FILE_SAMPLER; 182 decl.Range.First = 183 decl.Range.Last = index; 184 ctx->emit_declaration(ctx, &decl); 185} 186 187static inline void 188tgsi_transform_sampler_view_decl(struct tgsi_transform_context *ctx, 189 unsigned index, 190 unsigned target, 191 enum tgsi_return_type type) 192{ 193 struct tgsi_full_declaration decl; 194 195 decl = tgsi_default_full_declaration(); 196 decl.Declaration.File = TGSI_FILE_SAMPLER_VIEW; 197 decl.Declaration.UsageMask = TGSI_WRITEMASK_XYZW; 198 decl.Range.First = 199 decl.Range.Last = index; 200 decl.SamplerView.Resource = target; 201 decl.SamplerView.ReturnTypeX = type; 202 decl.SamplerView.ReturnTypeY = type; 203 decl.SamplerView.ReturnTypeZ = type; 204 decl.SamplerView.ReturnTypeW = type; 205 206 ctx->emit_declaration(ctx, &decl); 207} 208 209static inline void 210tgsi_transform_immediate_decl(struct tgsi_transform_context *ctx, 211 float x, float y, float z, float w) 212{ 213 struct tgsi_full_immediate immed; 214 unsigned size = 4; 215 216 immed = tgsi_default_full_immediate(); 217 immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ 218 immed.u[0].Float = x; 219 immed.u[1].Float = y; 220 immed.u[2].Float = z; 221 immed.u[3].Float = w; 222 223 ctx->emit_immediate(ctx, &immed); 224} 225 226static inline void 227tgsi_transform_immediate_int_decl(struct tgsi_transform_context *ctx, 228 int x, int y, int z, int w) 229{ 230 struct tgsi_full_immediate immed; 231 unsigned size = 4; 232 233 immed = tgsi_default_full_immediate(); 234 immed.Immediate.DataType = TGSI_IMM_INT32; 235 immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ 236 immed.u[0].Int = x; 237 immed.u[1].Int = y; 238 immed.u[2].Int = z; 239 immed.u[3].Int = w; 240 241 ctx->emit_immediate(ctx, &immed); 242} 243 244static inline void 245tgsi_transform_dst_reg(struct tgsi_full_dst_register *reg, 246 unsigned file, unsigned index, unsigned writemask) 247{ 248 reg->Register.File = file; 249 reg->Register.Index = index; 250 reg->Register.WriteMask = writemask; 251} 252 253static inline void 254tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register *reg, 255 unsigned file, unsigned index) 256{ 257 reg->Register.File = file; 258 reg->Register.Index = index; 259 if (file == TGSI_FILE_CONSTANT) { 260 reg->Register.Dimension = 1; 261 reg->Dimension.Index = 0; 262 } 263} 264 265static inline void 266tgsi_transform_src_reg(struct tgsi_full_src_register *reg, 267 unsigned file, unsigned index, 268 unsigned swizzleX, unsigned swizzleY, 269 unsigned swizzleZ, unsigned swizzleW) 270{ 271 reg->Register.File = file; 272 reg->Register.Index = index; 273 if (file == TGSI_FILE_CONSTANT) { 274 reg->Register.Dimension = 1; 275 reg->Dimension.Index = 0; 276 } 277 reg->Register.SwizzleX = swizzleX; 278 reg->Register.SwizzleY = swizzleY; 279 reg->Register.SwizzleZ = swizzleZ; 280 reg->Register.SwizzleW = swizzleW; 281} 282 283/** 284 * Helper for emitting 1-operand instructions. 285 */ 286static inline void 287tgsi_transform_op1_inst(struct tgsi_transform_context *ctx, 288 enum tgsi_opcode opcode, 289 unsigned dst_file, 290 unsigned dst_index, 291 unsigned dst_writemask, 292 unsigned src0_file, 293 unsigned src0_index) 294{ 295 struct tgsi_full_instruction inst; 296 297 inst = tgsi_default_full_instruction(); 298 inst.Instruction.Opcode = opcode; 299 inst.Instruction.NumDstRegs = 1; 300 inst.Dst[0].Register.File = dst_file, 301 inst.Dst[0].Register.Index = dst_index; 302 inst.Dst[0].Register.WriteMask = dst_writemask; 303 inst.Instruction.NumSrcRegs = 1; 304 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 305 306 ctx->emit_instruction(ctx, &inst); 307} 308 309 310static inline void 311tgsi_transform_op2_inst(struct tgsi_transform_context *ctx, 312 enum tgsi_opcode opcode, 313 unsigned dst_file, 314 unsigned dst_index, 315 unsigned dst_writemask, 316 unsigned src0_file, 317 unsigned src0_index, 318 unsigned src1_file, 319 unsigned src1_index, 320 bool src1_negate) 321{ 322 struct tgsi_full_instruction inst; 323 324 inst = tgsi_default_full_instruction(); 325 inst.Instruction.Opcode = opcode; 326 inst.Instruction.NumDstRegs = 1; 327 inst.Dst[0].Register.File = dst_file, 328 inst.Dst[0].Register.Index = dst_index; 329 inst.Dst[0].Register.WriteMask = dst_writemask; 330 inst.Instruction.NumSrcRegs = 2; 331 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 332 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 333 inst.Src[1].Register.Negate = src1_negate; 334 335 ctx->emit_instruction(ctx, &inst); 336} 337 338 339static inline void 340tgsi_transform_op3_inst(struct tgsi_transform_context *ctx, 341 enum tgsi_opcode opcode, 342 unsigned dst_file, 343 unsigned dst_index, 344 unsigned dst_writemask, 345 unsigned src0_file, 346 unsigned src0_index, 347 unsigned src1_file, 348 unsigned src1_index, 349 unsigned src2_file, 350 unsigned src2_index) 351{ 352 struct tgsi_full_instruction inst; 353 354 inst = tgsi_default_full_instruction(); 355 inst.Instruction.Opcode = opcode; 356 inst.Instruction.NumDstRegs = 1; 357 inst.Dst[0].Register.File = dst_file, 358 inst.Dst[0].Register.Index = dst_index; 359 inst.Dst[0].Register.WriteMask = dst_writemask; 360 inst.Instruction.NumSrcRegs = 3; 361 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 362 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 363 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index); 364 365 ctx->emit_instruction(ctx, &inst); 366} 367 368 369 370static inline void 371tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx, 372 enum tgsi_opcode opcode, 373 unsigned dst_file, 374 unsigned dst_index, 375 unsigned dst_writemask, 376 unsigned src0_file, 377 unsigned src0_index, 378 unsigned src0_swizzle) 379{ 380 struct tgsi_full_instruction inst; 381 382 inst = tgsi_default_full_instruction(); 383 inst.Instruction.Opcode = opcode; 384 inst.Instruction.NumDstRegs = 1; 385 inst.Dst[0].Register.File = dst_file, 386 inst.Dst[0].Register.Index = dst_index; 387 inst.Dst[0].Register.WriteMask = dst_writemask; 388 inst.Instruction.NumSrcRegs = 1; 389 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 390 switch (dst_writemask) { 391 case TGSI_WRITEMASK_X: 392 inst.Src[0].Register.SwizzleX = src0_swizzle; 393 break; 394 case TGSI_WRITEMASK_Y: 395 inst.Src[0].Register.SwizzleY = src0_swizzle; 396 break; 397 case TGSI_WRITEMASK_Z: 398 inst.Src[0].Register.SwizzleZ = src0_swizzle; 399 break; 400 case TGSI_WRITEMASK_W: 401 inst.Src[0].Register.SwizzleW = src0_swizzle; 402 break; 403 default: 404 ; /* nothing */ 405 } 406 407 ctx->emit_instruction(ctx, &inst); 408} 409 410 411static inline void 412tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx, 413 enum tgsi_opcode opcode, 414 unsigned dst_file, 415 unsigned dst_index, 416 unsigned dst_writemask, 417 unsigned src0_file, 418 unsigned src0_index, 419 unsigned src0_swizzle, 420 unsigned src1_file, 421 unsigned src1_index, 422 unsigned src1_swizzle, 423 bool src1_negate) 424{ 425 struct tgsi_full_instruction inst; 426 427 inst = tgsi_default_full_instruction(); 428 inst.Instruction.Opcode = opcode; 429 inst.Instruction.NumDstRegs = 1; 430 inst.Dst[0].Register.File = dst_file, 431 inst.Dst[0].Register.Index = dst_index; 432 inst.Dst[0].Register.WriteMask = dst_writemask; 433 inst.Instruction.NumSrcRegs = 2; 434 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 435 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 436 inst.Src[1].Register.Negate = src1_negate; 437 switch (dst_writemask) { 438 case TGSI_WRITEMASK_X: 439 inst.Src[0].Register.SwizzleX = src0_swizzle; 440 inst.Src[1].Register.SwizzleX = src1_swizzle; 441 break; 442 case TGSI_WRITEMASK_Y: 443 inst.Src[0].Register.SwizzleY = src0_swizzle; 444 inst.Src[1].Register.SwizzleY = src1_swizzle; 445 break; 446 case TGSI_WRITEMASK_Z: 447 inst.Src[0].Register.SwizzleZ = src0_swizzle; 448 inst.Src[1].Register.SwizzleZ = src1_swizzle; 449 break; 450 case TGSI_WRITEMASK_W: 451 inst.Src[0].Register.SwizzleW = src0_swizzle; 452 inst.Src[1].Register.SwizzleW = src1_swizzle; 453 break; 454 default: 455 ; /* nothing */ 456 } 457 458 ctx->emit_instruction(ctx, &inst); 459} 460 461 462static inline void 463tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx, 464 enum tgsi_opcode opcode, 465 unsigned dst_file, 466 unsigned dst_index, 467 unsigned dst_writemask, 468 unsigned src0_file, 469 unsigned src0_index, 470 unsigned src0_swizzle, 471 unsigned src0_negate, 472 unsigned src1_file, 473 unsigned src1_index, 474 unsigned src1_swizzle, 475 unsigned src2_file, 476 unsigned src2_index, 477 unsigned src2_swizzle) 478{ 479 struct tgsi_full_instruction inst; 480 481 inst = tgsi_default_full_instruction(); 482 inst.Instruction.Opcode = opcode; 483 inst.Instruction.NumDstRegs = 1; 484 inst.Dst[0].Register.File = dst_file, 485 inst.Dst[0].Register.Index = dst_index; 486 inst.Dst[0].Register.WriteMask = dst_writemask; 487 inst.Instruction.NumSrcRegs = 3; 488 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 489 inst.Src[0].Register.Negate = src0_negate; 490 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 491 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index); 492 switch (dst_writemask) { 493 case TGSI_WRITEMASK_X: 494 inst.Src[0].Register.SwizzleX = src0_swizzle; 495 inst.Src[1].Register.SwizzleX = src1_swizzle; 496 inst.Src[2].Register.SwizzleX = src2_swizzle; 497 break; 498 case TGSI_WRITEMASK_Y: 499 inst.Src[0].Register.SwizzleY = src0_swizzle; 500 inst.Src[1].Register.SwizzleY = src1_swizzle; 501 inst.Src[2].Register.SwizzleY = src2_swizzle; 502 break; 503 case TGSI_WRITEMASK_Z: 504 inst.Src[0].Register.SwizzleZ = src0_swizzle; 505 inst.Src[1].Register.SwizzleZ = src1_swizzle; 506 inst.Src[2].Register.SwizzleZ = src2_swizzle; 507 break; 508 case TGSI_WRITEMASK_W: 509 inst.Src[0].Register.SwizzleW = src0_swizzle; 510 inst.Src[1].Register.SwizzleW = src1_swizzle; 511 inst.Src[2].Register.SwizzleW = src2_swizzle; 512 break; 513 default: 514 ; /* nothing */ 515 } 516 517 ctx->emit_instruction(ctx, &inst); 518} 519 520 521static inline void 522tgsi_transform_kill_inst(struct tgsi_transform_context *ctx, 523 unsigned src_file, 524 unsigned src_index, 525 unsigned src_swizzle, 526 boolean negate) 527{ 528 struct tgsi_full_instruction inst; 529 530 inst = tgsi_default_full_instruction(); 531 inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF; 532 inst.Instruction.NumDstRegs = 0; 533 inst.Instruction.NumSrcRegs = 1; 534 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index); 535 inst.Src[0].Register.SwizzleX = 536 inst.Src[0].Register.SwizzleY = 537 inst.Src[0].Register.SwizzleZ = 538 inst.Src[0].Register.SwizzleW = src_swizzle; 539 inst.Src[0].Register.Negate = negate; 540 541 ctx->emit_instruction(ctx, &inst); 542} 543 544 545static inline void 546tgsi_transform_tex_inst(struct tgsi_transform_context *ctx, 547 unsigned dst_file, 548 unsigned dst_index, 549 unsigned src_file, 550 unsigned src_index, 551 unsigned tex_target, 552 unsigned sampler_index) 553{ 554 struct tgsi_full_instruction inst; 555 556 assert(tex_target < TGSI_TEXTURE_COUNT); 557 558 inst = tgsi_default_full_instruction(); 559 inst.Instruction.Opcode = TGSI_OPCODE_TEX; 560 inst.Instruction.NumDstRegs = 1; 561 inst.Dst[0].Register.File = dst_file; 562 inst.Dst[0].Register.Index = dst_index; 563 inst.Instruction.NumSrcRegs = 2; 564 inst.Instruction.Texture = TRUE; 565 inst.Texture.Texture = tex_target; 566 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index); 567 tgsi_transform_src_reg_xyzw(&inst.Src[1], TGSI_FILE_SAMPLER, sampler_index); 568 569 ctx->emit_instruction(ctx, &inst); 570} 571 572 573extern int 574tgsi_transform_shader(const struct tgsi_token *tokens_in, 575 struct tgsi_token *tokens_out, 576 uint max_tokens_out, 577 struct tgsi_transform_context *ctx); 578 579 580#endif /* TGSI_TRANSFORM_H */ 581