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