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