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