1/************************************************************************** 2 * 3 * Copyright 2009-2010 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 29#include "pipe/p_context.h" 30#include "pipe/p_state.h" 31#include "tgsi/tgsi_ureg.h" 32#include "tgsi/tgsi_build.h" 33#include "tgsi/tgsi_info.h" 34#include "tgsi/tgsi_dump.h" 35#include "tgsi/tgsi_sanity.h" 36#include "util/u_debug.h" 37#include "util/u_memory.h" 38#include "util/u_math.h" 39#include "util/u_bitmask.h" 40 41union tgsi_any_token { 42 struct tgsi_header header; 43 struct tgsi_processor processor; 44 struct tgsi_token token; 45 struct tgsi_property prop; 46 struct tgsi_property_data prop_data; 47 struct tgsi_declaration decl; 48 struct tgsi_declaration_range decl_range; 49 struct tgsi_declaration_dimension decl_dim; 50 struct tgsi_declaration_interp decl_interp; 51 struct tgsi_declaration_semantic decl_semantic; 52 struct tgsi_declaration_sampler_view decl_sampler_view; 53 struct tgsi_immediate imm; 54 union tgsi_immediate_data imm_data; 55 struct tgsi_instruction insn; 56 struct tgsi_instruction_predicate insn_predicate; 57 struct tgsi_instruction_label insn_label; 58 struct tgsi_instruction_texture insn_texture; 59 struct tgsi_texture_offset insn_texture_offset; 60 struct tgsi_src_register src; 61 struct tgsi_dimension dim; 62 struct tgsi_dst_register dst; 63 unsigned value; 64}; 65 66 67struct ureg_tokens { 68 union tgsi_any_token *tokens; 69 unsigned size; 70 unsigned order; 71 unsigned count; 72}; 73 74#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS 75#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS 76#define UREG_MAX_OUTPUT PIPE_MAX_SHADER_OUTPUTS 77#define UREG_MAX_CONSTANT_RANGE 32 78#define UREG_MAX_IMMEDIATE 256 79#define UREG_MAX_ADDR 2 80#define UREG_MAX_PRED 1 81 82struct const_decl { 83 struct { 84 unsigned first; 85 unsigned last; 86 } constant_range[UREG_MAX_CONSTANT_RANGE]; 87 unsigned nr_constant_ranges; 88}; 89 90#define DOMAIN_DECL 0 91#define DOMAIN_INSN 1 92 93struct ureg_program 94{ 95 unsigned processor; 96 struct pipe_context *pipe; 97 98 struct { 99 unsigned semantic_name; 100 unsigned semantic_index; 101 unsigned interp; 102 unsigned char cylindrical_wrap; 103 unsigned char centroid; 104 } fs_input[UREG_MAX_INPUT]; 105 unsigned nr_fs_inputs; 106 107 unsigned vs_inputs[UREG_MAX_INPUT/32]; 108 109 struct { 110 unsigned index; 111 unsigned semantic_name; 112 unsigned semantic_index; 113 } gs_input[UREG_MAX_INPUT]; 114 unsigned nr_gs_inputs; 115 116 struct { 117 unsigned index; 118 unsigned semantic_name; 119 unsigned semantic_index; 120 } system_value[UREG_MAX_SYSTEM_VALUE]; 121 unsigned nr_system_values; 122 123 struct { 124 unsigned semantic_name; 125 unsigned semantic_index; 126 unsigned usage_mask; /* = TGSI_WRITEMASK_* */ 127 } output[UREG_MAX_OUTPUT]; 128 unsigned nr_outputs; 129 130 struct { 131 union { 132 float f[4]; 133 unsigned u[4]; 134 int i[4]; 135 } value; 136 unsigned nr; 137 unsigned type; 138 } immediate[UREG_MAX_IMMEDIATE]; 139 unsigned nr_immediates; 140 141 struct ureg_src sampler[PIPE_MAX_SAMPLERS]; 142 unsigned nr_samplers; 143 144 struct { 145 unsigned index; 146 unsigned target; 147 unsigned return_type_x; 148 unsigned return_type_y; 149 unsigned return_type_z; 150 unsigned return_type_w; 151 } sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 152 unsigned nr_sampler_views; 153 154 struct util_bitmask *free_temps; 155 struct util_bitmask *local_temps; 156 unsigned nr_temps; 157 158 struct const_decl const_decls; 159 struct const_decl const_decls2D[PIPE_MAX_CONSTANT_BUFFERS]; 160 161 unsigned property_gs_input_prim; 162 unsigned property_gs_output_prim; 163 unsigned property_gs_max_vertices; 164 unsigned char property_fs_coord_origin; /* = TGSI_FS_COORD_ORIGIN_* */ 165 unsigned char property_fs_coord_pixel_center; /* = TGSI_FS_COORD_PIXEL_CENTER_* */ 166 unsigned char property_fs_color0_writes_all_cbufs; /* = TGSI_FS_COLOR0_WRITES_ALL_CBUFS * */ 167 unsigned char property_fs_depth_layout; /* TGSI_FS_DEPTH_LAYOUT */ 168 169 unsigned nr_addrs; 170 unsigned nr_preds; 171 unsigned nr_instructions; 172 173 struct ureg_tokens domain[2]; 174}; 175 176static union tgsi_any_token error_tokens[32]; 177 178static void tokens_error( struct ureg_tokens *tokens ) 179{ 180 if (tokens->tokens && tokens->tokens != error_tokens) 181 FREE(tokens->tokens); 182 183 tokens->tokens = error_tokens; 184 tokens->size = Elements(error_tokens); 185 tokens->count = 0; 186} 187 188 189static void tokens_expand( struct ureg_tokens *tokens, 190 unsigned count ) 191{ 192 unsigned old_size = tokens->size * sizeof(unsigned); 193 194 if (tokens->tokens == error_tokens) { 195 return; 196 } 197 198 while (tokens->count + count > tokens->size) { 199 tokens->size = (1 << ++tokens->order); 200 } 201 202 tokens->tokens = REALLOC(tokens->tokens, 203 old_size, 204 tokens->size * sizeof(unsigned)); 205 if (tokens->tokens == NULL) { 206 tokens_error(tokens); 207 } 208} 209 210static void set_bad( struct ureg_program *ureg ) 211{ 212 tokens_error(&ureg->domain[0]); 213} 214 215 216 217static union tgsi_any_token *get_tokens( struct ureg_program *ureg, 218 unsigned domain, 219 unsigned count ) 220{ 221 struct ureg_tokens *tokens = &ureg->domain[domain]; 222 union tgsi_any_token *result; 223 224 if (tokens->count + count > tokens->size) 225 tokens_expand(tokens, count); 226 227 result = &tokens->tokens[tokens->count]; 228 tokens->count += count; 229 return result; 230} 231 232 233static union tgsi_any_token *retrieve_token( struct ureg_program *ureg, 234 unsigned domain, 235 unsigned nr ) 236{ 237 if (ureg->domain[domain].tokens == error_tokens) 238 return &error_tokens[0]; 239 240 return &ureg->domain[domain].tokens[nr]; 241} 242 243 244 245static INLINE struct ureg_dst 246ureg_dst_register( unsigned file, 247 unsigned index ) 248{ 249 struct ureg_dst dst; 250 251 dst.File = file; 252 dst.WriteMask = TGSI_WRITEMASK_XYZW; 253 dst.Indirect = 0; 254 dst.IndirectIndex = 0; 255 dst.IndirectSwizzle = 0; 256 dst.Saturate = 0; 257 dst.Predicate = 0; 258 dst.PredNegate = 0; 259 dst.PredSwizzleX = TGSI_SWIZZLE_X; 260 dst.PredSwizzleY = TGSI_SWIZZLE_Y; 261 dst.PredSwizzleZ = TGSI_SWIZZLE_Z; 262 dst.PredSwizzleW = TGSI_SWIZZLE_W; 263 dst.Index = index; 264 265 return dst; 266} 267 268 269void 270ureg_property_gs_input_prim(struct ureg_program *ureg, 271 unsigned input_prim) 272{ 273 ureg->property_gs_input_prim = input_prim; 274} 275 276void 277ureg_property_gs_output_prim(struct ureg_program *ureg, 278 unsigned output_prim) 279{ 280 ureg->property_gs_output_prim = output_prim; 281} 282 283void 284ureg_property_gs_max_vertices(struct ureg_program *ureg, 285 unsigned max_vertices) 286{ 287 ureg->property_gs_max_vertices = max_vertices; 288} 289 290void 291ureg_property_fs_coord_origin(struct ureg_program *ureg, 292 unsigned fs_coord_origin) 293{ 294 ureg->property_fs_coord_origin = fs_coord_origin; 295} 296 297void 298ureg_property_fs_coord_pixel_center(struct ureg_program *ureg, 299 unsigned fs_coord_pixel_center) 300{ 301 ureg->property_fs_coord_pixel_center = fs_coord_pixel_center; 302} 303 304void 305ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg, 306 unsigned fs_color0_writes_all_cbufs) 307{ 308 ureg->property_fs_color0_writes_all_cbufs = fs_color0_writes_all_cbufs; 309} 310 311void 312ureg_property_fs_depth_layout(struct ureg_program *ureg, 313 unsigned fs_depth_layout) 314{ 315 ureg->property_fs_depth_layout = fs_depth_layout; 316} 317 318struct ureg_src 319ureg_DECL_fs_input_cyl_centroid(struct ureg_program *ureg, 320 unsigned semantic_name, 321 unsigned semantic_index, 322 unsigned interp_mode, 323 unsigned cylindrical_wrap, 324 unsigned centroid) 325{ 326 unsigned i; 327 328 for (i = 0; i < ureg->nr_fs_inputs; i++) { 329 if (ureg->fs_input[i].semantic_name == semantic_name && 330 ureg->fs_input[i].semantic_index == semantic_index) { 331 goto out; 332 } 333 } 334 335 if (ureg->nr_fs_inputs < UREG_MAX_INPUT) { 336 ureg->fs_input[i].semantic_name = semantic_name; 337 ureg->fs_input[i].semantic_index = semantic_index; 338 ureg->fs_input[i].interp = interp_mode; 339 ureg->fs_input[i].cylindrical_wrap = cylindrical_wrap; 340 ureg->fs_input[i].centroid = centroid; 341 ureg->nr_fs_inputs++; 342 } else { 343 set_bad(ureg); 344 } 345 346out: 347 return ureg_src_register(TGSI_FILE_INPUT, i); 348} 349 350 351struct ureg_src 352ureg_DECL_vs_input( struct ureg_program *ureg, 353 unsigned index ) 354{ 355 assert(ureg->processor == TGSI_PROCESSOR_VERTEX); 356 357 ureg->vs_inputs[index/32] |= 1 << (index % 32); 358 return ureg_src_register( TGSI_FILE_INPUT, index ); 359} 360 361 362struct ureg_src 363ureg_DECL_gs_input(struct ureg_program *ureg, 364 unsigned index, 365 unsigned semantic_name, 366 unsigned semantic_index) 367{ 368 if (ureg->nr_gs_inputs < UREG_MAX_INPUT) { 369 ureg->gs_input[ureg->nr_gs_inputs].index = index; 370 ureg->gs_input[ureg->nr_gs_inputs].semantic_name = semantic_name; 371 ureg->gs_input[ureg->nr_gs_inputs].semantic_index = semantic_index; 372 ureg->nr_gs_inputs++; 373 } else { 374 set_bad(ureg); 375 } 376 377 /* XXX: Add suport for true 2D input registers. */ 378 return ureg_src_register(TGSI_FILE_INPUT, index); 379} 380 381 382struct ureg_src 383ureg_DECL_system_value(struct ureg_program *ureg, 384 unsigned index, 385 unsigned semantic_name, 386 unsigned semantic_index) 387{ 388 if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) { 389 ureg->system_value[ureg->nr_system_values].index = index; 390 ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name; 391 ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index; 392 ureg->nr_system_values++; 393 } else { 394 set_bad(ureg); 395 } 396 397 return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index); 398} 399 400 401struct ureg_dst 402ureg_DECL_output_masked( struct ureg_program *ureg, 403 unsigned name, 404 unsigned index, 405 unsigned usage_mask ) 406{ 407 unsigned i; 408 409 assert(usage_mask != 0); 410 411 for (i = 0; i < ureg->nr_outputs; i++) { 412 if (ureg->output[i].semantic_name == name && 413 ureg->output[i].semantic_index == index) { 414 ureg->output[i].usage_mask |= usage_mask; 415 goto out; 416 } 417 } 418 419 if (ureg->nr_outputs < UREG_MAX_OUTPUT) { 420 ureg->output[i].semantic_name = name; 421 ureg->output[i].semantic_index = index; 422 ureg->output[i].usage_mask = usage_mask; 423 ureg->nr_outputs++; 424 } 425 else { 426 set_bad( ureg ); 427 } 428 429out: 430 return ureg_dst_register( TGSI_FILE_OUTPUT, i ); 431} 432 433 434struct ureg_dst 435ureg_DECL_output( struct ureg_program *ureg, 436 unsigned name, 437 unsigned index ) 438{ 439 return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW); 440} 441 442 443/* Returns a new constant register. Keep track of which have been 444 * referred to so that we can emit decls later. 445 * 446 * Constant operands declared with this function must be addressed 447 * with a two-dimensional index. 448 * 449 * There is nothing in this code to bind this constant to any tracked 450 * value or manage any constant_buffer contents -- that's the 451 * resposibility of the calling code. 452 */ 453void 454ureg_DECL_constant2D(struct ureg_program *ureg, 455 unsigned first, 456 unsigned last, 457 unsigned index2D) 458{ 459 struct const_decl *decl = &ureg->const_decls2D[index2D]; 460 461 assert(index2D < PIPE_MAX_CONSTANT_BUFFERS); 462 463 if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { 464 uint i = decl->nr_constant_ranges++; 465 466 decl->constant_range[i].first = first; 467 decl->constant_range[i].last = last; 468 } 469} 470 471 472/* A one-dimensional, depricated version of ureg_DECL_constant2D(). 473 * 474 * Constant operands declared with this function must be addressed 475 * with a one-dimensional index. 476 */ 477struct ureg_src 478ureg_DECL_constant(struct ureg_program *ureg, 479 unsigned index) 480{ 481 struct const_decl *decl = &ureg->const_decls; 482 unsigned minconst = index, maxconst = index; 483 unsigned i; 484 485 /* Inside existing range? 486 */ 487 for (i = 0; i < decl->nr_constant_ranges; i++) { 488 if (decl->constant_range[i].first <= index && 489 decl->constant_range[i].last >= index) { 490 goto out; 491 } 492 } 493 494 /* Extend existing range? 495 */ 496 for (i = 0; i < decl->nr_constant_ranges; i++) { 497 if (decl->constant_range[i].last == index - 1) { 498 decl->constant_range[i].last = index; 499 goto out; 500 } 501 502 if (decl->constant_range[i].first == index + 1) { 503 decl->constant_range[i].first = index; 504 goto out; 505 } 506 507 minconst = MIN2(minconst, decl->constant_range[i].first); 508 maxconst = MAX2(maxconst, decl->constant_range[i].last); 509 } 510 511 /* Create new range? 512 */ 513 if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { 514 i = decl->nr_constant_ranges++; 515 decl->constant_range[i].first = index; 516 decl->constant_range[i].last = index; 517 goto out; 518 } 519 520 /* Collapse all ranges down to one: 521 */ 522 i = 0; 523 decl->constant_range[0].first = minconst; 524 decl->constant_range[0].last = maxconst; 525 decl->nr_constant_ranges = 1; 526 527out: 528 assert(i < decl->nr_constant_ranges); 529 assert(decl->constant_range[i].first <= index); 530 assert(decl->constant_range[i].last >= index); 531 return ureg_src_register(TGSI_FILE_CONSTANT, index); 532} 533 534static struct ureg_dst alloc_temporary( struct ureg_program *ureg, 535 boolean local ) 536{ 537 unsigned i; 538 539 /* Look for a released temporary. 540 */ 541 for (i = util_bitmask_get_first_index(ureg->free_temps); 542 i != UTIL_BITMASK_INVALID_INDEX; 543 i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) { 544 if (util_bitmask_get(ureg->local_temps, i) == local) 545 break; 546 } 547 548 /* Or allocate a new one. 549 */ 550 if (i == UTIL_BITMASK_INVALID_INDEX) 551 i = ureg->nr_temps++; 552 553 util_bitmask_clear(ureg->free_temps, i); 554 555 if (local) 556 util_bitmask_set(ureg->local_temps, i); 557 558 return ureg_dst_register( TGSI_FILE_TEMPORARY, i ); 559} 560 561struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg ) 562{ 563 return alloc_temporary(ureg, FALSE); 564} 565 566struct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg ) 567{ 568 return alloc_temporary(ureg, TRUE); 569} 570 571void ureg_release_temporary( struct ureg_program *ureg, 572 struct ureg_dst tmp ) 573{ 574 if(tmp.File == TGSI_FILE_TEMPORARY) 575 util_bitmask_set(ureg->free_temps, tmp.Index); 576} 577 578 579/* Allocate a new address register. 580 */ 581struct ureg_dst ureg_DECL_address( struct ureg_program *ureg ) 582{ 583 if (ureg->nr_addrs < UREG_MAX_ADDR) 584 return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ ); 585 586 assert( 0 ); 587 return ureg_dst_register( TGSI_FILE_ADDRESS, 0 ); 588} 589 590/* Allocate a new predicate register. 591 */ 592struct ureg_dst 593ureg_DECL_predicate(struct ureg_program *ureg) 594{ 595 if (ureg->nr_preds < UREG_MAX_PRED) { 596 return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++); 597 } 598 599 assert(0); 600 return ureg_dst_register(TGSI_FILE_PREDICATE, 0); 601} 602 603/* Allocate a new sampler. 604 */ 605struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg, 606 unsigned nr ) 607{ 608 unsigned i; 609 610 for (i = 0; i < ureg->nr_samplers; i++) 611 if (ureg->sampler[i].Index == nr) 612 return ureg->sampler[i]; 613 614 if (i < PIPE_MAX_SAMPLERS) { 615 ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr ); 616 ureg->nr_samplers++; 617 return ureg->sampler[i]; 618 } 619 620 assert( 0 ); 621 return ureg->sampler[0]; 622} 623 624/* 625 * Allocate a new shader sampler view. 626 */ 627struct ureg_src 628ureg_DECL_sampler_view(struct ureg_program *ureg, 629 unsigned index, 630 unsigned target, 631 unsigned return_type_x, 632 unsigned return_type_y, 633 unsigned return_type_z, 634 unsigned return_type_w) 635{ 636 struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index); 637 uint i; 638 639 for (i = 0; i < ureg->nr_sampler_views; i++) { 640 if (ureg->sampler_view[i].index == index) { 641 return reg; 642 } 643 } 644 645 if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) { 646 ureg->sampler_view[i].index = index; 647 ureg->sampler_view[i].target = target; 648 ureg->sampler_view[i].return_type_x = return_type_x; 649 ureg->sampler_view[i].return_type_y = return_type_y; 650 ureg->sampler_view[i].return_type_z = return_type_z; 651 ureg->sampler_view[i].return_type_w = return_type_w; 652 ureg->nr_sampler_views++; 653 return reg; 654 } 655 656 assert(0); 657 return reg; 658} 659 660static int 661match_or_expand_immediate( const unsigned *v, 662 unsigned nr, 663 unsigned *v2, 664 unsigned *pnr2, 665 unsigned *swizzle ) 666{ 667 unsigned nr2 = *pnr2; 668 unsigned i, j; 669 670 *swizzle = 0; 671 672 for (i = 0; i < nr; i++) { 673 boolean found = FALSE; 674 675 for (j = 0; j < nr2 && !found; j++) { 676 if (v[i] == v2[j]) { 677 *swizzle |= j << (i * 2); 678 found = TRUE; 679 } 680 } 681 682 if (!found) { 683 if (nr2 >= 4) { 684 return FALSE; 685 } 686 687 v2[nr2] = v[i]; 688 *swizzle |= nr2 << (i * 2); 689 nr2++; 690 } 691 } 692 693 /* Actually expand immediate only when fully succeeded. 694 */ 695 *pnr2 = nr2; 696 return TRUE; 697} 698 699 700static struct ureg_src 701decl_immediate( struct ureg_program *ureg, 702 const unsigned *v, 703 unsigned nr, 704 unsigned type ) 705{ 706 unsigned i, j; 707 unsigned swizzle = 0; 708 709 /* Could do a first pass where we examine all existing immediates 710 * without expanding. 711 */ 712 713 for (i = 0; i < ureg->nr_immediates; i++) { 714 if (ureg->immediate[i].type != type) { 715 continue; 716 } 717 if (match_or_expand_immediate(v, 718 nr, 719 ureg->immediate[i].value.u, 720 &ureg->immediate[i].nr, 721 &swizzle)) { 722 goto out; 723 } 724 } 725 726 if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) { 727 i = ureg->nr_immediates++; 728 ureg->immediate[i].type = type; 729 if (match_or_expand_immediate(v, 730 nr, 731 ureg->immediate[i].value.u, 732 &ureg->immediate[i].nr, 733 &swizzle)) { 734 goto out; 735 } 736 } 737 738 set_bad(ureg); 739 740out: 741 /* Make sure that all referenced elements are from this immediate. 742 * Has the effect of making size-one immediates into scalars. 743 */ 744 for (j = nr; j < 4; j++) { 745 swizzle |= (swizzle & 0x3) << (j * 2); 746 } 747 748 return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i), 749 (swizzle >> 0) & 0x3, 750 (swizzle >> 2) & 0x3, 751 (swizzle >> 4) & 0x3, 752 (swizzle >> 6) & 0x3); 753} 754 755 756struct ureg_src 757ureg_DECL_immediate( struct ureg_program *ureg, 758 const float *v, 759 unsigned nr ) 760{ 761 union { 762 float f[4]; 763 unsigned u[4]; 764 } fu; 765 unsigned int i; 766 767 for (i = 0; i < nr; i++) { 768 fu.f[i] = v[i]; 769 } 770 771 return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32); 772} 773 774 775struct ureg_src 776ureg_DECL_immediate_uint( struct ureg_program *ureg, 777 const unsigned *v, 778 unsigned nr ) 779{ 780 return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32); 781} 782 783 784struct ureg_src 785ureg_DECL_immediate_block_uint( struct ureg_program *ureg, 786 const unsigned *v, 787 unsigned nr ) 788{ 789 uint index; 790 uint i; 791 792 if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) { 793 set_bad(ureg); 794 return ureg_src_register(TGSI_FILE_IMMEDIATE, 0); 795 } 796 797 index = ureg->nr_immediates; 798 ureg->nr_immediates += (nr + 3) / 4; 799 800 for (i = index; i < ureg->nr_immediates; i++) { 801 ureg->immediate[i].type = TGSI_IMM_UINT32; 802 ureg->immediate[i].nr = nr > 4 ? 4 : nr; 803 memcpy(ureg->immediate[i].value.u, 804 &v[(i - index) * 4], 805 ureg->immediate[i].nr * sizeof(uint)); 806 nr -= 4; 807 } 808 809 return ureg_src_register(TGSI_FILE_IMMEDIATE, index); 810} 811 812 813struct ureg_src 814ureg_DECL_immediate_int( struct ureg_program *ureg, 815 const int *v, 816 unsigned nr ) 817{ 818 return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32); 819} 820 821 822void 823ureg_emit_src( struct ureg_program *ureg, 824 struct ureg_src src ) 825{ 826 unsigned size = 1 + (src.Indirect ? 1 : 0) + 827 (src.Dimension ? (src.DimIndirect ? 2 : 1) : 0); 828 829 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); 830 unsigned n = 0; 831 832 assert(src.File != TGSI_FILE_NULL); 833 assert(src.File < TGSI_FILE_COUNT); 834 835 out[n].value = 0; 836 out[n].src.File = src.File; 837 out[n].src.SwizzleX = src.SwizzleX; 838 out[n].src.SwizzleY = src.SwizzleY; 839 out[n].src.SwizzleZ = src.SwizzleZ; 840 out[n].src.SwizzleW = src.SwizzleW; 841 out[n].src.Index = src.Index; 842 out[n].src.Negate = src.Negate; 843 out[0].src.Absolute = src.Absolute; 844 n++; 845 846 if (src.Indirect) { 847 out[0].src.Indirect = 1; 848 out[n].value = 0; 849 out[n].src.File = src.IndirectFile; 850 out[n].src.SwizzleX = src.IndirectSwizzle; 851 out[n].src.SwizzleY = src.IndirectSwizzle; 852 out[n].src.SwizzleZ = src.IndirectSwizzle; 853 out[n].src.SwizzleW = src.IndirectSwizzle; 854 out[n].src.Index = src.IndirectIndex; 855 n++; 856 } 857 858 if (src.Dimension) { 859 if (src.DimIndirect) { 860 out[0].src.Dimension = 1; 861 out[n].dim.Indirect = 1; 862 out[n].dim.Dimension = 0; 863 out[n].dim.Padding = 0; 864 out[n].dim.Index = src.DimensionIndex; 865 n++; 866 out[n].value = 0; 867 out[n].src.File = src.DimIndFile; 868 out[n].src.SwizzleX = src.DimIndSwizzle; 869 out[n].src.SwizzleY = src.DimIndSwizzle; 870 out[n].src.SwizzleZ = src.DimIndSwizzle; 871 out[n].src.SwizzleW = src.DimIndSwizzle; 872 out[n].src.Index = src.DimIndIndex; 873 } else { 874 out[0].src.Dimension = 1; 875 out[n].dim.Indirect = 0; 876 out[n].dim.Dimension = 0; 877 out[n].dim.Padding = 0; 878 out[n].dim.Index = src.DimensionIndex; 879 } 880 n++; 881 } 882 883 assert(n == size); 884} 885 886 887void 888ureg_emit_dst( struct ureg_program *ureg, 889 struct ureg_dst dst ) 890{ 891 unsigned size = (1 + 892 (dst.Indirect ? 1 : 0)); 893 894 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); 895 unsigned n = 0; 896 897 assert(dst.File != TGSI_FILE_NULL); 898 assert(dst.File != TGSI_FILE_CONSTANT); 899 assert(dst.File != TGSI_FILE_INPUT); 900 assert(dst.File != TGSI_FILE_SAMPLER); 901 assert(dst.File != TGSI_FILE_SAMPLER_VIEW); 902 assert(dst.File != TGSI_FILE_IMMEDIATE); 903 assert(dst.File < TGSI_FILE_COUNT); 904 905 out[n].value = 0; 906 out[n].dst.File = dst.File; 907 out[n].dst.WriteMask = dst.WriteMask; 908 out[n].dst.Indirect = dst.Indirect; 909 out[n].dst.Index = dst.Index; 910 n++; 911 912 if (dst.Indirect) { 913 out[n].value = 0; 914 out[n].src.File = TGSI_FILE_ADDRESS; 915 out[n].src.SwizzleX = dst.IndirectSwizzle; 916 out[n].src.SwizzleY = dst.IndirectSwizzle; 917 out[n].src.SwizzleZ = dst.IndirectSwizzle; 918 out[n].src.SwizzleW = dst.IndirectSwizzle; 919 out[n].src.Index = dst.IndirectIndex; 920 n++; 921 } 922 923 assert(n == size); 924} 925 926 927static void validate( unsigned opcode, 928 unsigned nr_dst, 929 unsigned nr_src ) 930{ 931#ifdef DEBUG 932 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode ); 933 assert(info); 934 if(info) { 935 assert(nr_dst == info->num_dst); 936 assert(nr_src == info->num_src); 937 } 938#endif 939} 940 941struct ureg_emit_insn_result 942ureg_emit_insn(struct ureg_program *ureg, 943 unsigned opcode, 944 boolean saturate, 945 boolean predicate, 946 boolean pred_negate, 947 unsigned pred_swizzle_x, 948 unsigned pred_swizzle_y, 949 unsigned pred_swizzle_z, 950 unsigned pred_swizzle_w, 951 unsigned num_dst, 952 unsigned num_src ) 953{ 954 union tgsi_any_token *out; 955 uint count = predicate ? 2 : 1; 956 struct ureg_emit_insn_result result; 957 958 validate( opcode, num_dst, num_src ); 959 960 out = get_tokens( ureg, DOMAIN_INSN, count ); 961 out[0].insn = tgsi_default_instruction(); 962 out[0].insn.Opcode = opcode; 963 out[0].insn.Saturate = saturate; 964 out[0].insn.NumDstRegs = num_dst; 965 out[0].insn.NumSrcRegs = num_src; 966 967 result.insn_token = ureg->domain[DOMAIN_INSN].count - count; 968 result.extended_token = result.insn_token; 969 970 if (predicate) { 971 out[0].insn.Predicate = 1; 972 out[1].insn_predicate = tgsi_default_instruction_predicate(); 973 out[1].insn_predicate.Negate = pred_negate; 974 out[1].insn_predicate.SwizzleX = pred_swizzle_x; 975 out[1].insn_predicate.SwizzleY = pred_swizzle_y; 976 out[1].insn_predicate.SwizzleZ = pred_swizzle_z; 977 out[1].insn_predicate.SwizzleW = pred_swizzle_w; 978 } 979 980 ureg->nr_instructions++; 981 982 return result; 983} 984 985 986void 987ureg_emit_label(struct ureg_program *ureg, 988 unsigned extended_token, 989 unsigned *label_token ) 990{ 991 union tgsi_any_token *out, *insn; 992 993 if(!label_token) 994 return; 995 996 out = get_tokens( ureg, DOMAIN_INSN, 1 ); 997 out[0].value = 0; 998 999 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); 1000 insn->insn.Label = 1; 1001 1002 *label_token = ureg->domain[DOMAIN_INSN].count - 1; 1003} 1004 1005/* Will return a number which can be used in a label to point to the 1006 * next instruction to be emitted. 1007 */ 1008unsigned 1009ureg_get_instruction_number( struct ureg_program *ureg ) 1010{ 1011 return ureg->nr_instructions; 1012} 1013 1014/* Patch a given label (expressed as a token number) to point to a 1015 * given instruction (expressed as an instruction number). 1016 */ 1017void 1018ureg_fixup_label(struct ureg_program *ureg, 1019 unsigned label_token, 1020 unsigned instruction_number ) 1021{ 1022 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token ); 1023 1024 out->insn_label.Label = instruction_number; 1025} 1026 1027 1028void 1029ureg_emit_texture(struct ureg_program *ureg, 1030 unsigned extended_token, 1031 unsigned target, unsigned num_offsets) 1032{ 1033 union tgsi_any_token *out, *insn; 1034 1035 out = get_tokens( ureg, DOMAIN_INSN, 1 ); 1036 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); 1037 1038 insn->insn.Texture = 1; 1039 1040 out[0].value = 0; 1041 out[0].insn_texture.Texture = target; 1042 out[0].insn_texture.NumOffsets = num_offsets; 1043} 1044 1045void 1046ureg_emit_texture_offset(struct ureg_program *ureg, 1047 const struct tgsi_texture_offset *offset) 1048{ 1049 union tgsi_any_token *out; 1050 1051 out = get_tokens( ureg, DOMAIN_INSN, 1); 1052 1053 out[0].value = 0; 1054 out[0].insn_texture_offset = *offset; 1055 1056} 1057 1058 1059void 1060ureg_fixup_insn_size(struct ureg_program *ureg, 1061 unsigned insn ) 1062{ 1063 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn ); 1064 1065 assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION); 1066 out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1; 1067} 1068 1069 1070void 1071ureg_insn(struct ureg_program *ureg, 1072 unsigned opcode, 1073 const struct ureg_dst *dst, 1074 unsigned nr_dst, 1075 const struct ureg_src *src, 1076 unsigned nr_src ) 1077{ 1078 struct ureg_emit_insn_result insn; 1079 unsigned i; 1080 boolean saturate; 1081 boolean predicate; 1082 boolean negate = FALSE; 1083 unsigned swizzle[4] = { 0 }; 1084 1085 saturate = nr_dst ? dst[0].Saturate : FALSE; 1086 predicate = nr_dst ? dst[0].Predicate : FALSE; 1087 if (predicate) { 1088 negate = dst[0].PredNegate; 1089 swizzle[0] = dst[0].PredSwizzleX; 1090 swizzle[1] = dst[0].PredSwizzleY; 1091 swizzle[2] = dst[0].PredSwizzleZ; 1092 swizzle[3] = dst[0].PredSwizzleW; 1093 } 1094 1095 insn = ureg_emit_insn(ureg, 1096 opcode, 1097 saturate, 1098 predicate, 1099 negate, 1100 swizzle[0], 1101 swizzle[1], 1102 swizzle[2], 1103 swizzle[3], 1104 nr_dst, 1105 nr_src); 1106 1107 for (i = 0; i < nr_dst; i++) 1108 ureg_emit_dst( ureg, dst[i] ); 1109 1110 for (i = 0; i < nr_src; i++) 1111 ureg_emit_src( ureg, src[i] ); 1112 1113 ureg_fixup_insn_size( ureg, insn.insn_token ); 1114} 1115 1116void 1117ureg_tex_insn(struct ureg_program *ureg, 1118 unsigned opcode, 1119 const struct ureg_dst *dst, 1120 unsigned nr_dst, 1121 unsigned target, 1122 const struct tgsi_texture_offset *texoffsets, 1123 unsigned nr_offset, 1124 const struct ureg_src *src, 1125 unsigned nr_src ) 1126{ 1127 struct ureg_emit_insn_result insn; 1128 unsigned i; 1129 boolean saturate; 1130 boolean predicate; 1131 boolean negate = FALSE; 1132 unsigned swizzle[4] = { 0 }; 1133 1134 saturate = nr_dst ? dst[0].Saturate : FALSE; 1135 predicate = nr_dst ? dst[0].Predicate : FALSE; 1136 if (predicate) { 1137 negate = dst[0].PredNegate; 1138 swizzle[0] = dst[0].PredSwizzleX; 1139 swizzle[1] = dst[0].PredSwizzleY; 1140 swizzle[2] = dst[0].PredSwizzleZ; 1141 swizzle[3] = dst[0].PredSwizzleW; 1142 } 1143 1144 insn = ureg_emit_insn(ureg, 1145 opcode, 1146 saturate, 1147 predicate, 1148 negate, 1149 swizzle[0], 1150 swizzle[1], 1151 swizzle[2], 1152 swizzle[3], 1153 nr_dst, 1154 nr_src); 1155 1156 ureg_emit_texture( ureg, insn.extended_token, target, nr_offset ); 1157 1158 for (i = 0; i < nr_offset; i++) 1159 ureg_emit_texture_offset( ureg, &texoffsets[i]); 1160 1161 for (i = 0; i < nr_dst; i++) 1162 ureg_emit_dst( ureg, dst[i] ); 1163 1164 for (i = 0; i < nr_src; i++) 1165 ureg_emit_src( ureg, src[i] ); 1166 1167 ureg_fixup_insn_size( ureg, insn.insn_token ); 1168} 1169 1170 1171void 1172ureg_label_insn(struct ureg_program *ureg, 1173 unsigned opcode, 1174 const struct ureg_src *src, 1175 unsigned nr_src, 1176 unsigned *label_token ) 1177{ 1178 struct ureg_emit_insn_result insn; 1179 unsigned i; 1180 1181 insn = ureg_emit_insn(ureg, 1182 opcode, 1183 FALSE, 1184 FALSE, 1185 FALSE, 1186 TGSI_SWIZZLE_X, 1187 TGSI_SWIZZLE_Y, 1188 TGSI_SWIZZLE_Z, 1189 TGSI_SWIZZLE_W, 1190 0, 1191 nr_src); 1192 1193 ureg_emit_label( ureg, insn.extended_token, label_token ); 1194 1195 for (i = 0; i < nr_src; i++) 1196 ureg_emit_src( ureg, src[i] ); 1197 1198 ureg_fixup_insn_size( ureg, insn.insn_token ); 1199} 1200 1201 1202static void 1203emit_decl_semantic(struct ureg_program *ureg, 1204 unsigned file, 1205 unsigned index, 1206 unsigned semantic_name, 1207 unsigned semantic_index, 1208 unsigned usage_mask) 1209{ 1210 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1211 1212 out[0].value = 0; 1213 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1214 out[0].decl.NrTokens = 3; 1215 out[0].decl.File = file; 1216 out[0].decl.UsageMask = usage_mask; 1217 out[0].decl.Semantic = 1; 1218 1219 out[1].value = 0; 1220 out[1].decl_range.First = index; 1221 out[1].decl_range.Last = index; 1222 1223 out[2].value = 0; 1224 out[2].decl_semantic.Name = semantic_name; 1225 out[2].decl_semantic.Index = semantic_index; 1226} 1227 1228 1229static void 1230emit_decl_fs(struct ureg_program *ureg, 1231 unsigned file, 1232 unsigned index, 1233 unsigned semantic_name, 1234 unsigned semantic_index, 1235 unsigned interpolate, 1236 unsigned cylindrical_wrap, 1237 unsigned centroid) 1238{ 1239 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 4); 1240 1241 out[0].value = 0; 1242 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1243 out[0].decl.NrTokens = 4; 1244 out[0].decl.File = file; 1245 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */ 1246 out[0].decl.Interpolate = 1; 1247 out[0].decl.Semantic = 1; 1248 1249 out[1].value = 0; 1250 out[1].decl_range.First = index; 1251 out[1].decl_range.Last = index; 1252 1253 out[2].value = 0; 1254 out[2].decl_interp.Interpolate = interpolate; 1255 out[2].decl_interp.CylindricalWrap = cylindrical_wrap; 1256 out[2].decl_interp.Centroid = centroid; 1257 1258 out[3].value = 0; 1259 out[3].decl_semantic.Name = semantic_name; 1260 out[3].decl_semantic.Index = semantic_index; 1261} 1262 1263 1264static void emit_decl( struct ureg_program *ureg, 1265 unsigned file, 1266 unsigned index, 1267 boolean local ) 1268{ 1269 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); 1270 1271 out[0].value = 0; 1272 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1273 out[0].decl.NrTokens = 2; 1274 out[0].decl.File = file; 1275 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1276 out[0].decl.Local = local; 1277 1278 out[1].value = 0; 1279 out[1].decl_range.First = index; 1280 out[1].decl_range.Last = index; 1281} 1282 1283static void emit_decl_range( struct ureg_program *ureg, 1284 unsigned file, 1285 unsigned first, 1286 unsigned count ) 1287{ 1288 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); 1289 1290 out[0].value = 0; 1291 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1292 out[0].decl.NrTokens = 2; 1293 out[0].decl.File = file; 1294 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1295 out[0].decl.Semantic = 0; 1296 1297 out[1].value = 0; 1298 out[1].decl_range.First = first; 1299 out[1].decl_range.Last = first + count - 1; 1300} 1301 1302static void 1303emit_decl_range2D(struct ureg_program *ureg, 1304 unsigned file, 1305 unsigned first, 1306 unsigned last, 1307 unsigned index2D) 1308{ 1309 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1310 1311 out[0].value = 0; 1312 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1313 out[0].decl.NrTokens = 3; 1314 out[0].decl.File = file; 1315 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1316 out[0].decl.Dimension = 1; 1317 1318 out[1].value = 0; 1319 out[1].decl_range.First = first; 1320 out[1].decl_range.Last = last; 1321 1322 out[2].value = 0; 1323 out[2].decl_dim.Index2D = index2D; 1324} 1325 1326static void 1327emit_decl_sampler_view(struct ureg_program *ureg, 1328 unsigned index, 1329 unsigned target, 1330 unsigned return_type_x, 1331 unsigned return_type_y, 1332 unsigned return_type_z, 1333 unsigned return_type_w ) 1334{ 1335 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1336 1337 out[0].value = 0; 1338 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1339 out[0].decl.NrTokens = 3; 1340 out[0].decl.File = TGSI_FILE_SAMPLER_VIEW; 1341 out[0].decl.UsageMask = 0xf; 1342 1343 out[1].value = 0; 1344 out[1].decl_range.First = index; 1345 out[1].decl_range.Last = index; 1346 1347 out[2].value = 0; 1348 out[2].decl_sampler_view.Resource = target; 1349 out[2].decl_sampler_view.ReturnTypeX = return_type_x; 1350 out[2].decl_sampler_view.ReturnTypeY = return_type_y; 1351 out[2].decl_sampler_view.ReturnTypeZ = return_type_z; 1352 out[2].decl_sampler_view.ReturnTypeW = return_type_w; 1353} 1354 1355static void 1356emit_immediate( struct ureg_program *ureg, 1357 const unsigned *v, 1358 unsigned type ) 1359{ 1360 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 ); 1361 1362 out[0].value = 0; 1363 out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE; 1364 out[0].imm.NrTokens = 5; 1365 out[0].imm.DataType = type; 1366 out[0].imm.Padding = 0; 1367 1368 out[1].imm_data.Uint = v[0]; 1369 out[2].imm_data.Uint = v[1]; 1370 out[3].imm_data.Uint = v[2]; 1371 out[4].imm_data.Uint = v[3]; 1372} 1373 1374static void 1375emit_property(struct ureg_program *ureg, 1376 unsigned name, 1377 unsigned data) 1378{ 1379 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2); 1380 1381 out[0].value = 0; 1382 out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY; 1383 out[0].prop.NrTokens = 2; 1384 out[0].prop.PropertyName = name; 1385 1386 out[1].prop_data.Data = data; 1387} 1388 1389 1390static void emit_decls( struct ureg_program *ureg ) 1391{ 1392 unsigned i; 1393 1394 if (ureg->property_gs_input_prim != ~0) { 1395 assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); 1396 1397 emit_property(ureg, 1398 TGSI_PROPERTY_GS_INPUT_PRIM, 1399 ureg->property_gs_input_prim); 1400 } 1401 1402 if (ureg->property_gs_output_prim != ~0) { 1403 assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); 1404 1405 emit_property(ureg, 1406 TGSI_PROPERTY_GS_OUTPUT_PRIM, 1407 ureg->property_gs_output_prim); 1408 } 1409 1410 if (ureg->property_gs_max_vertices != ~0) { 1411 assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); 1412 1413 emit_property(ureg, 1414 TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1415 ureg->property_gs_max_vertices); 1416 } 1417 1418 if (ureg->property_fs_coord_origin) { 1419 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1420 1421 emit_property(ureg, 1422 TGSI_PROPERTY_FS_COORD_ORIGIN, 1423 ureg->property_fs_coord_origin); 1424 } 1425 1426 if (ureg->property_fs_coord_pixel_center) { 1427 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1428 1429 emit_property(ureg, 1430 TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, 1431 ureg->property_fs_coord_pixel_center); 1432 } 1433 1434 if (ureg->property_fs_color0_writes_all_cbufs) { 1435 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1436 1437 emit_property(ureg, 1438 TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS, 1439 ureg->property_fs_color0_writes_all_cbufs); 1440 } 1441 1442 if (ureg->property_fs_depth_layout) { 1443 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1444 1445 emit_property(ureg, 1446 TGSI_PROPERTY_FS_DEPTH_LAYOUT, 1447 ureg->property_fs_depth_layout); 1448 } 1449 1450 if (ureg->processor == TGSI_PROCESSOR_VERTEX) { 1451 for (i = 0; i < UREG_MAX_INPUT; i++) { 1452 if (ureg->vs_inputs[i/32] & (1 << (i%32))) { 1453 emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 ); 1454 } 1455 } 1456 } else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) { 1457 for (i = 0; i < ureg->nr_fs_inputs; i++) { 1458 emit_decl_fs(ureg, 1459 TGSI_FILE_INPUT, 1460 i, 1461 ureg->fs_input[i].semantic_name, 1462 ureg->fs_input[i].semantic_index, 1463 ureg->fs_input[i].interp, 1464 ureg->fs_input[i].cylindrical_wrap, 1465 ureg->fs_input[i].centroid); 1466 } 1467 } else { 1468 for (i = 0; i < ureg->nr_gs_inputs; i++) { 1469 emit_decl_semantic(ureg, 1470 TGSI_FILE_INPUT, 1471 ureg->gs_input[i].index, 1472 ureg->gs_input[i].semantic_name, 1473 ureg->gs_input[i].semantic_index, 1474 TGSI_WRITEMASK_XYZW); 1475 } 1476 } 1477 1478 for (i = 0; i < ureg->nr_system_values; i++) { 1479 emit_decl_semantic(ureg, 1480 TGSI_FILE_SYSTEM_VALUE, 1481 ureg->system_value[i].index, 1482 ureg->system_value[i].semantic_name, 1483 ureg->system_value[i].semantic_index, 1484 TGSI_WRITEMASK_XYZW); 1485 } 1486 1487 for (i = 0; i < ureg->nr_outputs; i++) { 1488 emit_decl_semantic(ureg, 1489 TGSI_FILE_OUTPUT, 1490 i, 1491 ureg->output[i].semantic_name, 1492 ureg->output[i].semantic_index, 1493 ureg->output[i].usage_mask); 1494 } 1495 1496 for (i = 0; i < ureg->nr_samplers; i++) { 1497 emit_decl_range( ureg, 1498 TGSI_FILE_SAMPLER, 1499 ureg->sampler[i].Index, 1 ); 1500 } 1501 1502 for (i = 0; i < ureg->nr_sampler_views; i++) { 1503 emit_decl_sampler_view(ureg, 1504 ureg->sampler_view[i].index, 1505 ureg->sampler_view[i].target, 1506 ureg->sampler_view[i].return_type_x, 1507 ureg->sampler_view[i].return_type_y, 1508 ureg->sampler_view[i].return_type_z, 1509 ureg->sampler_view[i].return_type_w); 1510 } 1511 1512 if (ureg->const_decls.nr_constant_ranges) { 1513 for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) { 1514 emit_decl_range(ureg, 1515 TGSI_FILE_CONSTANT, 1516 ureg->const_decls.constant_range[i].first, 1517 ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1); 1518 } 1519 } 1520 1521 for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { 1522 struct const_decl *decl = &ureg->const_decls2D[i]; 1523 1524 if (decl->nr_constant_ranges) { 1525 uint j; 1526 1527 for (j = 0; j < decl->nr_constant_ranges; j++) { 1528 emit_decl_range2D(ureg, 1529 TGSI_FILE_CONSTANT, 1530 decl->constant_range[j].first, 1531 decl->constant_range[j].last, 1532 i); 1533 } 1534 } 1535 } 1536 1537 if (ureg->nr_temps) { 1538 if (util_bitmask_get_first_index(ureg->local_temps) == UTIL_BITMASK_INVALID_INDEX) { 1539 emit_decl_range( ureg, 1540 TGSI_FILE_TEMPORARY, 1541 0, ureg->nr_temps ); 1542 1543 } else { 1544 for (i = 0; i < ureg->nr_temps; i++) { 1545 emit_decl( ureg, TGSI_FILE_TEMPORARY, i, 1546 util_bitmask_get(ureg->local_temps, i) ); 1547 } 1548 } 1549 } 1550 1551 if (ureg->nr_addrs) { 1552 emit_decl_range( ureg, 1553 TGSI_FILE_ADDRESS, 1554 0, ureg->nr_addrs ); 1555 } 1556 1557 if (ureg->nr_preds) { 1558 emit_decl_range(ureg, 1559 TGSI_FILE_PREDICATE, 1560 0, 1561 ureg->nr_preds); 1562 } 1563 1564 for (i = 0; i < ureg->nr_immediates; i++) { 1565 emit_immediate( ureg, 1566 ureg->immediate[i].value.u, 1567 ureg->immediate[i].type ); 1568 } 1569} 1570 1571/* Append the instruction tokens onto the declarations to build a 1572 * contiguous stream suitable to send to the driver. 1573 */ 1574static void copy_instructions( struct ureg_program *ureg ) 1575{ 1576 unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count; 1577 union tgsi_any_token *out = get_tokens( ureg, 1578 DOMAIN_DECL, 1579 nr_tokens ); 1580 1581 memcpy(out, 1582 ureg->domain[DOMAIN_INSN].tokens, 1583 nr_tokens * sizeof out[0] ); 1584} 1585 1586 1587static void 1588fixup_header_size(struct ureg_program *ureg) 1589{ 1590 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 ); 1591 1592 out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2; 1593} 1594 1595 1596static void 1597emit_header( struct ureg_program *ureg ) 1598{ 1599 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); 1600 1601 out[0].header.HeaderSize = 2; 1602 out[0].header.BodySize = 0; 1603 1604 out[1].processor.Processor = ureg->processor; 1605 out[1].processor.Padding = 0; 1606} 1607 1608 1609const struct tgsi_token *ureg_finalize( struct ureg_program *ureg ) 1610{ 1611 const struct tgsi_token *tokens; 1612 1613 emit_header( ureg ); 1614 emit_decls( ureg ); 1615 copy_instructions( ureg ); 1616 fixup_header_size( ureg ); 1617 1618 if (ureg->domain[0].tokens == error_tokens || 1619 ureg->domain[1].tokens == error_tokens) { 1620 debug_printf("%s: error in generated shader\n", __FUNCTION__); 1621 assert(0); 1622 return NULL; 1623 } 1624 1625 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; 1626 1627 if (0) { 1628 debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__, 1629 ureg->domain[DOMAIN_DECL].count); 1630 tgsi_dump( tokens, 0 ); 1631 } 1632 1633#if DEBUG 1634 if (tokens && !tgsi_sanity_check(tokens)) { 1635 debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n"); 1636 tgsi_dump(tokens, 0); 1637 assert(0); 1638 } 1639#endif 1640 1641 1642 return tokens; 1643} 1644 1645 1646void *ureg_create_shader( struct ureg_program *ureg, 1647 struct pipe_context *pipe, 1648 const struct pipe_stream_output_info *so ) 1649{ 1650 struct pipe_shader_state state; 1651 1652 state.tokens = ureg_finalize(ureg); 1653 if(!state.tokens) 1654 return NULL; 1655 1656 if (so) 1657 state.stream_output = *so; 1658 else 1659 memset(&state.stream_output, 0, sizeof(state.stream_output)); 1660 1661 if (ureg->processor == TGSI_PROCESSOR_VERTEX) 1662 return pipe->create_vs_state( pipe, &state ); 1663 else 1664 return pipe->create_fs_state( pipe, &state ); 1665} 1666 1667 1668const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg, 1669 unsigned *nr_tokens ) 1670{ 1671 const struct tgsi_token *tokens; 1672 1673 ureg_finalize(ureg); 1674 1675 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; 1676 1677 if (nr_tokens) 1678 *nr_tokens = ureg->domain[DOMAIN_DECL].size; 1679 1680 ureg->domain[DOMAIN_DECL].tokens = 0; 1681 ureg->domain[DOMAIN_DECL].size = 0; 1682 ureg->domain[DOMAIN_DECL].order = 0; 1683 ureg->domain[DOMAIN_DECL].count = 0; 1684 1685 return tokens; 1686} 1687 1688 1689void ureg_free_tokens( const struct tgsi_token *tokens ) 1690{ 1691 FREE((struct tgsi_token *)tokens); 1692} 1693 1694 1695struct ureg_program *ureg_create( unsigned processor ) 1696{ 1697 struct ureg_program *ureg = CALLOC_STRUCT( ureg_program ); 1698 if (ureg == NULL) 1699 goto no_ureg; 1700 1701 ureg->processor = processor; 1702 ureg->property_gs_input_prim = ~0; 1703 ureg->property_gs_output_prim = ~0; 1704 ureg->property_gs_max_vertices = ~0; 1705 1706 ureg->free_temps = util_bitmask_create(); 1707 if (ureg->free_temps == NULL) 1708 goto no_free_temps; 1709 1710 ureg->local_temps = util_bitmask_create(); 1711 if (ureg->local_temps == NULL) 1712 goto no_local_temps; 1713 1714 return ureg; 1715 1716no_local_temps: 1717 util_bitmask_destroy(ureg->free_temps); 1718no_free_temps: 1719 FREE(ureg); 1720no_ureg: 1721 return NULL; 1722} 1723 1724 1725void ureg_destroy( struct ureg_program *ureg ) 1726{ 1727 unsigned i; 1728 1729 for (i = 0; i < Elements(ureg->domain); i++) { 1730 if (ureg->domain[i].tokens && 1731 ureg->domain[i].tokens != error_tokens) 1732 FREE(ureg->domain[i].tokens); 1733 } 1734 1735 util_bitmask_destroy(ureg->free_temps); 1736 util_bitmask_destroy(ureg->local_temps); 1737 1738 FREE(ureg); 1739} 1740