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