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_format.h" 32#include "pipe/p_compiler.h" 33#include "pipe/p_shader_tokens.h" 34#include "util/u_debug.h" 35 36#ifdef __cplusplus 37extern "C" { 38#endif 39 40struct pipe_screen; 41struct ureg_program; 42struct pipe_stream_output_info; 43 44/* Almost a tgsi_src_register, but we need to pull in the Absolute 45 * flag from the _ext token. Indirect flag always implies ADDR[0]. 46 */ 47struct ureg_src 48{ 49 unsigned File : 4; /* TGSI_FILE_ */ 50 unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */ 51 unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */ 52 unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */ 53 unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */ 54 unsigned Indirect : 1; /* BOOL */ 55 unsigned DimIndirect : 1; /* BOOL */ 56 unsigned Dimension : 1; /* BOOL */ 57 unsigned Absolute : 1; /* BOOL */ 58 unsigned Negate : 1; /* BOOL */ 59 unsigned IndirectFile : 4; /* TGSI_FILE_ */ 60 unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ 61 unsigned DimIndFile : 4; /* TGSI_FILE_ */ 62 unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */ 63 int Index : 16; /* SINT */ 64 int IndirectIndex : 16; /* SINT */ 65 int DimensionIndex : 16; /* SINT */ 66 int DimIndIndex : 16; /* SINT */ 67 unsigned ArrayID : 10; /* UINT */ 68}; 69 70/* Very similar to a tgsi_dst_register, removing unsupported fields 71 * and adding a Saturate flag. It's easier to push saturate into the 72 * destination register than to try and create a _SAT variant of each 73 * instruction function. 74 */ 75struct ureg_dst 76{ 77 unsigned File : 4; /* TGSI_FILE_ */ 78 unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */ 79 unsigned Indirect : 1; /* BOOL */ 80 unsigned DimIndirect : 1; /* BOOL */ 81 unsigned Dimension : 1; /* BOOL */ 82 unsigned Saturate : 1; /* BOOL */ 83 unsigned Invariant : 1; /* BOOL */ 84 int Index : 16; /* SINT */ 85 int IndirectIndex : 16; /* SINT */ 86 unsigned IndirectFile : 4; /* TGSI_FILE_ */ 87 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ 88 unsigned DimIndFile : 4; /* TGSI_FILE_ */ 89 unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */ 90 int DimensionIndex : 16; /* SINT */ 91 int DimIndIndex : 16; /* SINT */ 92 unsigned ArrayID : 10; /* UINT */ 93}; 94 95struct pipe_context; 96 97struct ureg_program * 98ureg_create(enum pipe_shader_type processor); 99 100struct ureg_program * 101ureg_create_with_screen(enum pipe_shader_type processor, 102 struct pipe_screen *screen); 103 104const struct tgsi_token * 105ureg_finalize( struct ureg_program * ); 106 107/* Create and return a shader: 108 */ 109void * 110ureg_create_shader( struct ureg_program *, 111 struct pipe_context *pipe, 112 const struct pipe_stream_output_info *so ); 113 114void 115ureg_set_next_shader_processor(struct ureg_program *ureg, unsigned processor); 116 117/* Alternately, return the built token stream and hand ownership of 118 * that memory to the caller: 119 */ 120const struct tgsi_token * 121ureg_get_tokens( struct ureg_program *ureg, 122 unsigned *nr_tokens ); 123 124/* 125 * Returns the number of currently declared outputs. 126 */ 127unsigned 128ureg_get_nr_outputs( const struct ureg_program *ureg ); 129 130 131/* Free the tokens created by ureg_get_tokens() */ 132void ureg_free_tokens( const struct tgsi_token *tokens ); 133 134 135void 136ureg_destroy( struct ureg_program * ); 137 138 139/*********************************************************************** 140 * Convenience routine: 141 */ 142static inline void * 143ureg_create_shader_with_so_and_destroy( struct ureg_program *p, 144 struct pipe_context *pipe, 145 const struct pipe_stream_output_info *so ) 146{ 147 void *result = ureg_create_shader( p, pipe, so ); 148 ureg_destroy( p ); 149 return result; 150} 151 152static inline void * 153ureg_create_shader_and_destroy( struct ureg_program *p, 154 struct pipe_context *pipe ) 155{ 156 return ureg_create_shader_with_so_and_destroy(p, pipe, NULL); 157} 158 159 160/*********************************************************************** 161 * Build shader properties: 162 */ 163 164void 165ureg_property(struct ureg_program *ureg, unsigned name, unsigned value); 166 167 168/*********************************************************************** 169 * Build shader declarations: 170 */ 171 172struct ureg_src 173ureg_DECL_fs_input_cyl_centroid_layout(struct ureg_program *, 174 enum tgsi_semantic semantic_name, 175 unsigned semantic_index, 176 enum tgsi_interpolate_mode interp_mode, 177 unsigned cylindrical_wrap, 178 enum tgsi_interpolate_loc interp_location, 179 unsigned index, 180 unsigned usage_mask, 181 unsigned array_id, 182 unsigned array_size); 183 184struct ureg_src 185ureg_DECL_fs_input_cyl_centroid(struct ureg_program *, 186 enum tgsi_semantic semantic_name, 187 unsigned semantic_index, 188 enum tgsi_interpolate_mode interp_mode, 189 unsigned cylindrical_wrap, 190 enum tgsi_interpolate_loc interp_location, 191 unsigned array_id, 192 unsigned array_size); 193 194static inline struct ureg_src 195ureg_DECL_fs_input_cyl(struct ureg_program *ureg, 196 enum tgsi_semantic semantic_name, 197 unsigned semantic_index, 198 enum tgsi_interpolate_mode interp_mode, 199 unsigned cylindrical_wrap) 200{ 201 return ureg_DECL_fs_input_cyl_centroid(ureg, 202 semantic_name, 203 semantic_index, 204 interp_mode, 205 cylindrical_wrap, 206 TGSI_INTERPOLATE_LOC_CENTER, 0, 1); 207} 208 209static inline struct ureg_src 210ureg_DECL_fs_input(struct ureg_program *ureg, 211 enum tgsi_semantic semantic_name, 212 unsigned semantic_index, 213 enum tgsi_interpolate_mode interp_mode) 214{ 215 return ureg_DECL_fs_input_cyl_centroid(ureg, 216 semantic_name, 217 semantic_index, 218 interp_mode, 219 0, TGSI_INTERPOLATE_LOC_CENTER, 0, 1); 220} 221 222struct ureg_src 223ureg_DECL_vs_input( struct ureg_program *, 224 unsigned index ); 225 226struct ureg_src 227ureg_DECL_input_layout(struct ureg_program *, 228 enum tgsi_semantic semantic_name, 229 unsigned semantic_index, 230 unsigned index, 231 unsigned usage_mask, 232 unsigned array_id, 233 unsigned array_size); 234 235struct ureg_src 236ureg_DECL_input(struct ureg_program *, 237 enum tgsi_semantic semantic_name, 238 unsigned semantic_index, 239 unsigned array_id, 240 unsigned array_size); 241 242struct ureg_src 243ureg_DECL_system_value(struct ureg_program *, 244 enum tgsi_semantic semantic_name, 245 unsigned semantic_index); 246 247struct ureg_dst 248ureg_DECL_output_layout(struct ureg_program *, 249 enum tgsi_semantic semantic_name, 250 unsigned semantic_index, 251 unsigned streams, 252 unsigned index, 253 unsigned usage_mask, 254 unsigned array_id, 255 unsigned array_size, 256 boolean invariant); 257 258struct ureg_dst 259ureg_DECL_output_masked(struct ureg_program *, 260 enum tgsi_semantic semantic_name, 261 unsigned semantic_index, 262 unsigned usage_mask, 263 unsigned array_id, 264 unsigned array_size); 265 266struct ureg_dst 267ureg_DECL_output(struct ureg_program *, 268 enum tgsi_semantic semantic_name, 269 unsigned semantic_index); 270 271struct ureg_dst 272ureg_DECL_output_array(struct ureg_program *ureg, 273 enum tgsi_semantic semantic_name, 274 unsigned semantic_index, 275 unsigned array_id, 276 unsigned array_size); 277 278struct ureg_src 279ureg_DECL_immediate( struct ureg_program *, 280 const float *v, 281 unsigned nr ); 282 283struct ureg_src 284ureg_DECL_immediate_f64( struct ureg_program *, 285 const double *v, 286 unsigned nr ); 287 288struct ureg_src 289ureg_DECL_immediate_uint( struct ureg_program *, 290 const unsigned *v, 291 unsigned nr ); 292 293struct ureg_src 294ureg_DECL_immediate_block_uint( struct ureg_program *, 295 const unsigned *v, 296 unsigned nr ); 297 298struct ureg_src 299ureg_DECL_immediate_int( struct ureg_program *, 300 const int *v, 301 unsigned nr ); 302 303struct ureg_src 304ureg_DECL_immediate_uint64( struct ureg_program *, 305 const uint64_t *v, 306 unsigned nr ); 307 308struct ureg_src 309ureg_DECL_immediate_int64( struct ureg_program *, 310 const int64_t *v, 311 unsigned nr ); 312 313void 314ureg_DECL_constant2D(struct ureg_program *ureg, 315 unsigned first, 316 unsigned last, 317 unsigned index2D); 318 319struct ureg_src 320ureg_DECL_constant( struct ureg_program *, 321 unsigned index ); 322 323void 324ureg_DECL_hw_atomic(struct ureg_program *ureg, 325 unsigned first, 326 unsigned last, 327 unsigned buffer_id, 328 unsigned array_id); 329 330struct ureg_dst 331ureg_DECL_temporary( struct ureg_program * ); 332 333/** 334 * Emit a temporary with the LOCAL declaration flag set. For use when 335 * the register value is not required to be preserved across 336 * subroutine boundaries. 337 */ 338struct ureg_dst 339ureg_DECL_local_temporary( struct ureg_program * ); 340 341/** 342 * Declare "size" continuous temporary registers. 343 */ 344struct ureg_dst 345ureg_DECL_array_temporary( struct ureg_program *, 346 unsigned size, 347 boolean local ); 348 349void 350ureg_release_temporary( struct ureg_program *ureg, 351 struct ureg_dst tmp ); 352 353struct ureg_dst 354ureg_DECL_address( struct ureg_program * ); 355 356/* Supply an index to the sampler declaration as this is the hook to 357 * the external pipe_sampler state. Users of this function probably 358 * don't want just any sampler, but a specific one which they've set 359 * up state for in the context. 360 */ 361struct ureg_src 362ureg_DECL_sampler( struct ureg_program *, 363 unsigned index ); 364 365struct ureg_src 366ureg_DECL_sampler_view(struct ureg_program *, 367 unsigned index, 368 enum tgsi_texture_type target, 369 enum tgsi_return_type return_type_x, 370 enum tgsi_return_type return_type_y, 371 enum tgsi_return_type return_type_z, 372 enum tgsi_return_type return_type_w ); 373 374struct ureg_src 375ureg_DECL_image(struct ureg_program *ureg, 376 unsigned index, 377 enum tgsi_texture_type target, 378 enum pipe_format format, 379 boolean wr, 380 boolean raw); 381 382struct ureg_src 383ureg_DECL_buffer(struct ureg_program *ureg, unsigned nr, bool atomic); 384 385struct ureg_src 386ureg_DECL_memory(struct ureg_program *ureg, unsigned memory_type); 387 388static inline struct ureg_src 389ureg_imm4f( struct ureg_program *ureg, 390 float a, float b, 391 float c, float d) 392{ 393 float v[4]; 394 v[0] = a; 395 v[1] = b; 396 v[2] = c; 397 v[3] = d; 398 return ureg_DECL_immediate( ureg, v, 4 ); 399} 400 401static inline struct ureg_src 402ureg_imm3f( struct ureg_program *ureg, 403 float a, float b, 404 float c) 405{ 406 float v[3]; 407 v[0] = a; 408 v[1] = b; 409 v[2] = c; 410 return ureg_DECL_immediate( ureg, v, 3 ); 411} 412 413static inline struct ureg_src 414ureg_imm2f( struct ureg_program *ureg, 415 float a, float b) 416{ 417 float v[2]; 418 v[0] = a; 419 v[1] = b; 420 return ureg_DECL_immediate( ureg, v, 2 ); 421} 422 423static inline struct ureg_src 424ureg_imm1f( struct ureg_program *ureg, 425 float a) 426{ 427 float v[1]; 428 v[0] = a; 429 return ureg_DECL_immediate( ureg, v, 1 ); 430} 431 432static inline struct ureg_src 433ureg_imm4u( struct ureg_program *ureg, 434 unsigned a, unsigned b, 435 unsigned c, unsigned d) 436{ 437 unsigned v[4]; 438 v[0] = a; 439 v[1] = b; 440 v[2] = c; 441 v[3] = d; 442 return ureg_DECL_immediate_uint( ureg, v, 4 ); 443} 444 445static inline struct ureg_src 446ureg_imm3u( struct ureg_program *ureg, 447 unsigned a, unsigned b, 448 unsigned c) 449{ 450 unsigned v[3]; 451 v[0] = a; 452 v[1] = b; 453 v[2] = c; 454 return ureg_DECL_immediate_uint( ureg, v, 3 ); 455} 456 457static inline struct ureg_src 458ureg_imm2u( struct ureg_program *ureg, 459 unsigned a, unsigned b) 460{ 461 unsigned v[2]; 462 v[0] = a; 463 v[1] = b; 464 return ureg_DECL_immediate_uint( ureg, v, 2 ); 465} 466 467static inline struct ureg_src 468ureg_imm1u( struct ureg_program *ureg, 469 unsigned a) 470{ 471 return ureg_DECL_immediate_uint( ureg, &a, 1 ); 472} 473 474static inline struct ureg_src 475ureg_imm4i( struct ureg_program *ureg, 476 int a, int b, 477 int c, int d) 478{ 479 int v[4]; 480 v[0] = a; 481 v[1] = b; 482 v[2] = c; 483 v[3] = d; 484 return ureg_DECL_immediate_int( ureg, v, 4 ); 485} 486 487static inline struct ureg_src 488ureg_imm3i( struct ureg_program *ureg, 489 int a, int b, 490 int c) 491{ 492 int v[3]; 493 v[0] = a; 494 v[1] = b; 495 v[2] = c; 496 return ureg_DECL_immediate_int( ureg, v, 3 ); 497} 498 499static inline struct ureg_src 500ureg_imm2i( struct ureg_program *ureg, 501 int a, int b) 502{ 503 int v[2]; 504 v[0] = a; 505 v[1] = b; 506 return ureg_DECL_immediate_int( ureg, v, 2 ); 507} 508 509static inline struct ureg_src 510ureg_imm1i( struct ureg_program *ureg, 511 int a) 512{ 513 return ureg_DECL_immediate_int( ureg, &a, 1 ); 514} 515 516/* Where the destination register has a valid file, but an empty 517 * writemask. 518 */ 519static inline boolean 520ureg_dst_is_empty( struct ureg_dst dst ) 521{ 522 return dst.File != TGSI_FILE_NULL && 523 dst.WriteMask == 0; 524} 525 526/*********************************************************************** 527 * Functions for patching up labels 528 */ 529 530 531/* Will return a number which can be used in a label to point to the 532 * next instruction to be emitted. 533 */ 534unsigned 535ureg_get_instruction_number( struct ureg_program *ureg ); 536 537 538/* Patch a given label (expressed as a token number) to point to a 539 * given instruction (expressed as an instruction number). 540 * 541 * Labels are obtained from instruction emitters, eg ureg_CAL(). 542 * Instruction numbers are obtained from ureg_get_instruction_number(), 543 * above. 544 */ 545void 546ureg_fixup_label(struct ureg_program *ureg, 547 unsigned label_token, 548 unsigned instruction_number ); 549 550 551/* Generic instruction emitter. Use if you need to pass the opcode as 552 * a parameter, rather than using the emit_OP() variants below. 553 */ 554void 555ureg_insn(struct ureg_program *ureg, 556 enum tgsi_opcode opcode, 557 const struct ureg_dst *dst, 558 unsigned nr_dst, 559 const struct ureg_src *src, 560 unsigned nr_src, 561 unsigned precise ); 562 563 564void 565ureg_tex_insn(struct ureg_program *ureg, 566 enum tgsi_opcode opcode, 567 const struct ureg_dst *dst, 568 unsigned nr_dst, 569 enum tgsi_texture_type target, 570 enum tgsi_return_type return_type, 571 const struct tgsi_texture_offset *texoffsets, 572 unsigned nr_offset, 573 const struct ureg_src *src, 574 unsigned nr_src ); 575 576 577void 578ureg_memory_insn(struct ureg_program *ureg, 579 enum tgsi_opcode opcode, 580 const struct ureg_dst *dst, 581 unsigned nr_dst, 582 const struct ureg_src *src, 583 unsigned nr_src, 584 unsigned qualifier, 585 enum tgsi_texture_type texture, 586 enum pipe_format format); 587 588/*********************************************************************** 589 * Internal instruction helpers, don't call these directly: 590 */ 591 592struct ureg_emit_insn_result { 593 unsigned insn_token; /*< Used to fixup insn size. */ 594 unsigned extended_token; /*< Used to set the Extended bit, usually the same as insn_token. */ 595}; 596 597struct ureg_emit_insn_result 598ureg_emit_insn(struct ureg_program *ureg, 599 enum tgsi_opcode opcode, 600 boolean saturate, 601 unsigned precise, 602 unsigned num_dst, 603 unsigned num_src); 604 605void 606ureg_emit_label(struct ureg_program *ureg, 607 unsigned insn_token, 608 unsigned *label_token ); 609 610void 611ureg_emit_texture(struct ureg_program *ureg, 612 unsigned insn_token, 613 enum tgsi_texture_type target, 614 enum tgsi_return_type return_type, 615 unsigned num_offsets); 616 617void 618ureg_emit_texture_offset(struct ureg_program *ureg, 619 const struct tgsi_texture_offset *offset); 620 621void 622ureg_emit_memory(struct ureg_program *ureg, 623 unsigned insn_token, 624 unsigned qualifier, 625 enum tgsi_texture_type texture, 626 enum pipe_format format); 627 628void 629ureg_emit_dst( struct ureg_program *ureg, 630 struct ureg_dst dst ); 631 632void 633ureg_emit_src( struct ureg_program *ureg, 634 struct ureg_src src ); 635 636void 637ureg_fixup_insn_size(struct ureg_program *ureg, 638 unsigned insn ); 639 640 641#define OP00( op ) \ 642static inline void ureg_##op( struct ureg_program *ureg ) \ 643{ \ 644 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 645 struct ureg_emit_insn_result insn; \ 646 insn = ureg_emit_insn(ureg, \ 647 opcode, \ 648 FALSE, \ 649 0, \ 650 0, \ 651 0); \ 652 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 653} 654 655#define OP01( op ) \ 656static inline void ureg_##op( struct ureg_program *ureg, \ 657 struct ureg_src src ) \ 658{ \ 659 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 660 struct ureg_emit_insn_result insn; \ 661 insn = ureg_emit_insn(ureg, \ 662 opcode, \ 663 FALSE, \ 664 0, \ 665 0, \ 666 1); \ 667 ureg_emit_src( ureg, src ); \ 668 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 669} 670 671#define OP00_LBL( op ) \ 672static inline void ureg_##op( struct ureg_program *ureg, \ 673 unsigned *label_token ) \ 674{ \ 675 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 676 struct ureg_emit_insn_result insn; \ 677 insn = ureg_emit_insn(ureg, \ 678 opcode, \ 679 FALSE, \ 680 0, \ 681 0, \ 682 0); \ 683 ureg_emit_label( ureg, insn.extended_token, label_token ); \ 684 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 685} 686 687#define OP01_LBL( op ) \ 688static inline void ureg_##op( struct ureg_program *ureg, \ 689 struct ureg_src src, \ 690 unsigned *label_token ) \ 691{ \ 692 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 693 struct ureg_emit_insn_result insn; \ 694 insn = ureg_emit_insn(ureg, \ 695 opcode, \ 696 FALSE, \ 697 0, \ 698 0, \ 699 1); \ 700 ureg_emit_label( ureg, insn.extended_token, label_token ); \ 701 ureg_emit_src( ureg, src ); \ 702 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 703} 704 705#define OP10( op ) \ 706static inline void ureg_##op( struct ureg_program *ureg, \ 707 struct ureg_dst dst ) \ 708{ \ 709 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 710 struct ureg_emit_insn_result insn; \ 711 if (ureg_dst_is_empty(dst)) \ 712 return; \ 713 insn = ureg_emit_insn(ureg, \ 714 opcode, \ 715 dst.Saturate, \ 716 0, \ 717 1, \ 718 0); \ 719 ureg_emit_dst( ureg, dst ); \ 720 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 721} 722 723 724#define OP11( op ) \ 725static inline void ureg_##op( struct ureg_program *ureg, \ 726 struct ureg_dst dst, \ 727 struct ureg_src src ) \ 728{ \ 729 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 730 struct ureg_emit_insn_result insn; \ 731 if (ureg_dst_is_empty(dst)) \ 732 return; \ 733 insn = ureg_emit_insn(ureg, \ 734 opcode, \ 735 dst.Saturate, \ 736 0, \ 737 1, \ 738 1); \ 739 ureg_emit_dst( ureg, dst ); \ 740 ureg_emit_src( ureg, src ); \ 741 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 742} 743 744#define OP12( op ) \ 745static inline void ureg_##op( struct ureg_program *ureg, \ 746 struct ureg_dst dst, \ 747 struct ureg_src src0, \ 748 struct ureg_src src1 ) \ 749{ \ 750 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 751 struct ureg_emit_insn_result insn; \ 752 if (ureg_dst_is_empty(dst)) \ 753 return; \ 754 insn = ureg_emit_insn(ureg, \ 755 opcode, \ 756 dst.Saturate, \ 757 0, \ 758 1, \ 759 2); \ 760 ureg_emit_dst( ureg, dst ); \ 761 ureg_emit_src( ureg, src0 ); \ 762 ureg_emit_src( ureg, src1 ); \ 763 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 764} 765 766#define OP12_TEX( op ) \ 767static inline void ureg_##op( struct ureg_program *ureg, \ 768 struct ureg_dst dst, \ 769 enum tgsi_texture_type target, \ 770 struct ureg_src src0, \ 771 struct ureg_src src1 ) \ 772{ \ 773 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 774 enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN; \ 775 struct ureg_emit_insn_result insn; \ 776 if (ureg_dst_is_empty(dst)) \ 777 return; \ 778 insn = ureg_emit_insn(ureg, \ 779 opcode, \ 780 dst.Saturate, \ 781 0, \ 782 1, \ 783 2); \ 784 ureg_emit_texture( ureg, insn.extended_token, target, \ 785 return_type, 0 ); \ 786 ureg_emit_dst( ureg, dst ); \ 787 ureg_emit_src( ureg, src0 ); \ 788 ureg_emit_src( ureg, src1 ); \ 789 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 790} 791 792#define OP13( op ) \ 793static inline void ureg_##op( struct ureg_program *ureg, \ 794 struct ureg_dst dst, \ 795 struct ureg_src src0, \ 796 struct ureg_src src1, \ 797 struct ureg_src src2 ) \ 798{ \ 799 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 800 struct ureg_emit_insn_result insn; \ 801 if (ureg_dst_is_empty(dst)) \ 802 return; \ 803 insn = ureg_emit_insn(ureg, \ 804 opcode, \ 805 dst.Saturate, \ 806 0, \ 807 1, \ 808 3); \ 809 ureg_emit_dst( ureg, dst ); \ 810 ureg_emit_src( ureg, src0 ); \ 811 ureg_emit_src( ureg, src1 ); \ 812 ureg_emit_src( ureg, src2 ); \ 813 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 814} 815 816#define OP14_TEX( op ) \ 817static inline void ureg_##op( struct ureg_program *ureg, \ 818 struct ureg_dst dst, \ 819 enum tgsi_texture_type target, \ 820 struct ureg_src src0, \ 821 struct ureg_src src1, \ 822 struct ureg_src src2, \ 823 struct ureg_src src3 ) \ 824{ \ 825 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ 826 enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN; \ 827 struct ureg_emit_insn_result insn; \ 828 if (ureg_dst_is_empty(dst)) \ 829 return; \ 830 insn = ureg_emit_insn(ureg, \ 831 opcode, \ 832 dst.Saturate, \ 833 0, \ 834 1, \ 835 4); \ 836 ureg_emit_texture( ureg, insn.extended_token, target, \ 837 return_type, 0 ); \ 838 ureg_emit_dst( ureg, dst ); \ 839 ureg_emit_src( ureg, src0 ); \ 840 ureg_emit_src( ureg, src1 ); \ 841 ureg_emit_src( ureg, src2 ); \ 842 ureg_emit_src( ureg, src3 ); \ 843 ureg_fixup_insn_size( ureg, insn.insn_token ); \ 844} 845 846/* Use a template include to generate a correctly-typed ureg_OP() 847 * function for each TGSI opcode: 848 */ 849#include "tgsi_opcode_tmp.h" 850 851 852/*********************************************************************** 853 * Inline helpers for manipulating register structs: 854 */ 855static inline struct ureg_src 856ureg_negate( struct ureg_src reg ) 857{ 858 assert(reg.File != TGSI_FILE_NULL); 859 reg.Negate ^= 1; 860 return reg; 861} 862 863static inline struct ureg_src 864ureg_abs( struct ureg_src reg ) 865{ 866 assert(reg.File != TGSI_FILE_NULL); 867 reg.Absolute = 1; 868 reg.Negate = 0; 869 return reg; 870} 871 872static inline struct ureg_src 873ureg_swizzle( struct ureg_src reg, 874 int x, int y, int z, int w ) 875{ 876 unsigned swz = ( (reg.SwizzleX << 0) | 877 (reg.SwizzleY << 2) | 878 (reg.SwizzleZ << 4) | 879 (reg.SwizzleW << 6)); 880 881 assert(reg.File != TGSI_FILE_NULL); 882 assert(x < 4); 883 assert(y < 4); 884 assert(z < 4); 885 assert(w < 4); 886 887 reg.SwizzleX = (swz >> (x*2)) & 0x3; 888 reg.SwizzleY = (swz >> (y*2)) & 0x3; 889 reg.SwizzleZ = (swz >> (z*2)) & 0x3; 890 reg.SwizzleW = (swz >> (w*2)) & 0x3; 891 return reg; 892} 893 894static inline struct ureg_src 895ureg_scalar( struct ureg_src reg, int x ) 896{ 897 return ureg_swizzle(reg, x, x, x, x); 898} 899 900static inline struct ureg_dst 901ureg_writemask( struct ureg_dst reg, 902 unsigned writemask ) 903{ 904 assert(reg.File != TGSI_FILE_NULL); 905 reg.WriteMask &= writemask; 906 return reg; 907} 908 909static inline struct ureg_dst 910ureg_saturate( struct ureg_dst reg ) 911{ 912 assert(reg.File != TGSI_FILE_NULL); 913 reg.Saturate = 1; 914 return reg; 915} 916 917static inline struct ureg_dst 918ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr ) 919{ 920 assert(reg.File != TGSI_FILE_NULL); 921 reg.Indirect = 1; 922 reg.IndirectFile = addr.File; 923 reg.IndirectIndex = addr.Index; 924 reg.IndirectSwizzle = addr.SwizzleX; 925 return reg; 926} 927 928static inline struct ureg_src 929ureg_src_indirect( struct ureg_src reg, struct ureg_src addr ) 930{ 931 assert(reg.File != TGSI_FILE_NULL); 932 reg.Indirect = 1; 933 reg.IndirectFile = addr.File; 934 reg.IndirectIndex = addr.Index; 935 reg.IndirectSwizzle = addr.SwizzleX; 936 return reg; 937} 938 939static inline struct ureg_dst 940ureg_dst_dimension( struct ureg_dst reg, int index ) 941{ 942 assert(reg.File != TGSI_FILE_NULL); 943 reg.Dimension = 1; 944 reg.DimIndirect = 0; 945 reg.DimensionIndex = index; 946 return reg; 947} 948 949static inline struct ureg_src 950ureg_src_dimension( struct ureg_src reg, int index ) 951{ 952 assert(reg.File != TGSI_FILE_NULL); 953 reg.Dimension = 1; 954 reg.DimIndirect = 0; 955 reg.DimensionIndex = index; 956 return reg; 957} 958 959static inline struct ureg_dst 960ureg_dst_dimension_indirect( struct ureg_dst reg, struct ureg_src addr, 961 int index ) 962{ 963 assert(reg.File != TGSI_FILE_NULL); 964 reg.Dimension = 1; 965 reg.DimIndirect = 1; 966 reg.DimensionIndex = index; 967 reg.DimIndFile = addr.File; 968 reg.DimIndIndex = addr.Index; 969 reg.DimIndSwizzle = addr.SwizzleX; 970 return reg; 971} 972 973static inline struct ureg_src 974ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr, 975 int index ) 976{ 977 assert(reg.File != TGSI_FILE_NULL); 978 reg.Dimension = 1; 979 reg.DimIndirect = 1; 980 reg.DimensionIndex = index; 981 reg.DimIndFile = addr.File; 982 reg.DimIndIndex = addr.Index; 983 reg.DimIndSwizzle = addr.SwizzleX; 984 return reg; 985} 986 987static inline struct ureg_src 988ureg_src_array_offset(struct ureg_src reg, int offset) 989{ 990 reg.Index += offset; 991 return reg; 992} 993 994static inline struct ureg_dst 995ureg_dst_array_offset( struct ureg_dst reg, int offset ) 996{ 997 reg.Index += offset; 998 return reg; 999} 1000 1001static inline struct ureg_dst 1002ureg_dst_array_register(unsigned file, 1003 unsigned index, 1004 unsigned array_id) 1005{ 1006 struct ureg_dst dst; 1007 1008 dst.File = file; 1009 dst.WriteMask = TGSI_WRITEMASK_XYZW; 1010 dst.Indirect = 0; 1011 dst.IndirectFile = TGSI_FILE_NULL; 1012 dst.IndirectIndex = 0; 1013 dst.IndirectSwizzle = 0; 1014 dst.Saturate = 0; 1015 dst.Index = index; 1016 dst.Dimension = 0; 1017 dst.DimensionIndex = 0; 1018 dst.DimIndirect = 0; 1019 dst.DimIndFile = TGSI_FILE_NULL; 1020 dst.DimIndIndex = 0; 1021 dst.DimIndSwizzle = 0; 1022 dst.ArrayID = array_id; 1023 dst.Invariant = 0; 1024 1025 return dst; 1026} 1027 1028static inline struct ureg_dst 1029ureg_dst_register(unsigned file, 1030 unsigned index) 1031{ 1032 return ureg_dst_array_register(file, index, 0); 1033} 1034 1035static inline struct ureg_dst 1036ureg_dst( struct ureg_src src ) 1037{ 1038 struct ureg_dst dst; 1039 1040 dst.File = src.File; 1041 dst.WriteMask = TGSI_WRITEMASK_XYZW; 1042 dst.IndirectFile = src.IndirectFile; 1043 dst.Indirect = src.Indirect; 1044 dst.IndirectIndex = src.IndirectIndex; 1045 dst.IndirectSwizzle = src.IndirectSwizzle; 1046 dst.Saturate = 0; 1047 dst.Index = src.Index; 1048 dst.Dimension = src.Dimension; 1049 dst.DimensionIndex = src.DimensionIndex; 1050 dst.DimIndirect = src.DimIndirect; 1051 dst.DimIndFile = src.DimIndFile; 1052 dst.DimIndIndex = src.DimIndIndex; 1053 dst.DimIndSwizzle = src.DimIndSwizzle; 1054 dst.ArrayID = src.ArrayID; 1055 dst.Invariant = 0; 1056 1057 return dst; 1058} 1059 1060static inline struct ureg_src 1061ureg_src_array_register(unsigned file, 1062 unsigned index, 1063 unsigned array_id) 1064{ 1065 struct ureg_src src; 1066 1067 src.File = file; 1068 src.SwizzleX = TGSI_SWIZZLE_X; 1069 src.SwizzleY = TGSI_SWIZZLE_Y; 1070 src.SwizzleZ = TGSI_SWIZZLE_Z; 1071 src.SwizzleW = TGSI_SWIZZLE_W; 1072 src.Indirect = 0; 1073 src.IndirectFile = TGSI_FILE_NULL; 1074 src.IndirectIndex = 0; 1075 src.IndirectSwizzle = 0; 1076 src.Absolute = 0; 1077 src.Index = index; 1078 src.Negate = 0; 1079 src.Dimension = 0; 1080 src.DimensionIndex = 0; 1081 src.DimIndirect = 0; 1082 src.DimIndFile = TGSI_FILE_NULL; 1083 src.DimIndIndex = 0; 1084 src.DimIndSwizzle = 0; 1085 src.ArrayID = array_id; 1086 1087 return src; 1088} 1089 1090static inline struct ureg_src 1091ureg_src_register(unsigned file, 1092 unsigned index) 1093{ 1094 return ureg_src_array_register(file, index, 0); 1095} 1096 1097static inline struct ureg_src 1098ureg_src( struct ureg_dst dst ) 1099{ 1100 struct ureg_src src; 1101 1102 src.File = dst.File; 1103 src.SwizzleX = TGSI_SWIZZLE_X; 1104 src.SwizzleY = TGSI_SWIZZLE_Y; 1105 src.SwizzleZ = TGSI_SWIZZLE_Z; 1106 src.SwizzleW = TGSI_SWIZZLE_W; 1107 src.Indirect = dst.Indirect; 1108 src.IndirectFile = dst.IndirectFile; 1109 src.IndirectIndex = dst.IndirectIndex; 1110 src.IndirectSwizzle = dst.IndirectSwizzle; 1111 src.Absolute = 0; 1112 src.Index = dst.Index; 1113 src.Negate = 0; 1114 src.Dimension = dst.Dimension; 1115 src.DimensionIndex = dst.DimensionIndex; 1116 src.DimIndirect = dst.DimIndirect; 1117 src.DimIndFile = dst.DimIndFile; 1118 src.DimIndIndex = dst.DimIndIndex; 1119 src.DimIndSwizzle = dst.DimIndSwizzle; 1120 src.ArrayID = dst.ArrayID; 1121 1122 return src; 1123} 1124 1125 1126 1127static inline struct ureg_dst 1128ureg_dst_undef( void ) 1129{ 1130 struct ureg_dst dst; 1131 1132 dst.File = TGSI_FILE_NULL; 1133 dst.WriteMask = 0; 1134 dst.Indirect = 0; 1135 dst.IndirectFile = TGSI_FILE_NULL; 1136 dst.IndirectIndex = 0; 1137 dst.IndirectSwizzle = 0; 1138 dst.Saturate = 0; 1139 dst.Index = 0; 1140 dst.Dimension = 0; 1141 dst.DimensionIndex = 0; 1142 dst.DimIndirect = 0; 1143 dst.DimIndFile = TGSI_FILE_NULL; 1144 dst.DimIndIndex = 0; 1145 dst.DimIndSwizzle = 0; 1146 dst.ArrayID = 0; 1147 dst.Invariant = 0; 1148 1149 return dst; 1150} 1151 1152static inline struct ureg_src 1153ureg_src_undef( void ) 1154{ 1155 struct ureg_src src; 1156 1157 src.File = TGSI_FILE_NULL; 1158 src.SwizzleX = 0; 1159 src.SwizzleY = 0; 1160 src.SwizzleZ = 0; 1161 src.SwizzleW = 0; 1162 src.Indirect = 0; 1163 src.IndirectFile = TGSI_FILE_NULL; 1164 src.IndirectIndex = 0; 1165 src.IndirectSwizzle = 0; 1166 src.Absolute = 0; 1167 src.Index = 0; 1168 src.Negate = 0; 1169 src.Dimension = 0; 1170 src.DimensionIndex = 0; 1171 src.DimIndirect = 0; 1172 src.DimIndFile = TGSI_FILE_NULL; 1173 src.DimIndIndex = 0; 1174 src.DimIndSwizzle = 0; 1175 src.ArrayID = 0; 1176 1177 return src; 1178} 1179 1180static inline boolean 1181ureg_src_is_undef( struct ureg_src src ) 1182{ 1183 return src.File == TGSI_FILE_NULL; 1184} 1185 1186static inline boolean 1187ureg_dst_is_undef( struct ureg_dst dst ) 1188{ 1189 return dst.File == TGSI_FILE_NULL; 1190} 1191 1192 1193#ifdef __cplusplus 1194} 1195#endif 1196 1197#endif 1198