tgsi_ureg.h revision ae4704eabc237e13c9b06df9c44f31c9baca6208
1/************************************************************************** 2 * 3 * Copyright 2009 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, INC 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_UREG_H 29#define TGSI_UREG_H 30 31#include "pipe/p_compiler.h" 32#include "pipe/p_shader_tokens.h" 33 34#ifdef __cplusplus 35extern "C" { 36#endif 37 38struct ureg_program; 39 40/* Almost a tgsi_src_register, but we need to pull in the Absolute 41 * flag from the _ext token. Indirect flag always implies ADDR[0]. 42 */ 43struct ureg_src 44{ 45 unsigned File : 4; /* TGSI_FILE_ */ 46 unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */ 47 unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */ 48 unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */ 49 unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */ 50 unsigned Pad : 1; /* BOOL */ 51 unsigned Indirect : 1; /* BOOL */ 52 unsigned Absolute : 1; /* BOOL */ 53 int Index : 16; /* SINT */ 54 unsigned Negate : 1; /* BOOL */ 55 int IndirectIndex : 16; /* SINT */ 56 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ 57}; 58 59/* Very similar to a tgsi_dst_register, removing unsupported fields 60 * and adding a Saturate flag. It's easier to push saturate into the 61 * destination register than to try and create a _SAT varient of each 62 * instruction function. 63 */ 64struct ureg_dst 65{ 66 unsigned File : 4; /* TGSI_FILE_ */ 67 unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */ 68 unsigned Indirect : 1; /* BOOL */ 69 unsigned Saturate : 1; /* BOOL */ 70 int Index : 16; /* SINT */ 71 unsigned Pad1 : 5; 72 unsigned Pad2 : 1; /* BOOL */ 73 int IndirectIndex : 16; /* SINT */ 74 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ 75}; 76 77struct pipe_context; 78 79struct ureg_program * 80ureg_create( unsigned processor ); 81 82const struct tgsi_token * 83ureg_finalize( struct ureg_program * ); 84 85void * 86ureg_create_shader( struct ureg_program *, 87 struct pipe_context *pipe ); 88 89void 90ureg_destroy( struct ureg_program * ); 91 92 93/*********************************************************************** 94 * Convenience routine: 95 */ 96static INLINE void * 97ureg_create_shader_and_destroy( struct ureg_program *p, 98 struct pipe_context *pipe ) 99{ 100 void *result = ureg_create_shader( p, pipe ); 101 ureg_destroy( p ); 102 return result; 103} 104 105 106 107/*********************************************************************** 108 * Build shader declarations: 109 */ 110 111struct ureg_src 112ureg_DECL_fs_input( struct ureg_program *, 113 unsigned semantic_name, 114 unsigned semantic_index, 115 unsigned interp_mode ); 116 117struct ureg_src 118ureg_DECL_vs_input( struct ureg_program *, 119 unsigned index ); 120 121struct ureg_dst 122ureg_DECL_output( struct ureg_program *, 123 unsigned semantic_name, 124 unsigned semantic_index ); 125 126struct ureg_src 127ureg_DECL_immediate( struct ureg_program *, 128 const float *v, 129 unsigned nr ); 130 131struct ureg_src 132ureg_DECL_constant( struct ureg_program *, 133 unsigned index ); 134 135struct ureg_dst 136ureg_DECL_temporary( struct ureg_program * ); 137 138void 139ureg_release_temporary( struct ureg_program *ureg, 140 struct ureg_dst tmp ); 141 142struct ureg_dst 143ureg_DECL_address( struct ureg_program * ); 144 145/* Supply an index to the sampler declaration as this is the hook to 146 * the external pipe_sampler state. Users of this function probably 147 * don't want just any sampler, but a specific one which they've set 148 * up state for in the context. 149 */ 150struct ureg_src 151ureg_DECL_sampler( struct ureg_program *, 152 unsigned index ); 153 154 155static INLINE struct ureg_src 156ureg_imm4f( struct ureg_program *ureg, 157 float a, float b, 158 float c, float d) 159{ 160 float v[4]; 161 v[0] = a; 162 v[1] = b; 163 v[2] = c; 164 v[3] = d; 165 return ureg_DECL_immediate( ureg, v, 4 ); 166} 167 168static INLINE struct ureg_src 169ureg_imm3f( struct ureg_program *ureg, 170 float a, float b, 171 float c) 172{ 173 float v[3]; 174 v[0] = a; 175 v[1] = b; 176 v[2] = c; 177 return ureg_DECL_immediate( ureg, v, 3 ); 178} 179 180static INLINE struct ureg_src 181ureg_imm2f( struct ureg_program *ureg, 182 float a, float b) 183{ 184 float v[2]; 185 v[0] = a; 186 v[1] = b; 187 return ureg_DECL_immediate( ureg, v, 2 ); 188} 189 190static INLINE struct ureg_src 191ureg_imm1f( struct ureg_program *ureg, 192 float a) 193{ 194 float v[1]; 195 v[0] = a; 196 return ureg_DECL_immediate( ureg, v, 1 ); 197} 198 199/*********************************************************************** 200 * Functions for patching up labels 201 */ 202 203 204/* Will return a number which can be used in a label to point to the 205 * next instruction to be emitted. 206 */ 207unsigned 208ureg_get_instruction_number( struct ureg_program *ureg ); 209 210 211/* Patch a given label (expressed as a token number) to point to a 212 * given instruction (expressed as an instruction number). 213 * 214 * Labels are obtained from instruction emitters, eg ureg_CAL(). 215 * Instruction numbers are obtained from ureg_get_instruction_number(), 216 * above. 217 */ 218void 219ureg_fixup_label(struct ureg_program *ureg, 220 unsigned label_token, 221 unsigned instruction_number ); 222 223 224/* Generic instruction emitter. Use if you need to pass the opcode as 225 * a parameter, rather than using the emit_OP() varients below. 226 */ 227void 228ureg_insn(struct ureg_program *ureg, 229 unsigned opcode, 230 const struct ureg_dst *dst, 231 unsigned nr_dst, 232 const struct ureg_src *src, 233 unsigned nr_src ); 234 235 236/*********************************************************************** 237 * Internal instruction helpers, don't call these directly: 238 */ 239 240unsigned 241ureg_emit_insn(struct ureg_program *ureg, 242 unsigned opcode, 243 boolean saturate, 244 unsigned num_dst, 245 unsigned num_src ); 246 247void 248ureg_emit_label(struct ureg_program *ureg, 249 unsigned insn_token, 250 unsigned *label_token ); 251 252void 253ureg_emit_texture(struct ureg_program *ureg, 254 unsigned insn_token, 255 unsigned target ); 256 257void 258ureg_emit_dst( struct ureg_program *ureg, 259 struct ureg_dst dst ); 260 261void 262ureg_emit_src( struct ureg_program *ureg, 263 struct ureg_src src ); 264 265void 266ureg_fixup_insn_size(struct ureg_program *ureg, 267 unsigned insn ); 268 269 270#define OP00( op ) \ 271static INLINE void ureg_##op( struct ureg_program *ureg ) \ 272{ \ 273 unsigned opcode = TGSI_OPCODE_##op; \ 274 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \ 275 ureg_fixup_insn_size( ureg, insn ); \ 276} 277 278#define OP01( op ) \ 279static INLINE void ureg_##op( struct ureg_program *ureg, \ 280 struct ureg_src src ) \ 281{ \ 282 unsigned opcode = TGSI_OPCODE_##op; \ 283 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \ 284 ureg_emit_src( ureg, src ); \ 285 ureg_fixup_insn_size( ureg, insn ); \ 286} 287 288#define OP00_LBL( op ) \ 289static INLINE void ureg_##op( struct ureg_program *ureg, \ 290 unsigned *label_token ) \ 291{ \ 292 unsigned opcode = TGSI_OPCODE_##op; \ 293 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \ 294 ureg_emit_label( ureg, insn, label_token ); \ 295 ureg_fixup_insn_size( ureg, insn ); \ 296} 297 298#define OP01_LBL( op ) \ 299static INLINE void ureg_##op( struct ureg_program *ureg, \ 300 struct ureg_src src, \ 301 unsigned *label_token ) \ 302{ \ 303 unsigned opcode = TGSI_OPCODE_##op; \ 304 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \ 305 ureg_emit_label( ureg, insn, label_token ); \ 306 ureg_emit_src( ureg, src ); \ 307 ureg_fixup_insn_size( ureg, insn ); \ 308} 309 310#define OP10( op ) \ 311static INLINE void ureg_##op( struct ureg_program *ureg, \ 312 struct ureg_dst dst ) \ 313{ \ 314 unsigned opcode = TGSI_OPCODE_##op; \ 315 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \ 316 ureg_emit_dst( ureg, dst ); \ 317 ureg_fixup_insn_size( ureg, insn ); \ 318} 319 320 321#define OP11( op ) \ 322static INLINE void ureg_##op( struct ureg_program *ureg, \ 323 struct ureg_dst dst, \ 324 struct ureg_src src ) \ 325{ \ 326 unsigned opcode = TGSI_OPCODE_##op; \ 327 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \ 328 ureg_emit_dst( ureg, dst ); \ 329 ureg_emit_src( ureg, src ); \ 330 ureg_fixup_insn_size( ureg, insn ); \ 331} 332 333#define OP12( op ) \ 334static INLINE void ureg_##op( struct ureg_program *ureg, \ 335 struct ureg_dst dst, \ 336 struct ureg_src src0, \ 337 struct ureg_src src1 ) \ 338{ \ 339 unsigned opcode = TGSI_OPCODE_##op; \ 340 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \ 341 ureg_emit_dst( ureg, dst ); \ 342 ureg_emit_src( ureg, src0 ); \ 343 ureg_emit_src( ureg, src1 ); \ 344 ureg_fixup_insn_size( ureg, insn ); \ 345} 346 347#define OP12_TEX( op ) \ 348static INLINE void ureg_##op( struct ureg_program *ureg, \ 349 struct ureg_dst dst, \ 350 unsigned target, \ 351 struct ureg_src src0, \ 352 struct ureg_src src1 ) \ 353{ \ 354 unsigned opcode = TGSI_OPCODE_##op; \ 355 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \ 356 ureg_emit_texture( ureg, insn, target ); \ 357 ureg_emit_dst( ureg, dst ); \ 358 ureg_emit_src( ureg, src0 ); \ 359 ureg_emit_src( ureg, src1 ); \ 360 ureg_fixup_insn_size( ureg, insn ); \ 361} 362 363#define OP13( op ) \ 364static INLINE void ureg_##op( struct ureg_program *ureg, \ 365 struct ureg_dst dst, \ 366 struct ureg_src src0, \ 367 struct ureg_src src1, \ 368 struct ureg_src src2 ) \ 369{ \ 370 unsigned opcode = TGSI_OPCODE_##op; \ 371 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \ 372 ureg_emit_dst( ureg, dst ); \ 373 ureg_emit_src( ureg, src0 ); \ 374 ureg_emit_src( ureg, src1 ); \ 375 ureg_emit_src( ureg, src2 ); \ 376 ureg_fixup_insn_size( ureg, insn ); \ 377} 378 379#define OP14_TEX( op ) \ 380static INLINE void ureg_##op( struct ureg_program *ureg, \ 381 struct ureg_dst dst, \ 382 unsigned target, \ 383 struct ureg_src src0, \ 384 struct ureg_src src1, \ 385 struct ureg_src src2, \ 386 struct ureg_src src3 ) \ 387{ \ 388 unsigned opcode = TGSI_OPCODE_##op; \ 389 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \ 390 ureg_emit_texture( ureg, insn, target ); \ 391 ureg_emit_dst( ureg, dst ); \ 392 ureg_emit_src( ureg, src0 ); \ 393 ureg_emit_src( ureg, src1 ); \ 394 ureg_emit_src( ureg, src2 ); \ 395 ureg_emit_src( ureg, src3 ); \ 396 ureg_fixup_insn_size( ureg, insn ); \ 397} 398 399 400/* Use a template include to generate a correctly-typed ureg_OP() 401 * function for each TGSI opcode: 402 */ 403#include "tgsi_opcode_tmp.h" 404 405 406/*********************************************************************** 407 * Inline helpers for manipulating register structs: 408 */ 409static INLINE struct ureg_src 410ureg_negate( struct ureg_src reg ) 411{ 412 assert(reg.File != TGSI_FILE_NULL); 413 reg.Negate ^= 1; 414 return reg; 415} 416 417static INLINE struct ureg_src 418ureg_abs( struct ureg_src reg ) 419{ 420 assert(reg.File != TGSI_FILE_NULL); 421 reg.Absolute = 1; 422 reg.Negate = 0; 423 return reg; 424} 425 426static INLINE struct ureg_src 427ureg_swizzle( struct ureg_src reg, 428 int x, int y, int z, int w ) 429{ 430 unsigned swz = ( (reg.SwizzleX << 0) | 431 (reg.SwizzleY << 2) | 432 (reg.SwizzleZ << 4) | 433 (reg.SwizzleW << 6)); 434 435 assert(reg.File != TGSI_FILE_NULL); 436 assert(x < 4); 437 assert(y < 4); 438 assert(z < 4); 439 assert(w < 4); 440 441 reg.SwizzleX = (swz >> (x*2)) & 0x3; 442 reg.SwizzleY = (swz >> (y*2)) & 0x3; 443 reg.SwizzleZ = (swz >> (z*2)) & 0x3; 444 reg.SwizzleW = (swz >> (w*2)) & 0x3; 445 return reg; 446} 447 448static INLINE struct ureg_src 449ureg_scalar( struct ureg_src reg, int x ) 450{ 451 return ureg_swizzle(reg, x, x, x, x); 452} 453 454static INLINE struct ureg_dst 455ureg_writemask( struct ureg_dst reg, 456 unsigned writemask ) 457{ 458 assert(reg.File != TGSI_FILE_NULL); 459 reg.WriteMask &= writemask; 460 return reg; 461} 462 463static INLINE struct ureg_dst 464ureg_saturate( struct ureg_dst reg ) 465{ 466 assert(reg.File != TGSI_FILE_NULL); 467 reg.Saturate = 1; 468 return reg; 469} 470 471static INLINE struct ureg_dst 472ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr ) 473{ 474 assert(reg.File != TGSI_FILE_NULL); 475 assert(addr.File == TGSI_FILE_ADDRESS); 476 reg.Indirect = 1; 477 reg.IndirectIndex = addr.Index; 478 reg.IndirectSwizzle = addr.SwizzleX; 479 return reg; 480} 481 482static INLINE struct ureg_src 483ureg_src_indirect( struct ureg_src reg, struct ureg_src addr ) 484{ 485 assert(reg.File != TGSI_FILE_NULL); 486 assert(addr.File == TGSI_FILE_ADDRESS); 487 reg.Indirect = 1; 488 reg.IndirectIndex = addr.Index; 489 reg.IndirectSwizzle = addr.SwizzleX; 490 return reg; 491} 492 493static INLINE struct ureg_dst 494ureg_dst( struct ureg_src src ) 495{ 496 struct ureg_dst dst; 497 498 dst.File = src.File; 499 dst.WriteMask = TGSI_WRITEMASK_XYZW; 500 dst.Indirect = src.Indirect; 501 dst.IndirectIndex = src.IndirectIndex; 502 dst.IndirectSwizzle = src.IndirectSwizzle; 503 dst.Saturate = 0; 504 dst.Index = src.Index; 505 dst.Pad1 = 0; 506 dst.Pad2 = 0; 507 508 return dst; 509} 510 511static INLINE struct ureg_src 512ureg_src( struct ureg_dst dst ) 513{ 514 struct ureg_src src; 515 516 src.File = dst.File; 517 src.SwizzleX = TGSI_SWIZZLE_X; 518 src.SwizzleY = TGSI_SWIZZLE_Y; 519 src.SwizzleZ = TGSI_SWIZZLE_Z; 520 src.SwizzleW = TGSI_SWIZZLE_W; 521 src.Pad = 0; 522 src.Indirect = dst.Indirect; 523 src.IndirectIndex = dst.IndirectIndex; 524 src.IndirectSwizzle = dst.IndirectSwizzle; 525 src.Absolute = 0; 526 src.Index = dst.Index; 527 src.Negate = 0; 528 529 return src; 530} 531 532 533 534static INLINE struct ureg_dst 535ureg_dst_undef( void ) 536{ 537 struct ureg_dst dst; 538 539 dst.File = TGSI_FILE_NULL; 540 dst.WriteMask = 0; 541 dst.Indirect = 0; 542 dst.IndirectIndex = 0; 543 dst.IndirectSwizzle = 0; 544 dst.Saturate = 0; 545 dst.Index = 0; 546 dst.Pad1 = 0; 547 dst.Pad2 = 0; 548 549 return dst; 550} 551 552static INLINE struct ureg_src 553ureg_src_undef( void ) 554{ 555 struct ureg_src src; 556 557 src.File = TGSI_FILE_NULL; 558 src.SwizzleX = 0; 559 src.SwizzleY = 0; 560 src.SwizzleZ = 0; 561 src.SwizzleW = 0; 562 src.Pad = 0; 563 src.Indirect = 0; 564 src.IndirectIndex = 0; 565 src.IndirectSwizzle = 0; 566 src.Absolute = 0; 567 src.Index = 0; 568 src.Negate = 0; 569 570 return src; 571} 572 573static INLINE boolean 574ureg_src_is_undef( struct ureg_src src ) 575{ 576 return src.File == TGSI_FILE_NULL; 577} 578 579static INLINE boolean 580ureg_dst_is_undef( struct ureg_dst dst ) 581{ 582 return dst.File == TGSI_FILE_NULL; 583} 584 585 586#ifdef __cplusplus 587} 588#endif 589 590#endif 591