tgsi_ureg.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2009 VMware, Inc.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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 /* Returns a new constant register.  Keep track of which have been
00310  * referred to so that we can emit decls later.
00311  *
00312  * There is nothing in this code to bind this constant to any tracked
00313  * value or manage any constant_buffer contents -- that's the
00314  * resposibility of the calling code.
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 /* Allocate a new temporary.  Temporaries greater than UREG_MAX_TEMP
00323  * are legal, but will not be released.
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    /* No reusable temps, so allocate a new one:
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 /* Allocate a new address register.
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 /* Allocate a new sampler.
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    /* Could do a first pass where we examine all existing immediates
00440     * without expanding.
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    /* Make sure that all referenced elements are from this immediate.
00466     * Has the effect of making size-one immediates into scalars.
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 /* Will return a number which can be used in a label to point to the
00618  * next instruction to be emitted.
00619  */
00620 unsigned
00621 ureg_get_instruction_number( struct ureg_program *ureg )
00622 {
00623    return ureg->nr_instructions;
00624 }
00625 
00626 /* Patch a given label (expressed as a token number) to point to a
00627  * given instruction (expressed as an instruction number).
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; /* FIXME! */
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 /* Append the instruction tokens onto the declarations to build a
00829  * contiguous stream suitable to send to the driver.
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 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4