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 ctx->emit_declaration(ctx, &decl); 128} 129 130static inline void 131tgsi_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 151static inline void 152tgsi_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 172static inline void 173tgsi_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 185static inline void 186tgsi_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 207static inline void 208tgsi_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 224static inline void 225tgsi_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 233static inline void 234tgsi_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 */ 250static inline void 251tgsi_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 275static inline void 276tgsi_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 306static inline void 307tgsi_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 340static inline void 341tgsi_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 382static inline void 383tgsi_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 435static inline void 436tgsi_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 497static inline void 498tgsi_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 522static inline void 523tgsi_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 552extern int 553tgsi_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