tgsi_ureg.c revision 1b8aecc797b72a84c4a571639e952fe1f84e0fa5
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_ATTRIBS 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 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 533struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg ) 534{ 535 /* Look for a released temporary. 536 */ 537 unsigned i = util_bitmask_get_first_index(ureg->free_temps); 538 539 /* Or allocate a new one. 540 */ 541 if (i == UTIL_BITMASK_INVALID_INDEX) 542 i = ureg->nr_temps++; 543 544 util_bitmask_clear(ureg->free_temps, i); 545 546 return ureg_dst_register( TGSI_FILE_TEMPORARY, i ); 547} 548 549void ureg_release_temporary( struct ureg_program *ureg, 550 struct ureg_dst tmp ) 551{ 552 if(tmp.File == TGSI_FILE_TEMPORARY) 553 util_bitmask_set(ureg->free_temps, tmp.Index); 554} 555 556 557/* Allocate a new address register. 558 */ 559struct ureg_dst ureg_DECL_address( struct ureg_program *ureg ) 560{ 561 if (ureg->nr_addrs < UREG_MAX_ADDR) 562 return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ ); 563 564 assert( 0 ); 565 return ureg_dst_register( TGSI_FILE_ADDRESS, 0 ); 566} 567 568/* Allocate a new predicate register. 569 */ 570struct ureg_dst 571ureg_DECL_predicate(struct ureg_program *ureg) 572{ 573 if (ureg->nr_preds < UREG_MAX_PRED) { 574 return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++); 575 } 576 577 assert(0); 578 return ureg_dst_register(TGSI_FILE_PREDICATE, 0); 579} 580 581/* Allocate a new sampler. 582 */ 583struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg, 584 unsigned nr ) 585{ 586 unsigned i; 587 588 for (i = 0; i < ureg->nr_samplers; i++) 589 if (ureg->sampler[i].Index == nr) 590 return ureg->sampler[i]; 591 592 if (i < PIPE_MAX_SAMPLERS) { 593 ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr ); 594 ureg->nr_samplers++; 595 return ureg->sampler[i]; 596 } 597 598 assert( 0 ); 599 return ureg->sampler[0]; 600} 601 602/* 603 * Allocate a new shader sampler view. 604 */ 605struct ureg_src 606ureg_DECL_sampler_view(struct ureg_program *ureg, 607 unsigned index, 608 unsigned target, 609 unsigned return_type_x, 610 unsigned return_type_y, 611 unsigned return_type_z, 612 unsigned return_type_w) 613{ 614 struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index); 615 uint i; 616 617 for (i = 0; i < ureg->nr_sampler_views; i++) { 618 if (ureg->sampler_view[i].index == index) { 619 return reg; 620 } 621 } 622 623 if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) { 624 ureg->sampler_view[i].index = index; 625 ureg->sampler_view[i].target = target; 626 ureg->sampler_view[i].return_type_x = return_type_x; 627 ureg->sampler_view[i].return_type_y = return_type_y; 628 ureg->sampler_view[i].return_type_z = return_type_z; 629 ureg->sampler_view[i].return_type_w = return_type_w; 630 ureg->nr_sampler_views++; 631 return reg; 632 } 633 634 assert(0); 635 return reg; 636} 637 638static int 639match_or_expand_immediate( const unsigned *v, 640 unsigned nr, 641 unsigned *v2, 642 unsigned *pnr2, 643 unsigned *swizzle ) 644{ 645 unsigned nr2 = *pnr2; 646 unsigned i, j; 647 648 *swizzle = 0; 649 650 for (i = 0; i < nr; i++) { 651 boolean found = FALSE; 652 653 for (j = 0; j < nr2 && !found; j++) { 654 if (v[i] == v2[j]) { 655 *swizzle |= j << (i * 2); 656 found = TRUE; 657 } 658 } 659 660 if (!found) { 661 if (nr2 >= 4) { 662 return FALSE; 663 } 664 665 v2[nr2] = v[i]; 666 *swizzle |= nr2 << (i * 2); 667 nr2++; 668 } 669 } 670 671 /* Actually expand immediate only when fully succeeded. 672 */ 673 *pnr2 = nr2; 674 return TRUE; 675} 676 677 678static struct ureg_src 679decl_immediate( struct ureg_program *ureg, 680 const unsigned *v, 681 unsigned nr, 682 unsigned type ) 683{ 684 unsigned i, j; 685 unsigned swizzle = 0; 686 687 /* Could do a first pass where we examine all existing immediates 688 * without expanding. 689 */ 690 691 for (i = 0; i < ureg->nr_immediates; i++) { 692 if (ureg->immediate[i].type != type) { 693 continue; 694 } 695 if (match_or_expand_immediate(v, 696 nr, 697 ureg->immediate[i].value.u, 698 &ureg->immediate[i].nr, 699 &swizzle)) { 700 goto out; 701 } 702 } 703 704 if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) { 705 i = ureg->nr_immediates++; 706 ureg->immediate[i].type = type; 707 if (match_or_expand_immediate(v, 708 nr, 709 ureg->immediate[i].value.u, 710 &ureg->immediate[i].nr, 711 &swizzle)) { 712 goto out; 713 } 714 } 715 716 set_bad(ureg); 717 718out: 719 /* Make sure that all referenced elements are from this immediate. 720 * Has the effect of making size-one immediates into scalars. 721 */ 722 for (j = nr; j < 4; j++) { 723 swizzle |= (swizzle & 0x3) << (j * 2); 724 } 725 726 return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i), 727 (swizzle >> 0) & 0x3, 728 (swizzle >> 2) & 0x3, 729 (swizzle >> 4) & 0x3, 730 (swizzle >> 6) & 0x3); 731} 732 733 734struct ureg_src 735ureg_DECL_immediate( struct ureg_program *ureg, 736 const float *v, 737 unsigned nr ) 738{ 739 union { 740 float f[4]; 741 unsigned u[4]; 742 } fu; 743 unsigned int i; 744 745 for (i = 0; i < nr; i++) { 746 fu.f[i] = v[i]; 747 } 748 749 return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32); 750} 751 752 753struct ureg_src 754ureg_DECL_immediate_uint( struct ureg_program *ureg, 755 const unsigned *v, 756 unsigned nr ) 757{ 758 return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32); 759} 760 761 762struct ureg_src 763ureg_DECL_immediate_block_uint( struct ureg_program *ureg, 764 const unsigned *v, 765 unsigned nr ) 766{ 767 uint index; 768 uint i; 769 770 if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) { 771 set_bad(ureg); 772 return ureg_src_register(TGSI_FILE_IMMEDIATE, 0); 773 } 774 775 index = ureg->nr_immediates; 776 ureg->nr_immediates += (nr + 3) / 4; 777 778 for (i = index; i < ureg->nr_immediates; i++) { 779 ureg->immediate[i].type = TGSI_IMM_UINT32; 780 ureg->immediate[i].nr = nr > 4 ? 4 : nr; 781 memcpy(ureg->immediate[i].value.u, 782 &v[(i - index) * 4], 783 ureg->immediate[i].nr * sizeof(uint)); 784 nr -= 4; 785 } 786 787 return ureg_src_register(TGSI_FILE_IMMEDIATE, index); 788} 789 790 791struct ureg_src 792ureg_DECL_immediate_int( struct ureg_program *ureg, 793 const int *v, 794 unsigned nr ) 795{ 796 return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32); 797} 798 799 800void 801ureg_emit_src( struct ureg_program *ureg, 802 struct ureg_src src ) 803{ 804 unsigned size = 1 + (src.Indirect ? 1 : 0) + 805 (src.Dimension ? (src.DimIndirect ? 2 : 1) : 0); 806 807 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); 808 unsigned n = 0; 809 810 assert(src.File != TGSI_FILE_NULL); 811 assert(src.File < TGSI_FILE_COUNT); 812 813 out[n].value = 0; 814 out[n].src.File = src.File; 815 out[n].src.SwizzleX = src.SwizzleX; 816 out[n].src.SwizzleY = src.SwizzleY; 817 out[n].src.SwizzleZ = src.SwizzleZ; 818 out[n].src.SwizzleW = src.SwizzleW; 819 out[n].src.Index = src.Index; 820 out[n].src.Negate = src.Negate; 821 out[0].src.Absolute = src.Absolute; 822 n++; 823 824 if (src.Indirect) { 825 out[0].src.Indirect = 1; 826 out[n].value = 0; 827 out[n].src.File = src.IndirectFile; 828 out[n].src.SwizzleX = src.IndirectSwizzle; 829 out[n].src.SwizzleY = src.IndirectSwizzle; 830 out[n].src.SwizzleZ = src.IndirectSwizzle; 831 out[n].src.SwizzleW = src.IndirectSwizzle; 832 out[n].src.Index = src.IndirectIndex; 833 n++; 834 } 835 836 if (src.Dimension) { 837 if (src.DimIndirect) { 838 out[0].src.Dimension = 1; 839 out[n].dim.Indirect = 1; 840 out[n].dim.Dimension = 0; 841 out[n].dim.Padding = 0; 842 out[n].dim.Index = src.DimensionIndex; 843 n++; 844 out[n].value = 0; 845 out[n].src.File = src.DimIndFile; 846 out[n].src.SwizzleX = src.DimIndSwizzle; 847 out[n].src.SwizzleY = src.DimIndSwizzle; 848 out[n].src.SwizzleZ = src.DimIndSwizzle; 849 out[n].src.SwizzleW = src.DimIndSwizzle; 850 out[n].src.Index = src.DimIndIndex; 851 } else { 852 out[0].src.Dimension = 1; 853 out[n].dim.Indirect = 0; 854 out[n].dim.Dimension = 0; 855 out[n].dim.Padding = 0; 856 out[n].dim.Index = src.DimensionIndex; 857 } 858 n++; 859 } 860 861 assert(n == size); 862} 863 864 865void 866ureg_emit_dst( struct ureg_program *ureg, 867 struct ureg_dst dst ) 868{ 869 unsigned size = (1 + 870 (dst.Indirect ? 1 : 0)); 871 872 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); 873 unsigned n = 0; 874 875 assert(dst.File != TGSI_FILE_NULL); 876 assert(dst.File != TGSI_FILE_CONSTANT); 877 assert(dst.File != TGSI_FILE_INPUT); 878 assert(dst.File != TGSI_FILE_SAMPLER); 879 assert(dst.File != TGSI_FILE_SAMPLER_VIEW); 880 assert(dst.File != TGSI_FILE_IMMEDIATE); 881 assert(dst.File < TGSI_FILE_COUNT); 882 883 out[n].value = 0; 884 out[n].dst.File = dst.File; 885 out[n].dst.WriteMask = dst.WriteMask; 886 out[n].dst.Indirect = dst.Indirect; 887 out[n].dst.Index = dst.Index; 888 n++; 889 890 if (dst.Indirect) { 891 out[n].value = 0; 892 out[n].src.File = TGSI_FILE_ADDRESS; 893 out[n].src.SwizzleX = dst.IndirectSwizzle; 894 out[n].src.SwizzleY = dst.IndirectSwizzle; 895 out[n].src.SwizzleZ = dst.IndirectSwizzle; 896 out[n].src.SwizzleW = dst.IndirectSwizzle; 897 out[n].src.Index = dst.IndirectIndex; 898 n++; 899 } 900 901 assert(n == size); 902} 903 904 905static void validate( unsigned opcode, 906 unsigned nr_dst, 907 unsigned nr_src ) 908{ 909#ifdef DEBUG 910 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode ); 911 assert(info); 912 if(info) { 913 assert(nr_dst == info->num_dst); 914 assert(nr_src == info->num_src); 915 } 916#endif 917} 918 919struct ureg_emit_insn_result 920ureg_emit_insn(struct ureg_program *ureg, 921 unsigned opcode, 922 boolean saturate, 923 boolean predicate, 924 boolean pred_negate, 925 unsigned pred_swizzle_x, 926 unsigned pred_swizzle_y, 927 unsigned pred_swizzle_z, 928 unsigned pred_swizzle_w, 929 unsigned num_dst, 930 unsigned num_src ) 931{ 932 union tgsi_any_token *out; 933 uint count = predicate ? 2 : 1; 934 struct ureg_emit_insn_result result; 935 936 validate( opcode, num_dst, num_src ); 937 938 out = get_tokens( ureg, DOMAIN_INSN, count ); 939 out[0].insn = tgsi_default_instruction(); 940 out[0].insn.Opcode = opcode; 941 out[0].insn.Saturate = saturate; 942 out[0].insn.NumDstRegs = num_dst; 943 out[0].insn.NumSrcRegs = num_src; 944 945 result.insn_token = ureg->domain[DOMAIN_INSN].count - count; 946 result.extended_token = result.insn_token; 947 948 if (predicate) { 949 out[0].insn.Predicate = 1; 950 out[1].insn_predicate = tgsi_default_instruction_predicate(); 951 out[1].insn_predicate.Negate = pred_negate; 952 out[1].insn_predicate.SwizzleX = pred_swizzle_x; 953 out[1].insn_predicate.SwizzleY = pred_swizzle_y; 954 out[1].insn_predicate.SwizzleZ = pred_swizzle_z; 955 out[1].insn_predicate.SwizzleW = pred_swizzle_w; 956 } 957 958 ureg->nr_instructions++; 959 960 return result; 961} 962 963 964void 965ureg_emit_label(struct ureg_program *ureg, 966 unsigned extended_token, 967 unsigned *label_token ) 968{ 969 union tgsi_any_token *out, *insn; 970 971 if(!label_token) 972 return; 973 974 out = get_tokens( ureg, DOMAIN_INSN, 1 ); 975 out[0].value = 0; 976 977 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); 978 insn->insn.Label = 1; 979 980 *label_token = ureg->domain[DOMAIN_INSN].count - 1; 981} 982 983/* Will return a number which can be used in a label to point to the 984 * next instruction to be emitted. 985 */ 986unsigned 987ureg_get_instruction_number( struct ureg_program *ureg ) 988{ 989 return ureg->nr_instructions; 990} 991 992/* Patch a given label (expressed as a token number) to point to a 993 * given instruction (expressed as an instruction number). 994 */ 995void 996ureg_fixup_label(struct ureg_program *ureg, 997 unsigned label_token, 998 unsigned instruction_number ) 999{ 1000 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token ); 1001 1002 out->insn_label.Label = instruction_number; 1003} 1004 1005 1006void 1007ureg_emit_texture(struct ureg_program *ureg, 1008 unsigned extended_token, 1009 unsigned target, unsigned num_offsets) 1010{ 1011 union tgsi_any_token *out, *insn; 1012 1013 out = get_tokens( ureg, DOMAIN_INSN, 1 ); 1014 insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); 1015 1016 insn->insn.Texture = 1; 1017 1018 out[0].value = 0; 1019 out[0].insn_texture.Texture = target; 1020 out[0].insn_texture.NumOffsets = num_offsets; 1021} 1022 1023void 1024ureg_emit_texture_offset(struct ureg_program *ureg, 1025 const struct tgsi_texture_offset *offset) 1026{ 1027 union tgsi_any_token *out; 1028 1029 out = get_tokens( ureg, DOMAIN_INSN, 1); 1030 1031 out[0].value = 0; 1032 out[0].insn_texture_offset = *offset; 1033 1034} 1035 1036 1037void 1038ureg_fixup_insn_size(struct ureg_program *ureg, 1039 unsigned insn ) 1040{ 1041 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn ); 1042 1043 assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION); 1044 out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1; 1045} 1046 1047 1048void 1049ureg_insn(struct ureg_program *ureg, 1050 unsigned opcode, 1051 const struct ureg_dst *dst, 1052 unsigned nr_dst, 1053 const struct ureg_src *src, 1054 unsigned nr_src ) 1055{ 1056 struct ureg_emit_insn_result insn; 1057 unsigned i; 1058 boolean saturate; 1059 boolean predicate; 1060 boolean negate = FALSE; 1061 unsigned swizzle[4] = { 0 }; 1062 1063 saturate = nr_dst ? dst[0].Saturate : FALSE; 1064 predicate = nr_dst ? dst[0].Predicate : FALSE; 1065 if (predicate) { 1066 negate = dst[0].PredNegate; 1067 swizzle[0] = dst[0].PredSwizzleX; 1068 swizzle[1] = dst[0].PredSwizzleY; 1069 swizzle[2] = dst[0].PredSwizzleZ; 1070 swizzle[3] = dst[0].PredSwizzleW; 1071 } 1072 1073 insn = ureg_emit_insn(ureg, 1074 opcode, 1075 saturate, 1076 predicate, 1077 negate, 1078 swizzle[0], 1079 swizzle[1], 1080 swizzle[2], 1081 swizzle[3], 1082 nr_dst, 1083 nr_src); 1084 1085 for (i = 0; i < nr_dst; i++) 1086 ureg_emit_dst( ureg, dst[i] ); 1087 1088 for (i = 0; i < nr_src; i++) 1089 ureg_emit_src( ureg, src[i] ); 1090 1091 ureg_fixup_insn_size( ureg, insn.insn_token ); 1092} 1093 1094void 1095ureg_tex_insn(struct ureg_program *ureg, 1096 unsigned opcode, 1097 const struct ureg_dst *dst, 1098 unsigned nr_dst, 1099 unsigned target, 1100 const struct tgsi_texture_offset *texoffsets, 1101 unsigned nr_offset, 1102 const struct ureg_src *src, 1103 unsigned nr_src ) 1104{ 1105 struct ureg_emit_insn_result insn; 1106 unsigned i; 1107 boolean saturate; 1108 boolean predicate; 1109 boolean negate = FALSE; 1110 unsigned swizzle[4] = { 0 }; 1111 1112 saturate = nr_dst ? dst[0].Saturate : FALSE; 1113 predicate = nr_dst ? dst[0].Predicate : FALSE; 1114 if (predicate) { 1115 negate = dst[0].PredNegate; 1116 swizzle[0] = dst[0].PredSwizzleX; 1117 swizzle[1] = dst[0].PredSwizzleY; 1118 swizzle[2] = dst[0].PredSwizzleZ; 1119 swizzle[3] = dst[0].PredSwizzleW; 1120 } 1121 1122 insn = ureg_emit_insn(ureg, 1123 opcode, 1124 saturate, 1125 predicate, 1126 negate, 1127 swizzle[0], 1128 swizzle[1], 1129 swizzle[2], 1130 swizzle[3], 1131 nr_dst, 1132 nr_src); 1133 1134 ureg_emit_texture( ureg, insn.extended_token, target, nr_offset ); 1135 1136 for (i = 0; i < nr_offset; i++) 1137 ureg_emit_texture_offset( ureg, &texoffsets[i]); 1138 1139 for (i = 0; i < nr_dst; i++) 1140 ureg_emit_dst( ureg, dst[i] ); 1141 1142 for (i = 0; i < nr_src; i++) 1143 ureg_emit_src( ureg, src[i] ); 1144 1145 ureg_fixup_insn_size( ureg, insn.insn_token ); 1146} 1147 1148 1149void 1150ureg_label_insn(struct ureg_program *ureg, 1151 unsigned opcode, 1152 const struct ureg_src *src, 1153 unsigned nr_src, 1154 unsigned *label_token ) 1155{ 1156 struct ureg_emit_insn_result insn; 1157 unsigned i; 1158 1159 insn = ureg_emit_insn(ureg, 1160 opcode, 1161 FALSE, 1162 FALSE, 1163 FALSE, 1164 TGSI_SWIZZLE_X, 1165 TGSI_SWIZZLE_Y, 1166 TGSI_SWIZZLE_Z, 1167 TGSI_SWIZZLE_W, 1168 0, 1169 nr_src); 1170 1171 ureg_emit_label( ureg, insn.extended_token, label_token ); 1172 1173 for (i = 0; i < nr_src; i++) 1174 ureg_emit_src( ureg, src[i] ); 1175 1176 ureg_fixup_insn_size( ureg, insn.insn_token ); 1177} 1178 1179 1180static void 1181emit_decl_semantic(struct ureg_program *ureg, 1182 unsigned file, 1183 unsigned index, 1184 unsigned semantic_name, 1185 unsigned semantic_index, 1186 unsigned usage_mask) 1187{ 1188 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1189 1190 out[0].value = 0; 1191 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1192 out[0].decl.NrTokens = 3; 1193 out[0].decl.File = file; 1194 out[0].decl.UsageMask = usage_mask; 1195 out[0].decl.Semantic = 1; 1196 1197 out[1].value = 0; 1198 out[1].decl_range.First = index; 1199 out[1].decl_range.Last = index; 1200 1201 out[2].value = 0; 1202 out[2].decl_semantic.Name = semantic_name; 1203 out[2].decl_semantic.Index = semantic_index; 1204} 1205 1206 1207static void 1208emit_decl_fs(struct ureg_program *ureg, 1209 unsigned file, 1210 unsigned index, 1211 unsigned semantic_name, 1212 unsigned semantic_index, 1213 unsigned interpolate, 1214 unsigned cylindrical_wrap, 1215 unsigned centroid) 1216{ 1217 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 4); 1218 1219 out[0].value = 0; 1220 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1221 out[0].decl.NrTokens = 4; 1222 out[0].decl.File = file; 1223 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */ 1224 out[0].decl.Interpolate = 1; 1225 out[0].decl.Semantic = 1; 1226 1227 out[1].value = 0; 1228 out[1].decl_range.First = index; 1229 out[1].decl_range.Last = index; 1230 1231 out[2].value = 0; 1232 out[2].decl_interp.Interpolate = interpolate; 1233 out[2].decl_interp.CylindricalWrap = cylindrical_wrap; 1234 out[2].decl_interp.Centroid = centroid; 1235 1236 out[3].value = 0; 1237 out[3].decl_semantic.Name = semantic_name; 1238 out[3].decl_semantic.Index = semantic_index; 1239} 1240 1241 1242static void emit_decl_range( struct ureg_program *ureg, 1243 unsigned file, 1244 unsigned first, 1245 unsigned count ) 1246{ 1247 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); 1248 1249 out[0].value = 0; 1250 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1251 out[0].decl.NrTokens = 2; 1252 out[0].decl.File = file; 1253 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1254 out[0].decl.Semantic = 0; 1255 1256 out[1].value = 0; 1257 out[1].decl_range.First = first; 1258 out[1].decl_range.Last = first + count - 1; 1259} 1260 1261static void 1262emit_decl_range2D(struct ureg_program *ureg, 1263 unsigned file, 1264 unsigned first, 1265 unsigned last, 1266 unsigned index2D) 1267{ 1268 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1269 1270 out[0].value = 0; 1271 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1272 out[0].decl.NrTokens = 3; 1273 out[0].decl.File = file; 1274 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1275 out[0].decl.Dimension = 1; 1276 1277 out[1].value = 0; 1278 out[1].decl_range.First = first; 1279 out[1].decl_range.Last = last; 1280 1281 out[2].value = 0; 1282 out[2].decl_dim.Index2D = index2D; 1283} 1284 1285static void 1286emit_decl_sampler_view(struct ureg_program *ureg, 1287 unsigned index, 1288 unsigned target, 1289 unsigned return_type_x, 1290 unsigned return_type_y, 1291 unsigned return_type_z, 1292 unsigned return_type_w ) 1293{ 1294 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1295 1296 out[0].value = 0; 1297 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1298 out[0].decl.NrTokens = 3; 1299 out[0].decl.File = TGSI_FILE_SAMPLER_VIEW; 1300 out[0].decl.UsageMask = 0xf; 1301 1302 out[1].value = 0; 1303 out[1].decl_range.First = index; 1304 out[1].decl_range.Last = index; 1305 1306 out[2].value = 0; 1307 out[2].decl_sampler_view.Resource = target; 1308 out[2].decl_sampler_view.ReturnTypeX = return_type_x; 1309 out[2].decl_sampler_view.ReturnTypeY = return_type_y; 1310 out[2].decl_sampler_view.ReturnTypeZ = return_type_z; 1311 out[2].decl_sampler_view.ReturnTypeW = return_type_w; 1312} 1313 1314static void 1315emit_immediate( struct ureg_program *ureg, 1316 const unsigned *v, 1317 unsigned type ) 1318{ 1319 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 ); 1320 1321 out[0].value = 0; 1322 out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE; 1323 out[0].imm.NrTokens = 5; 1324 out[0].imm.DataType = type; 1325 out[0].imm.Padding = 0; 1326 1327 out[1].imm_data.Uint = v[0]; 1328 out[2].imm_data.Uint = v[1]; 1329 out[3].imm_data.Uint = v[2]; 1330 out[4].imm_data.Uint = v[3]; 1331} 1332 1333static void 1334emit_property(struct ureg_program *ureg, 1335 unsigned name, 1336 unsigned data) 1337{ 1338 union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2); 1339 1340 out[0].value = 0; 1341 out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY; 1342 out[0].prop.NrTokens = 2; 1343 out[0].prop.PropertyName = name; 1344 1345 out[1].prop_data.Data = data; 1346} 1347 1348 1349static void emit_decls( struct ureg_program *ureg ) 1350{ 1351 unsigned i; 1352 1353 if (ureg->property_gs_input_prim != ~0) { 1354 assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); 1355 1356 emit_property(ureg, 1357 TGSI_PROPERTY_GS_INPUT_PRIM, 1358 ureg->property_gs_input_prim); 1359 } 1360 1361 if (ureg->property_gs_output_prim != ~0) { 1362 assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); 1363 1364 emit_property(ureg, 1365 TGSI_PROPERTY_GS_OUTPUT_PRIM, 1366 ureg->property_gs_output_prim); 1367 } 1368 1369 if (ureg->property_gs_max_vertices != ~0) { 1370 assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY); 1371 1372 emit_property(ureg, 1373 TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1374 ureg->property_gs_max_vertices); 1375 } 1376 1377 if (ureg->property_fs_coord_origin) { 1378 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1379 1380 emit_property(ureg, 1381 TGSI_PROPERTY_FS_COORD_ORIGIN, 1382 ureg->property_fs_coord_origin); 1383 } 1384 1385 if (ureg->property_fs_coord_pixel_center) { 1386 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1387 1388 emit_property(ureg, 1389 TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, 1390 ureg->property_fs_coord_pixel_center); 1391 } 1392 1393 if (ureg->property_fs_color0_writes_all_cbufs) { 1394 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1395 1396 emit_property(ureg, 1397 TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS, 1398 ureg->property_fs_color0_writes_all_cbufs); 1399 } 1400 1401 if (ureg->property_fs_depth_layout) { 1402 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); 1403 1404 emit_property(ureg, 1405 TGSI_PROPERTY_FS_DEPTH_LAYOUT, 1406 ureg->property_fs_depth_layout); 1407 } 1408 1409 if (ureg->processor == TGSI_PROCESSOR_VERTEX) { 1410 for (i = 0; i < UREG_MAX_INPUT; i++) { 1411 if (ureg->vs_inputs[i/32] & (1 << (i%32))) { 1412 emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 ); 1413 } 1414 } 1415 } else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) { 1416 for (i = 0; i < ureg->nr_fs_inputs; i++) { 1417 emit_decl_fs(ureg, 1418 TGSI_FILE_INPUT, 1419 i, 1420 ureg->fs_input[i].semantic_name, 1421 ureg->fs_input[i].semantic_index, 1422 ureg->fs_input[i].interp, 1423 ureg->fs_input[i].cylindrical_wrap, 1424 ureg->fs_input[i].centroid); 1425 } 1426 } else { 1427 for (i = 0; i < ureg->nr_gs_inputs; i++) { 1428 emit_decl_semantic(ureg, 1429 TGSI_FILE_INPUT, 1430 ureg->gs_input[i].index, 1431 ureg->gs_input[i].semantic_name, 1432 ureg->gs_input[i].semantic_index, 1433 TGSI_WRITEMASK_XYZW); 1434 } 1435 } 1436 1437 for (i = 0; i < ureg->nr_system_values; i++) { 1438 emit_decl_semantic(ureg, 1439 TGSI_FILE_SYSTEM_VALUE, 1440 ureg->system_value[i].index, 1441 ureg->system_value[i].semantic_name, 1442 ureg->system_value[i].semantic_index, 1443 TGSI_WRITEMASK_XYZW); 1444 } 1445 1446 for (i = 0; i < ureg->nr_outputs; i++) { 1447 emit_decl_semantic(ureg, 1448 TGSI_FILE_OUTPUT, 1449 i, 1450 ureg->output[i].semantic_name, 1451 ureg->output[i].semantic_index, 1452 ureg->output[i].usage_mask); 1453 } 1454 1455 for (i = 0; i < ureg->nr_samplers; i++) { 1456 emit_decl_range( ureg, 1457 TGSI_FILE_SAMPLER, 1458 ureg->sampler[i].Index, 1 ); 1459 } 1460 1461 for (i = 0; i < ureg->nr_sampler_views; i++) { 1462 emit_decl_sampler_view(ureg, 1463 ureg->sampler_view[i].index, 1464 ureg->sampler_view[i].target, 1465 ureg->sampler_view[i].return_type_x, 1466 ureg->sampler_view[i].return_type_y, 1467 ureg->sampler_view[i].return_type_z, 1468 ureg->sampler_view[i].return_type_w); 1469 } 1470 1471 if (ureg->const_decls.nr_constant_ranges) { 1472 for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) { 1473 emit_decl_range(ureg, 1474 TGSI_FILE_CONSTANT, 1475 ureg->const_decls.constant_range[i].first, 1476 ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1); 1477 } 1478 } 1479 1480 for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { 1481 struct const_decl *decl = &ureg->const_decls2D[i]; 1482 1483 if (decl->nr_constant_ranges) { 1484 uint j; 1485 1486 for (j = 0; j < decl->nr_constant_ranges; j++) { 1487 emit_decl_range2D(ureg, 1488 TGSI_FILE_CONSTANT, 1489 decl->constant_range[j].first, 1490 decl->constant_range[j].last, 1491 i); 1492 } 1493 } 1494 } 1495 1496 if (ureg->nr_temps) { 1497 emit_decl_range( ureg, 1498 TGSI_FILE_TEMPORARY, 1499 0, ureg->nr_temps ); 1500 } 1501 1502 if (ureg->nr_addrs) { 1503 emit_decl_range( ureg, 1504 TGSI_FILE_ADDRESS, 1505 0, ureg->nr_addrs ); 1506 } 1507 1508 if (ureg->nr_preds) { 1509 emit_decl_range(ureg, 1510 TGSI_FILE_PREDICATE, 1511 0, 1512 ureg->nr_preds); 1513 } 1514 1515 for (i = 0; i < ureg->nr_immediates; i++) { 1516 emit_immediate( ureg, 1517 ureg->immediate[i].value.u, 1518 ureg->immediate[i].type ); 1519 } 1520} 1521 1522/* Append the instruction tokens onto the declarations to build a 1523 * contiguous stream suitable to send to the driver. 1524 */ 1525static void copy_instructions( struct ureg_program *ureg ) 1526{ 1527 unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count; 1528 union tgsi_any_token *out = get_tokens( ureg, 1529 DOMAIN_DECL, 1530 nr_tokens ); 1531 1532 memcpy(out, 1533 ureg->domain[DOMAIN_INSN].tokens, 1534 nr_tokens * sizeof out[0] ); 1535} 1536 1537 1538static void 1539fixup_header_size(struct ureg_program *ureg) 1540{ 1541 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 ); 1542 1543 out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2; 1544} 1545 1546 1547static void 1548emit_header( struct ureg_program *ureg ) 1549{ 1550 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); 1551 1552 out[0].header.HeaderSize = 2; 1553 out[0].header.BodySize = 0; 1554 1555 out[1].processor.Processor = ureg->processor; 1556 out[1].processor.Padding = 0; 1557} 1558 1559 1560const struct tgsi_token *ureg_finalize( struct ureg_program *ureg ) 1561{ 1562 const struct tgsi_token *tokens; 1563 1564 emit_header( ureg ); 1565 emit_decls( ureg ); 1566 copy_instructions( ureg ); 1567 fixup_header_size( ureg ); 1568 1569 if (ureg->domain[0].tokens == error_tokens || 1570 ureg->domain[1].tokens == error_tokens) { 1571 debug_printf("%s: error in generated shader\n", __FUNCTION__); 1572 assert(0); 1573 return NULL; 1574 } 1575 1576 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; 1577 1578 if (0) { 1579 debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__, 1580 ureg->domain[DOMAIN_DECL].count); 1581 tgsi_dump( tokens, 0 ); 1582 } 1583 1584#if DEBUG 1585 if (tokens && !tgsi_sanity_check(tokens)) { 1586 debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n"); 1587 tgsi_dump(tokens, 0); 1588 assert(0); 1589 } 1590#endif 1591 1592 1593 return tokens; 1594} 1595 1596 1597void *ureg_create_shader( struct ureg_program *ureg, 1598 struct pipe_context *pipe, 1599 const struct pipe_stream_output_info *so ) 1600{ 1601 struct pipe_shader_state state; 1602 1603 state.tokens = ureg_finalize(ureg); 1604 if(!state.tokens) 1605 return NULL; 1606 1607 if (so) 1608 state.stream_output = *so; 1609 else 1610 memset(&state.stream_output, 0, sizeof(state.stream_output)); 1611 1612 if (ureg->processor == TGSI_PROCESSOR_VERTEX) 1613 return pipe->create_vs_state( pipe, &state ); 1614 else 1615 return pipe->create_fs_state( pipe, &state ); 1616} 1617 1618 1619const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg, 1620 unsigned *nr_tokens ) 1621{ 1622 const struct tgsi_token *tokens; 1623 1624 ureg_finalize(ureg); 1625 1626 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; 1627 1628 if (nr_tokens) 1629 *nr_tokens = ureg->domain[DOMAIN_DECL].size; 1630 1631 ureg->domain[DOMAIN_DECL].tokens = 0; 1632 ureg->domain[DOMAIN_DECL].size = 0; 1633 ureg->domain[DOMAIN_DECL].order = 0; 1634 ureg->domain[DOMAIN_DECL].count = 0; 1635 1636 return tokens; 1637} 1638 1639 1640void ureg_free_tokens( const struct tgsi_token *tokens ) 1641{ 1642 FREE((struct tgsi_token *)tokens); 1643} 1644 1645 1646struct ureg_program *ureg_create( unsigned processor ) 1647{ 1648 struct ureg_program *ureg = CALLOC_STRUCT( ureg_program ); 1649 if (ureg == NULL) 1650 return NULL; 1651 1652 ureg->processor = processor; 1653 ureg->property_gs_input_prim = ~0; 1654 ureg->property_gs_output_prim = ~0; 1655 ureg->property_gs_max_vertices = ~0; 1656 1657 ureg->free_temps = util_bitmask_create(); 1658 if (ureg->free_temps == NULL) 1659 goto fail; 1660 1661 return ureg; 1662 1663fail: 1664 FREE(ureg); 1665 return NULL; 1666} 1667 1668 1669void ureg_destroy( struct ureg_program *ureg ) 1670{ 1671 unsigned i; 1672 1673 for (i = 0; i < Elements(ureg->domain); i++) { 1674 if (ureg->domain[i].tokens && 1675 ureg->domain[i].tokens != error_tokens) 1676 FREE(ureg->domain[i].tokens); 1677 } 1678 1679 util_bitmask_destroy(ureg->free_temps); 1680 1681 FREE(ureg); 1682} 1683