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_dst_reg(struct tgsi_full_dst_register *reg, 228 unsigned file, unsigned index, unsigned writemask) 229{ 230 reg->Register.File = file; 231 reg->Register.Index = index; 232 reg->Register.WriteMask = writemask; 233} 234 235static inline void 236tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register *reg, 237 unsigned file, unsigned index) 238{ 239 reg->Register.File = file; 240 reg->Register.Index = index; 241 if (file == TGSI_FILE_CONSTANT) { 242 reg->Register.Dimension = 1; 243 reg->Dimension.Index = 0; 244 } 245} 246 247static inline void 248tgsi_transform_src_reg(struct tgsi_full_src_register *reg, 249 unsigned file, unsigned index, 250 unsigned swizzleX, unsigned swizzleY, 251 unsigned swizzleZ, unsigned swizzleW) 252{ 253 reg->Register.File = file; 254 reg->Register.Index = index; 255 if (file == TGSI_FILE_CONSTANT) { 256 reg->Register.Dimension = 1; 257 reg->Dimension.Index = 0; 258 } 259 reg->Register.SwizzleX = swizzleX; 260 reg->Register.SwizzleY = swizzleY; 261 reg->Register.SwizzleZ = swizzleZ; 262 reg->Register.SwizzleW = swizzleW; 263} 264 265/** 266 * Helper for emitting 1-operand instructions. 267 */ 268static inline void 269tgsi_transform_op1_inst(struct tgsi_transform_context *ctx, 270 enum tgsi_opcode opcode, 271 unsigned dst_file, 272 unsigned dst_index, 273 unsigned dst_writemask, 274 unsigned src0_file, 275 unsigned src0_index) 276{ 277 struct tgsi_full_instruction inst; 278 279 inst = tgsi_default_full_instruction(); 280 inst.Instruction.Opcode = opcode; 281 inst.Instruction.NumDstRegs = 1; 282 inst.Dst[0].Register.File = dst_file, 283 inst.Dst[0].Register.Index = dst_index; 284 inst.Dst[0].Register.WriteMask = dst_writemask; 285 inst.Instruction.NumSrcRegs = 1; 286 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 287 288 ctx->emit_instruction(ctx, &inst); 289} 290 291 292static inline void 293tgsi_transform_op2_inst(struct tgsi_transform_context *ctx, 294 enum tgsi_opcode opcode, 295 unsigned dst_file, 296 unsigned dst_index, 297 unsigned dst_writemask, 298 unsigned src0_file, 299 unsigned src0_index, 300 unsigned src1_file, 301 unsigned src1_index, 302 bool src1_negate) 303{ 304 struct tgsi_full_instruction inst; 305 306 inst = tgsi_default_full_instruction(); 307 inst.Instruction.Opcode = opcode; 308 inst.Instruction.NumDstRegs = 1; 309 inst.Dst[0].Register.File = dst_file, 310 inst.Dst[0].Register.Index = dst_index; 311 inst.Dst[0].Register.WriteMask = dst_writemask; 312 inst.Instruction.NumSrcRegs = 2; 313 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 314 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 315 inst.Src[1].Register.Negate = src1_negate; 316 317 ctx->emit_instruction(ctx, &inst); 318} 319 320 321static inline void 322tgsi_transform_op3_inst(struct tgsi_transform_context *ctx, 323 enum tgsi_opcode opcode, 324 unsigned dst_file, 325 unsigned dst_index, 326 unsigned dst_writemask, 327 unsigned src0_file, 328 unsigned src0_index, 329 unsigned src1_file, 330 unsigned src1_index, 331 unsigned src2_file, 332 unsigned src2_index) 333{ 334 struct tgsi_full_instruction inst; 335 336 inst = tgsi_default_full_instruction(); 337 inst.Instruction.Opcode = opcode; 338 inst.Instruction.NumDstRegs = 1; 339 inst.Dst[0].Register.File = dst_file, 340 inst.Dst[0].Register.Index = dst_index; 341 inst.Dst[0].Register.WriteMask = dst_writemask; 342 inst.Instruction.NumSrcRegs = 3; 343 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 344 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 345 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index); 346 347 ctx->emit_instruction(ctx, &inst); 348} 349 350 351 352static inline void 353tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx, 354 enum tgsi_opcode opcode, 355 unsigned dst_file, 356 unsigned dst_index, 357 unsigned dst_writemask, 358 unsigned src0_file, 359 unsigned src0_index, 360 unsigned src0_swizzle) 361{ 362 struct tgsi_full_instruction inst; 363 364 inst = tgsi_default_full_instruction(); 365 inst.Instruction.Opcode = opcode; 366 inst.Instruction.NumDstRegs = 1; 367 inst.Dst[0].Register.File = dst_file, 368 inst.Dst[0].Register.Index = dst_index; 369 inst.Dst[0].Register.WriteMask = dst_writemask; 370 inst.Instruction.NumSrcRegs = 1; 371 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 372 switch (dst_writemask) { 373 case TGSI_WRITEMASK_X: 374 inst.Src[0].Register.SwizzleX = src0_swizzle; 375 break; 376 case TGSI_WRITEMASK_Y: 377 inst.Src[0].Register.SwizzleY = src0_swizzle; 378 break; 379 case TGSI_WRITEMASK_Z: 380 inst.Src[0].Register.SwizzleZ = src0_swizzle; 381 break; 382 case TGSI_WRITEMASK_W: 383 inst.Src[0].Register.SwizzleW = src0_swizzle; 384 break; 385 default: 386 ; /* nothing */ 387 } 388 389 ctx->emit_instruction(ctx, &inst); 390} 391 392 393static inline void 394tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx, 395 enum tgsi_opcode opcode, 396 unsigned dst_file, 397 unsigned dst_index, 398 unsigned dst_writemask, 399 unsigned src0_file, 400 unsigned src0_index, 401 unsigned src0_swizzle, 402 unsigned src1_file, 403 unsigned src1_index, 404 unsigned src1_swizzle, 405 bool src1_negate) 406{ 407 struct tgsi_full_instruction inst; 408 409 inst = tgsi_default_full_instruction(); 410 inst.Instruction.Opcode = opcode; 411 inst.Instruction.NumDstRegs = 1; 412 inst.Dst[0].Register.File = dst_file, 413 inst.Dst[0].Register.Index = dst_index; 414 inst.Dst[0].Register.WriteMask = dst_writemask; 415 inst.Instruction.NumSrcRegs = 2; 416 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 417 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 418 inst.Src[1].Register.Negate = src1_negate; 419 switch (dst_writemask) { 420 case TGSI_WRITEMASK_X: 421 inst.Src[0].Register.SwizzleX = src0_swizzle; 422 inst.Src[1].Register.SwizzleX = src1_swizzle; 423 break; 424 case TGSI_WRITEMASK_Y: 425 inst.Src[0].Register.SwizzleY = src0_swizzle; 426 inst.Src[1].Register.SwizzleY = src1_swizzle; 427 break; 428 case TGSI_WRITEMASK_Z: 429 inst.Src[0].Register.SwizzleZ = src0_swizzle; 430 inst.Src[1].Register.SwizzleZ = src1_swizzle; 431 break; 432 case TGSI_WRITEMASK_W: 433 inst.Src[0].Register.SwizzleW = src0_swizzle; 434 inst.Src[1].Register.SwizzleW = src1_swizzle; 435 break; 436 default: 437 ; /* nothing */ 438 } 439 440 ctx->emit_instruction(ctx, &inst); 441} 442 443 444static inline void 445tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx, 446 enum tgsi_opcode opcode, 447 unsigned dst_file, 448 unsigned dst_index, 449 unsigned dst_writemask, 450 unsigned src0_file, 451 unsigned src0_index, 452 unsigned src0_swizzle, 453 unsigned src0_negate, 454 unsigned src1_file, 455 unsigned src1_index, 456 unsigned src1_swizzle, 457 unsigned src2_file, 458 unsigned src2_index, 459 unsigned src2_swizzle) 460{ 461 struct tgsi_full_instruction inst; 462 463 inst = tgsi_default_full_instruction(); 464 inst.Instruction.Opcode = opcode; 465 inst.Instruction.NumDstRegs = 1; 466 inst.Dst[0].Register.File = dst_file, 467 inst.Dst[0].Register.Index = dst_index; 468 inst.Dst[0].Register.WriteMask = dst_writemask; 469 inst.Instruction.NumSrcRegs = 3; 470 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index); 471 inst.Src[0].Register.Negate = src0_negate; 472 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index); 473 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index); 474 switch (dst_writemask) { 475 case TGSI_WRITEMASK_X: 476 inst.Src[0].Register.SwizzleX = src0_swizzle; 477 inst.Src[1].Register.SwizzleX = src1_swizzle; 478 inst.Src[2].Register.SwizzleX = src2_swizzle; 479 break; 480 case TGSI_WRITEMASK_Y: 481 inst.Src[0].Register.SwizzleY = src0_swizzle; 482 inst.Src[1].Register.SwizzleY = src1_swizzle; 483 inst.Src[2].Register.SwizzleY = src2_swizzle; 484 break; 485 case TGSI_WRITEMASK_Z: 486 inst.Src[0].Register.SwizzleZ = src0_swizzle; 487 inst.Src[1].Register.SwizzleZ = src1_swizzle; 488 inst.Src[2].Register.SwizzleZ = src2_swizzle; 489 break; 490 case TGSI_WRITEMASK_W: 491 inst.Src[0].Register.SwizzleW = src0_swizzle; 492 inst.Src[1].Register.SwizzleW = src1_swizzle; 493 inst.Src[2].Register.SwizzleW = src2_swizzle; 494 break; 495 default: 496 ; /* nothing */ 497 } 498 499 ctx->emit_instruction(ctx, &inst); 500} 501 502 503static inline void 504tgsi_transform_kill_inst(struct tgsi_transform_context *ctx, 505 unsigned src_file, 506 unsigned src_index, 507 unsigned src_swizzle, 508 boolean negate) 509{ 510 struct tgsi_full_instruction inst; 511 512 inst = tgsi_default_full_instruction(); 513 inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF; 514 inst.Instruction.NumDstRegs = 0; 515 inst.Instruction.NumSrcRegs = 1; 516 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index); 517 inst.Src[0].Register.SwizzleX = 518 inst.Src[0].Register.SwizzleY = 519 inst.Src[0].Register.SwizzleZ = 520 inst.Src[0].Register.SwizzleW = src_swizzle; 521 inst.Src[0].Register.Negate = negate; 522 523 ctx->emit_instruction(ctx, &inst); 524} 525 526 527static inline void 528tgsi_transform_tex_inst(struct tgsi_transform_context *ctx, 529 unsigned dst_file, 530 unsigned dst_index, 531 unsigned src_file, 532 unsigned src_index, 533 unsigned tex_target, 534 unsigned sampler_index) 535{ 536 struct tgsi_full_instruction inst; 537 538 assert(tex_target < TGSI_TEXTURE_COUNT); 539 540 inst = tgsi_default_full_instruction(); 541 inst.Instruction.Opcode = TGSI_OPCODE_TEX; 542 inst.Instruction.NumDstRegs = 1; 543 inst.Dst[0].Register.File = dst_file; 544 inst.Dst[0].Register.Index = dst_index; 545 inst.Instruction.NumSrcRegs = 2; 546 inst.Instruction.Texture = TRUE; 547 inst.Texture.Texture = tex_target; 548 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index); 549 tgsi_transform_src_reg_xyzw(&inst.Src[1], TGSI_FILE_SAMPLER, sampler_index); 550 551 ctx->emit_instruction(ctx, &inst); 552} 553 554 555extern int 556tgsi_transform_shader(const struct tgsi_token *tokens_in, 557 struct tgsi_token *tokens_out, 558 uint max_tokens_out, 559 struct tgsi_transform_context *ctx); 560 561 562#endif /* TGSI_TRANSFORM_H */ 563