00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "pipe/p_context.h"
00030 #include "pipe/p_state.h"
00031 #include "tgsi/tgsi_ureg.h"
00032 #include "tgsi/tgsi_info.h"
00033 #include "tgsi/tgsi_dump.h"
00034 #include "util/u_memory.h"
00035 #include "util/u_math.h"
00036
00037 union tgsi_any_token {
00038 struct tgsi_version version;
00039 struct tgsi_header header;
00040 struct tgsi_processor processor;
00041 struct tgsi_token token;
00042 struct tgsi_declaration decl;
00043 struct tgsi_declaration_range decl_range;
00044 struct tgsi_declaration_semantic decl_semantic;
00045 struct tgsi_immediate imm;
00046 struct tgsi_immediate_float32 imm_data;
00047 struct tgsi_instruction insn;
00048 struct tgsi_instruction_ext_nv insn_ext_nv;
00049 struct tgsi_instruction_ext_label insn_ext_label;
00050 struct tgsi_instruction_ext_texture insn_ext_texture;
00051 struct tgsi_instruction_ext_predicate insn_ext_predicate;
00052 struct tgsi_src_register src;
00053 struct tgsi_src_register_ext_swz src_ext_swz;
00054 struct tgsi_src_register_ext_mod src_ext_mod;
00055 struct tgsi_dimension dim;
00056 struct tgsi_dst_register dst;
00057 struct tgsi_dst_register_ext_concode dst_ext_code;
00058 struct tgsi_dst_register_ext_modulate dst_ext_mod;
00059 struct tgsi_dst_register_ext_predicate dst_ext_pred;
00060 unsigned value;
00061 };
00062
00063
00064 struct ureg_tokens {
00065 union tgsi_any_token *tokens;
00066 unsigned size;
00067 unsigned order;
00068 unsigned count;
00069 };
00070
00071 #define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
00072 #define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS
00073 #define UREG_MAX_IMMEDIATE 32
00074 #define UREG_MAX_TEMP 256
00075 #define UREG_MAX_ADDR 2
00076
00077 #define DOMAIN_DECL 0
00078 #define DOMAIN_INSN 1
00079
00080 struct ureg_program
00081 {
00082 unsigned processor;
00083 struct pipe_context *pipe;
00084
00085 struct {
00086 unsigned semantic_name;
00087 unsigned semantic_index;
00088 unsigned interp;
00089 } input[UREG_MAX_INPUT];
00090 unsigned nr_inputs;
00091
00092 struct {
00093 unsigned semantic_name;
00094 unsigned semantic_index;
00095 } output[UREG_MAX_OUTPUT];
00096 unsigned nr_outputs;
00097
00098 struct {
00099 float v[4];
00100 unsigned nr;
00101 } immediate[UREG_MAX_IMMEDIATE];
00102 unsigned nr_immediates;
00103
00104 struct ureg_src sampler[PIPE_MAX_SAMPLERS];
00105 unsigned nr_samplers;
00106
00107 unsigned temps_active[UREG_MAX_TEMP / 32];
00108 unsigned nr_temps;
00109
00110 unsigned nr_addrs;
00111
00112 unsigned nr_constants;
00113 unsigned nr_instructions;
00114
00115 struct ureg_tokens domain[2];
00116 };
00117
00118 static union tgsi_any_token error_tokens[32];
00119
00120 static void tokens_error( struct ureg_tokens *tokens )
00121 {
00122 tokens->tokens = error_tokens;
00123 tokens->size = Elements(error_tokens);
00124 tokens->count = 0;
00125 }
00126
00127
00128 static void tokens_expand( struct ureg_tokens *tokens,
00129 unsigned count )
00130 {
00131 unsigned old_size = tokens->size * sizeof(unsigned);
00132
00133 if (tokens->tokens == error_tokens)
00134 goto fail;
00135
00136 while (tokens->count + count > tokens->size) {
00137 tokens->size = (1 << ++tokens->order);
00138 }
00139
00140 tokens->tokens = REALLOC(tokens->tokens,
00141 old_size,
00142 tokens->size * sizeof(unsigned));
00143 if (tokens->tokens == NULL)
00144 goto fail;
00145
00146 return;
00147
00148 fail:
00149 tokens_error(tokens);
00150 }
00151
00152 static void set_bad( struct ureg_program *ureg )
00153 {
00154 tokens_error(&ureg->domain[0]);
00155 }
00156
00157
00158
00159 static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
00160 unsigned domain,
00161 unsigned count )
00162 {
00163 struct ureg_tokens *tokens = &ureg->domain[domain];
00164 union tgsi_any_token *result;
00165
00166 if (tokens->count + count > tokens->size)
00167 tokens_expand(tokens, count);
00168
00169 result = &tokens->tokens[tokens->count];
00170 tokens->count += count;
00171 return result;
00172 }
00173
00174
00175 static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
00176 unsigned domain,
00177 unsigned nr )
00178 {
00179 if (ureg->domain[domain].tokens == error_tokens)
00180 return &error_tokens[0];
00181
00182 return &ureg->domain[domain].tokens[nr];
00183 }
00184
00185
00186
00187 static INLINE struct ureg_dst
00188 ureg_dst_register( unsigned file,
00189 unsigned index )
00190 {
00191 struct ureg_dst dst;
00192
00193 dst.File = file;
00194 dst.WriteMask = TGSI_WRITEMASK_XYZW;
00195 dst.Indirect = 0;
00196 dst.IndirectIndex = 0;
00197 dst.IndirectSwizzle = 0;
00198 dst.Saturate = 0;
00199 dst.Index = index;
00200 dst.Pad1 = 0;
00201 dst.Pad2 = 0;
00202
00203 return dst;
00204 }
00205
00206 static INLINE struct ureg_src
00207 ureg_src_register( unsigned file,
00208 unsigned index )
00209 {
00210 struct ureg_src src;
00211
00212 src.File = file;
00213 src.SwizzleX = TGSI_SWIZZLE_X;
00214 src.SwizzleY = TGSI_SWIZZLE_Y;
00215 src.SwizzleZ = TGSI_SWIZZLE_Z;
00216 src.SwizzleW = TGSI_SWIZZLE_W;
00217 src.Pad = 0;
00218 src.Indirect = 0;
00219 src.IndirectIndex = 0;
00220 src.IndirectSwizzle = 0;
00221 src.Absolute = 0;
00222 src.Index = index;
00223 src.Negate = 0;
00224
00225 return src;
00226 }
00227
00228
00229
00230
00231 static struct ureg_src
00232 ureg_DECL_input( struct ureg_program *ureg,
00233 unsigned name,
00234 unsigned index,
00235 unsigned interp_mode )
00236 {
00237 unsigned i;
00238
00239 for (i = 0; i < ureg->nr_inputs; i++) {
00240 if (ureg->input[i].semantic_name == name &&
00241 ureg->input[i].semantic_index == index)
00242 goto out;
00243 }
00244
00245 if (ureg->nr_inputs < UREG_MAX_INPUT) {
00246 ureg->input[i].semantic_name = name;
00247 ureg->input[i].semantic_index = index;
00248 ureg->input[i].interp = interp_mode;
00249 ureg->nr_inputs++;
00250 }
00251 else {
00252 set_bad( ureg );
00253 }
00254
00255 out:
00256 return ureg_src_register( TGSI_FILE_INPUT, i );
00257 }
00258
00259
00260
00261 struct ureg_src
00262 ureg_DECL_fs_input( struct ureg_program *ureg,
00263 unsigned name,
00264 unsigned index,
00265 unsigned interp )
00266 {
00267 assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
00268 return ureg_DECL_input( ureg, name, index, interp );
00269 }
00270
00271
00272 struct ureg_src
00273 ureg_DECL_vs_input( struct ureg_program *ureg,
00274 unsigned name,
00275 unsigned index )
00276 {
00277 assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
00278 return ureg_DECL_input( ureg, name, index, TGSI_INTERPOLATE_CONSTANT );
00279 }
00280
00281
00282 struct ureg_dst
00283 ureg_DECL_output( struct ureg_program *ureg,
00284 unsigned name,
00285 unsigned index )
00286 {
00287 unsigned i;
00288
00289 for (i = 0; i < ureg->nr_outputs; i++) {
00290 if (ureg->output[i].semantic_name == name &&
00291 ureg->output[i].semantic_index == index)
00292 goto out;
00293 }
00294
00295 if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
00296 ureg->output[i].semantic_name = name;
00297 ureg->output[i].semantic_index = index;
00298 ureg->nr_outputs++;
00299 }
00300 else {
00301 set_bad( ureg );
00302 }
00303
00304 out:
00305 return ureg_dst_register( TGSI_FILE_OUTPUT, i );
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 struct ureg_src ureg_DECL_constant(struct ureg_program *ureg )
00317 {
00318 return ureg_src_register( TGSI_FILE_CONSTANT, ureg->nr_constants++ );
00319 }
00320
00321
00322
00323
00324
00325 struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
00326 {
00327 unsigned i;
00328
00329 for (i = 0; i < UREG_MAX_TEMP; i += 32) {
00330 int bit = ffs(~ureg->temps_active[i/32]);
00331 if (bit != 0) {
00332 i += bit - 1;
00333 goto out;
00334 }
00335 }
00336
00337
00338
00339 i = ureg->nr_temps++;
00340
00341 out:
00342 if (i < UREG_MAX_TEMP)
00343 ureg->temps_active[i/32] |= 1 << (i % 32);
00344
00345 if (i >= ureg->nr_temps)
00346 ureg->nr_temps = i + 1;
00347
00348 return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
00349 }
00350
00351
00352 void ureg_release_temporary( struct ureg_program *ureg,
00353 struct ureg_dst tmp )
00354 {
00355 if(tmp.File == TGSI_FILE_TEMPORARY)
00356 if (tmp.Index < UREG_MAX_TEMP)
00357 ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32));
00358 }
00359
00360
00361
00362
00363 struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
00364 {
00365 if (ureg->nr_addrs < UREG_MAX_ADDR)
00366 return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
00367
00368 assert( 0 );
00369 return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
00370 }
00371
00372
00373
00374 struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
00375 unsigned nr )
00376 {
00377 unsigned i;
00378
00379 for (i = 0; i < ureg->nr_samplers; i++)
00380 if (ureg->sampler[i].Index == nr)
00381 return ureg->sampler[i];
00382
00383 if (i < PIPE_MAX_SAMPLERS) {
00384 ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
00385 ureg->nr_samplers++;
00386 return ureg->sampler[i];
00387 }
00388
00389 assert( 0 );
00390 return ureg->sampler[0];
00391 }
00392
00393
00394
00395
00396 static int match_or_expand_immediate( const float *v,
00397 unsigned nr,
00398 float *v2,
00399 unsigned *nr2,
00400 unsigned *swizzle )
00401 {
00402 unsigned i, j;
00403
00404 *swizzle = 0;
00405
00406 for (i = 0; i < nr; i++) {
00407 boolean found = FALSE;
00408
00409 for (j = 0; j < *nr2 && !found; j++) {
00410 if (v[i] == v2[j]) {
00411 *swizzle |= j << (i * 2);
00412 found = TRUE;
00413 }
00414 }
00415
00416 if (!found) {
00417 if (*nr2 >= 4)
00418 return FALSE;
00419
00420 v2[*nr2] = v[i];
00421 *swizzle |= *nr2 << (i * 2);
00422 (*nr2)++;
00423 }
00424 }
00425
00426 return TRUE;
00427 }
00428
00429
00430
00431
00432 struct ureg_src ureg_DECL_immediate( struct ureg_program *ureg,
00433 const float *v,
00434 unsigned nr )
00435 {
00436 unsigned i, j;
00437 unsigned swizzle;
00438
00439
00440
00441
00442
00443 for (i = 0; i < ureg->nr_immediates; i++) {
00444 if (match_or_expand_immediate( v,
00445 nr,
00446 ureg->immediate[i].v,
00447 &ureg->immediate[i].nr,
00448 &swizzle ))
00449 goto out;
00450 }
00451
00452 if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
00453 i = ureg->nr_immediates++;
00454 if (match_or_expand_immediate( v,
00455 nr,
00456 ureg->immediate[i].v,
00457 &ureg->immediate[i].nr,
00458 &swizzle ))
00459 goto out;
00460 }
00461
00462 set_bad( ureg );
00463
00464 out:
00465
00466
00467
00468 for (j = nr; j < 4; j++)
00469 swizzle |= (swizzle & 0x3) << (j * 2);
00470
00471 return ureg_swizzle( ureg_src_register( TGSI_FILE_IMMEDIATE, i ),
00472 (swizzle >> 0) & 0x3,
00473 (swizzle >> 2) & 0x3,
00474 (swizzle >> 4) & 0x3,
00475 (swizzle >> 6) & 0x3);
00476 }
00477
00478
00479 void
00480 ureg_emit_src( struct ureg_program *ureg,
00481 struct ureg_src src )
00482 {
00483 unsigned size = (1 +
00484 (src.Absolute ? 1 : 0) +
00485 (src.Indirect ? 1 : 0));
00486
00487 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
00488 unsigned n = 0;
00489
00490 assert(src.File != TGSI_FILE_NULL);
00491 assert(src.File != TGSI_FILE_OUTPUT);
00492 assert(src.File < TGSI_FILE_COUNT);
00493
00494 out[n].value = 0;
00495 out[n].src.File = src.File;
00496 out[n].src.SwizzleX = src.SwizzleX;
00497 out[n].src.SwizzleY = src.SwizzleY;
00498 out[n].src.SwizzleZ = src.SwizzleZ;
00499 out[n].src.SwizzleW = src.SwizzleW;
00500 out[n].src.Index = src.Index;
00501 out[n].src.Negate = src.Negate;
00502 n++;
00503
00504 if (src.Absolute) {
00505 out[0].src.Extended = 1;
00506 out[0].src.Negate = 0;
00507 out[n].value = 0;
00508 out[n].src_ext_mod.Type = TGSI_SRC_REGISTER_EXT_TYPE_MOD;
00509 out[n].src_ext_mod.Absolute = 1;
00510 out[n].src_ext_mod.Negate = src.Negate;
00511 n++;
00512 }
00513
00514 if (src.Indirect) {
00515 out[0].src.Indirect = 1;
00516 out[n].value = 0;
00517 out[n].src.File = TGSI_FILE_ADDRESS;
00518 out[n].src.SwizzleX = src.IndirectSwizzle;
00519 out[n].src.SwizzleY = src.IndirectSwizzle;
00520 out[n].src.SwizzleZ = src.IndirectSwizzle;
00521 out[n].src.SwizzleW = src.IndirectSwizzle;
00522 out[n].src.Index = src.IndirectIndex;
00523 n++;
00524 }
00525
00526 assert(n == size);
00527 }
00528
00529
00530 void
00531 ureg_emit_dst( struct ureg_program *ureg,
00532 struct ureg_dst dst )
00533 {
00534 unsigned size = (1 +
00535 (dst.Indirect ? 1 : 0));
00536
00537 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
00538 unsigned n = 0;
00539
00540 assert(dst.File != TGSI_FILE_NULL);
00541 assert(dst.File != TGSI_FILE_CONSTANT);
00542 assert(dst.File != TGSI_FILE_INPUT);
00543 assert(dst.File != TGSI_FILE_SAMPLER);
00544 assert(dst.File != TGSI_FILE_IMMEDIATE);
00545 assert(dst.File < TGSI_FILE_COUNT);
00546
00547 out[n].value = 0;
00548 out[n].dst.File = dst.File;
00549 out[n].dst.WriteMask = dst.WriteMask;
00550 out[n].dst.Indirect = dst.Indirect;
00551 out[n].dst.Index = dst.Index;
00552 n++;
00553
00554 if (dst.Indirect) {
00555 out[n].value = 0;
00556 out[n].src.File = TGSI_FILE_ADDRESS;
00557 out[n].src.SwizzleX = dst.IndirectSwizzle;
00558 out[n].src.SwizzleY = dst.IndirectSwizzle;
00559 out[n].src.SwizzleZ = dst.IndirectSwizzle;
00560 out[n].src.SwizzleW = dst.IndirectSwizzle;
00561 out[n].src.Index = dst.IndirectIndex;
00562 n++;
00563 }
00564
00565 assert(n == size);
00566 }
00567
00568
00569
00570 unsigned
00571 ureg_emit_insn(struct ureg_program *ureg,
00572 unsigned opcode,
00573 boolean saturate,
00574 unsigned num_dst,
00575 unsigned num_src )
00576 {
00577 union tgsi_any_token *out;
00578
00579 out = get_tokens( ureg, DOMAIN_INSN, 1 );
00580 out[0].value = 0;
00581 out[0].insn.Type = TGSI_TOKEN_TYPE_INSTRUCTION;
00582 out[0].insn.Size = 0;
00583 out[0].insn.Opcode = opcode;
00584 out[0].insn.Saturate = saturate;
00585 out[0].insn.NumDstRegs = num_dst;
00586 out[0].insn.NumSrcRegs = num_src;
00587 out[0].insn.Padding = 0;
00588 out[0].insn.Extended = 0;
00589
00590 ureg->nr_instructions++;
00591
00592 return ureg->domain[DOMAIN_INSN].count - 1;
00593 }
00594
00595
00596 void
00597 ureg_emit_label(struct ureg_program *ureg,
00598 unsigned insn_token,
00599 unsigned *label_token )
00600 {
00601 union tgsi_any_token *out, *insn;
00602
00603 if(!label_token)
00604 return;
00605
00606 out = get_tokens( ureg, DOMAIN_INSN, 1 );
00607 insn = retrieve_token( ureg, DOMAIN_INSN, insn_token );
00608
00609 insn->insn.Extended = 1;
00610
00611 out[0].value = 0;
00612 out[0].insn_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL;
00613
00614 *label_token = ureg->domain[DOMAIN_INSN].count - 1;
00615 }
00616
00617
00618
00619
00620 unsigned
00621 ureg_get_instruction_number( struct ureg_program *ureg )
00622 {
00623 return ureg->nr_instructions;
00624 }
00625
00626
00627
00628
00629 void
00630 ureg_fixup_label(struct ureg_program *ureg,
00631 unsigned label_token,
00632 unsigned instruction_number )
00633 {
00634 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
00635
00636 assert(out->insn_ext_label.Type == TGSI_INSTRUCTION_EXT_TYPE_LABEL);
00637 out->insn_ext_label.Label = instruction_number;
00638 }
00639
00640
00641 void
00642 ureg_emit_texture(struct ureg_program *ureg,
00643 unsigned insn_token,
00644 unsigned target )
00645 {
00646 union tgsi_any_token *out, *insn;
00647
00648 out = get_tokens( ureg, DOMAIN_INSN, 1 );
00649 insn = retrieve_token( ureg, DOMAIN_INSN, insn_token );
00650
00651 insn->insn.Extended = 1;
00652
00653 out[0].value = 0;
00654 out[0].insn_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE;
00655 out[0].insn_ext_texture.Texture = target;
00656 }
00657
00658
00659 void
00660 ureg_fixup_insn_size(struct ureg_program *ureg,
00661 unsigned insn )
00662 {
00663 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
00664
00665 assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
00666 out->insn.Size = ureg->domain[DOMAIN_INSN].count - insn - 1;
00667 }
00668
00669
00670 void
00671 ureg_insn(struct ureg_program *ureg,
00672 unsigned opcode,
00673 const struct ureg_dst *dst,
00674 unsigned nr_dst,
00675 const struct ureg_src *src,
00676 unsigned nr_src )
00677 {
00678 unsigned insn, i;
00679 boolean saturate;
00680
00681 #ifdef DEBUG
00682 {
00683 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
00684 assert(info);
00685 if(info) {
00686 assert(nr_dst == info->num_dst);
00687 assert(nr_src == info->num_src);
00688 }
00689 }
00690 #endif
00691
00692 saturate = nr_dst ? dst[0].Saturate : FALSE;
00693
00694 insn = ureg_emit_insn( ureg, opcode, saturate, nr_dst, nr_src );
00695
00696 for (i = 0; i < nr_dst; i++)
00697 ureg_emit_dst( ureg, dst[i] );
00698
00699 for (i = 0; i < nr_src; i++)
00700 ureg_emit_src( ureg, src[i] );
00701
00702 ureg_fixup_insn_size( ureg, insn );
00703 }
00704
00705
00706
00707 static void emit_decl( struct ureg_program *ureg,
00708 unsigned file,
00709 unsigned index,
00710 unsigned semantic_name,
00711 unsigned semantic_index,
00712 unsigned interp )
00713 {
00714 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 );
00715
00716 out[0].value = 0;
00717 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
00718 out[0].decl.Size = 3;
00719 out[0].decl.File = file;
00720 out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
00721 out[0].decl.Interpolate = interp;
00722 out[0].decl.Semantic = 1;
00723
00724 out[1].value = 0;
00725 out[1].decl_range.First =
00726 out[1].decl_range.Last = index;
00727
00728 out[2].value = 0;
00729 out[2].decl_semantic.SemanticName = semantic_name;
00730 out[2].decl_semantic.SemanticIndex = semantic_index;
00731
00732 }
00733
00734
00735 static void emit_decl_range( struct ureg_program *ureg,
00736 unsigned file,
00737 unsigned first,
00738 unsigned count )
00739 {
00740 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
00741
00742 out[0].value = 0;
00743 out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
00744 out[0].decl.Size = 2;
00745 out[0].decl.File = file;
00746 out[0].decl.UsageMask = 0xf;
00747 out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT;
00748 out[0].decl.Semantic = 0;
00749
00750 out[1].value = 0;
00751 out[1].decl_range.First = first;
00752 out[1].decl_range.Last = first + count - 1;
00753 }
00754
00755 static void emit_immediate( struct ureg_program *ureg,
00756 const float *v )
00757 {
00758 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
00759
00760 out[0].value = 0;
00761 out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
00762 out[0].imm.Size = 5;
00763 out[0].imm.DataType = TGSI_IMM_FLOAT32;
00764 out[0].imm.Padding = 0;
00765 out[0].imm.Extended = 0;
00766
00767 out[1].imm_data.Float = v[0];
00768 out[2].imm_data.Float = v[1];
00769 out[3].imm_data.Float = v[2];
00770 out[4].imm_data.Float = v[3];
00771 }
00772
00773
00774
00775
00776 static void emit_decls( struct ureg_program *ureg )
00777 {
00778 unsigned i;
00779
00780 for (i = 0; i < ureg->nr_inputs; i++) {
00781 emit_decl( ureg,
00782 TGSI_FILE_INPUT,
00783 i,
00784 ureg->input[i].semantic_name,
00785 ureg->input[i].semantic_index,
00786 ureg->input[i].interp );
00787 }
00788
00789 for (i = 0; i < ureg->nr_outputs; i++) {
00790 emit_decl( ureg,
00791 TGSI_FILE_OUTPUT,
00792 i,
00793 ureg->output[i].semantic_name,
00794 ureg->output[i].semantic_index,
00795 TGSI_INTERPOLATE_CONSTANT );
00796 }
00797
00798 for (i = 0; i < ureg->nr_samplers; i++) {
00799 emit_decl_range( ureg,
00800 TGSI_FILE_SAMPLER,
00801 ureg->sampler[i].Index, 1 );
00802 }
00803
00804 if (ureg->nr_constants) {
00805 emit_decl_range( ureg,
00806 TGSI_FILE_CONSTANT,
00807 0, ureg->nr_constants );
00808 }
00809
00810 if (ureg->nr_temps) {
00811 emit_decl_range( ureg,
00812 TGSI_FILE_TEMPORARY,
00813 0, ureg->nr_temps );
00814 }
00815
00816 if (ureg->nr_addrs) {
00817 emit_decl_range( ureg,
00818 TGSI_FILE_ADDRESS,
00819 0, ureg->nr_addrs );
00820 }
00821
00822 for (i = 0; i < ureg->nr_immediates; i++) {
00823 emit_immediate( ureg,
00824 ureg->immediate[i].v );
00825 }
00826 }
00827
00828
00829
00830
00831 static void copy_instructions( struct ureg_program *ureg )
00832 {
00833 unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
00834 union tgsi_any_token *out = get_tokens( ureg,
00835 DOMAIN_DECL,
00836 nr_tokens );
00837
00838 memcpy(out,
00839 ureg->domain[DOMAIN_INSN].tokens,
00840 nr_tokens * sizeof out[0] );
00841 }
00842
00843
00844 static void
00845 fixup_header_size(struct ureg_program *ureg)
00846 {
00847 union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 1 );
00848
00849 out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 3;
00850 }
00851
00852
00853 static void
00854 emit_header( struct ureg_program *ureg )
00855 {
00856 union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 );
00857
00858 out[0].version.MajorVersion = 1;
00859 out[0].version.MinorVersion = 1;
00860 out[0].version.Padding = 0;
00861
00862 out[1].header.HeaderSize = 2;
00863 out[1].header.BodySize = 0;
00864
00865 out[2].processor.Processor = ureg->processor;
00866 out[2].processor.Padding = 0;
00867 }
00868
00869
00870 const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
00871 {
00872 const struct tgsi_token *tokens;
00873
00874 emit_header( ureg );
00875 emit_decls( ureg );
00876 copy_instructions( ureg );
00877 fixup_header_size( ureg );
00878
00879 if (ureg->domain[0].tokens == error_tokens ||
00880 ureg->domain[1].tokens == error_tokens) {
00881 debug_printf("%s: error in generated shader\n", __FUNCTION__);
00882 assert(0);
00883 return NULL;
00884 }
00885
00886 tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
00887
00888 if (0) {
00889 debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
00890 ureg->domain[DOMAIN_DECL].count);
00891 tgsi_dump( tokens, 0 );
00892 }
00893
00894 return tokens;
00895 }
00896
00897
00898 void *ureg_create_shader( struct ureg_program *ureg,
00899 struct pipe_context *pipe )
00900 {
00901 struct pipe_shader_state state;
00902
00903 state.tokens = ureg_finalize(ureg);
00904 if(!state.tokens)
00905 return NULL;
00906
00907 if (ureg->processor == TGSI_PROCESSOR_VERTEX)
00908 return pipe->create_vs_state( pipe, &state );
00909 else
00910 return pipe->create_fs_state( pipe, &state );
00911 }
00912
00913
00914
00915
00916 struct ureg_program *ureg_create( unsigned processor )
00917 {
00918 struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
00919 if (ureg == NULL)
00920 return NULL;
00921
00922 ureg->processor = processor;
00923 return ureg;
00924 }
00925
00926
00927 void ureg_destroy( struct ureg_program *ureg )
00928 {
00929 unsigned i;
00930
00931 for (i = 0; i < Elements(ureg->domain); i++) {
00932 if (ureg->domain[i].tokens &&
00933 ureg->domain[i].tokens != error_tokens)
00934 FREE(ureg->domain[i].tokens);
00935 }
00936
00937 FREE(ureg);
00938 }