st_atom_shader.c File Reference

Include dependency graph for st_atom_shader.c:

Go to the source code of this file.

Data Structures

struct  translated_vertex_program
 State validation for vertex/fragment shaders. More...

Functions

static GLint vp_out_to_fp_in (GLuint vertResult)
 Given a vertex program output attribute, return the corresponding fragment program input attribute.
static struct
translated_vertex_program
find_translated_vp (struct st_context *st, struct st_vertex_program *stvp, struct st_fragment_program *stfp)
 Find a translated vertex program that corresponds to stvp and has outputs matched to stfp's inputs.
void st_free_translated_vertex_programs (struct st_context *st, struct translated_vertex_program *xvp)
static void * get_passthrough_fs (struct st_context *st)
static void update_linkage (struct st_context *st)

Variables

struct st_tracked_state st_update_shader


Function Documentation

static struct translated_vertex_program* find_translated_vp ( struct st_context st,
struct st_vertex_program stvp,
struct st_fragment_program stfp 
) [static, read]

Find a translated vertex program that corresponds to stvp and has outputs matched to stfp's inputs.

This performs vertex and fragment translation (to TGSI) when needed.

Definition at line 124 of file st_atom_shader.c.

References assert, st_vertex_program::Base, st_fragment_program::Base, CALLOC_STRUCT, translated_vertex_program::frag_inputs, st_fragment_program::input_map, st_fragment_program::input_semantic_index, st_fragment_program::input_semantic_name, st_fragment_program::input_to_slot, translated_vertex_program::master, MAX2, translated_vertex_program::next, st_fragment_program::num_input_slots, translated_vertex_program::output_to_semantic_index, translated_vertex_program::output_to_semantic_name, translated_vertex_program::output_to_slot, st_vertex_program::serialNo, translated_vertex_program::serialNo, st_translate_fragment_program(), st_translate_vertex_program(), st_fragment_program::state, TGSI_SEMANTIC_COLOR, TGSI_SEMANTIC_COUNT, TGSI_SEMANTIC_GENERIC, TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_PSIZE, pipe_shader_state::tokens, st_fragment_program::vertex_programs, translated_vertex_program::vp, and vp_out_to_fp_in().

00127 {
00128    static const GLuint UNUSED = ~0;
00129    struct translated_vertex_program *xvp;
00130    const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
00131 
00132    /*
00133     * Translate fragment program if needed.
00134     */
00135    if (!stfp->state.tokens) {
00136       GLuint inAttr, numIn = 0;
00137 
00138       for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
00139          if (fragInputsRead & (1 << inAttr)) {
00140             stfp->input_to_slot[inAttr] = numIn;
00141             numIn++;
00142          }
00143          else {
00144             stfp->input_to_slot[inAttr] = UNUSED;
00145          }
00146       }
00147 
00148       stfp->num_input_slots = numIn;
00149 
00150       assert(stfp->Base.Base.NumInstructions > 1);
00151 
00152       st_translate_fragment_program(st, stfp, stfp->input_to_slot);
00153    }
00154 
00155 
00156    /* See if we've got a translated vertex program whose outputs match
00157     * the fragment program's inputs.
00158     * XXX This could be a hash lookup, using InputsRead as the key.
00159     */
00160    for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
00161       if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
00162          break;
00163       }
00164    }
00165 
00166    /* No?  Allocate translated vp object now */
00167    if (!xvp) {
00168       xvp = CALLOC_STRUCT(translated_vertex_program);
00169       xvp->frag_inputs = fragInputsRead;
00170       xvp->master = stvp;
00171 
00172       xvp->next = stfp->vertex_programs;
00173       stfp->vertex_programs = xvp;
00174    }
00175 
00176    /* See if we need to translate vertex program to TGSI form */
00177    if (xvp->serialNo != stvp->serialNo) {
00178       GLuint outAttr, dummySlot;
00179       const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
00180       GLuint numVpOuts = 0;
00181       GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
00182       GLint maxGeneric;
00183 
00184       /* Compute mapping of vertex program outputs to slots, which depends
00185        * on the fragment program's input->slot mapping.
00186        */
00187       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
00188          /* set defaults: */
00189          xvp->output_to_slot[outAttr] = UNUSED;
00190          xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
00191          xvp->output_to_semantic_index[outAttr] = 99;
00192 
00193          if (outAttr == VERT_RESULT_HPOS) {
00194             /* always put xformed position into slot zero */
00195             xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
00196             xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
00197             xvp->output_to_semantic_index[outAttr] = 0;
00198             numVpOuts++;
00199          }
00200          else if (outputsWritten & (1 << outAttr)) {
00201             /* see if the frag prog wants this vert output */
00202             GLint fpInAttrib = vp_out_to_fp_in(outAttr);
00203             if (fpInAttrib >= 0) {
00204                GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
00205                if (fpInSlot != ~0) {
00206                   /* match this vp output to the fp input */
00207                   GLuint vpOutSlot = stfp->input_map[fpInSlot];
00208                   xvp->output_to_slot[outAttr] = vpOutSlot;
00209                   xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
00210                   xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
00211                   numVpOuts++;
00212                }
00213             }
00214             else if (outAttr == VERT_RESULT_PSIZ)
00215                emitPntSize = GL_TRUE;
00216             else if (outAttr == VERT_RESULT_BFC0)
00217                emitBFC0 = GL_TRUE;
00218             else if (outAttr == VERT_RESULT_BFC1)
00219                emitBFC1 = GL_TRUE;
00220          }
00221 #if 0 /*debug*/
00222          printf("assign vp output_to_slot[%d] = %d\n", outAttr, 
00223                 xvp->output_to_slot[outAttr]);
00224 #endif
00225       }
00226 
00227       /* must do these last */
00228       if (emitPntSize) {
00229          xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
00230          xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
00231          xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
00232       }
00233       if (emitBFC0) {
00234          xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
00235          xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
00236          xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
00237       }
00238       if (emitBFC1) {
00239          xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
00240          xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
00241          xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1;
00242       }
00243 
00244       /* Unneeded vertex program outputs will go to this slot.
00245        * We could use this info to do dead code elimination in the
00246        * vertex program.
00247        */
00248       dummySlot = numVpOuts;
00249 
00250       /* find max GENERIC slot index */
00251       maxGeneric = -1;
00252       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
00253          if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
00254             maxGeneric = MAX2(maxGeneric,
00255                               xvp->output_to_semantic_index[outAttr]);
00256          }
00257       }
00258 
00259       /* Map vert program outputs that aren't used to the dummy slot
00260        * (and an unused generic attribute slot).
00261        */
00262       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
00263          if (outputsWritten & (1 << outAttr)) {
00264             if (xvp->output_to_slot[outAttr] == UNUSED) {
00265                xvp->output_to_slot[outAttr] = dummySlot;
00266                xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
00267                xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
00268             }
00269          }
00270 
00271 #if 0 /*debug*/
00272          printf("vp output_to_slot[%d] = %d\n", outAttr, 
00273                 xvp->output_to_slot[outAttr]);
00274 #endif
00275       }
00276 
00277       assert(stvp->Base.Base.NumInstructions > 1);
00278 
00279       st_translate_vertex_program(st, stvp, xvp->output_to_slot,
00280                                   xvp->output_to_semantic_name,
00281                                   xvp->output_to_semantic_index);
00282 
00283       xvp->vp = stvp;
00284 
00285       /* translated VP is up to date now */
00286       xvp->serialNo = stvp->serialNo;
00287    }
00288 
00289    return xvp;
00290 }

static void* get_passthrough_fs ( struct st_context st  )  [static]

Definition at line 308 of file st_atom_shader.c.

References st_context::passthrough_fs, st_context::pipe, util_free_shader(), and util_make_fragment_passthrough_shader().

00309 {
00310    struct pipe_shader_state shader;
00311 
00312    if (!st->passthrough_fs) {
00313       st->passthrough_fs =
00314          util_make_fragment_passthrough_shader(st->pipe, &shader);
00315 #if 0      /* We actually need to keep the tokens around at this time */
00316       util_free_shader(&shader);
00317 #endif
00318    }
00319 
00320    return st->passthrough_fs;
00321 }

void st_free_translated_vertex_programs ( struct st_context st,
struct translated_vertex_program xvp 
)

Definition at line 294 of file st_atom_shader.c.

References translated_vertex_program::next.

00296 {
00297    struct translated_vertex_program *next;
00298 
00299    while (xvp) {
00300       next = xvp->next;
00301       free(xvp);
00302       xvp = next;
00303    }
00304 }

static void update_linkage ( struct st_context st  )  [static]

Definition at line 325 of file st_atom_shader.c.

References assert, st_fragment_program::Base, st_vertex_program::Base, st_context::cso_context, cso_set_fragment_shader_handle(), cso_set_vertex_shader_handle(), st_context::ctx, st_fragment_program::driver_shader, st_vertex_program::driver_shader, find_translated_vp(), st_context::fp, get_passthrough_fs(), st_context::missing_textures, translated_vertex_program::output_to_slot, st_fragment_program(), st_reference_fragprog(), st_reference_vertprog(), st_vertex_program(), st_context::vertex_result_to_slot, and st_context::vp.

00326 {
00327    struct st_vertex_program *stvp;
00328    struct st_fragment_program *stfp;
00329    struct translated_vertex_program *xvp;
00330 
00331    /* find active shader and params -- Should be covered by
00332     * ST_NEW_VERTEX_PROGRAM
00333     */
00334    assert(st->ctx->VertexProgram._Current);
00335    stvp = st_vertex_program(st->ctx->VertexProgram._Current);
00336    assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
00337 
00338    assert(st->ctx->FragmentProgram._Current);
00339    stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
00340    assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
00341 
00342    xvp = find_translated_vp(st, stvp, stfp);
00343 
00344    st_reference_vertprog(st, &st->vp, stvp);
00345    st_reference_fragprog(st, &st->fp, stfp);
00346 
00347    cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
00348 
00349    if (st->missing_textures) {
00350       /* use a pass-through frag shader that uses no textures */
00351       void *fs = get_passthrough_fs(st);
00352       cso_set_fragment_shader_handle(st->cso_context, fs);
00353    }
00354    else {
00355       cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
00356    }
00357 
00358    st->vertex_result_to_slot = xvp->output_to_slot;
00359 }

static GLint vp_out_to_fp_in ( GLuint  vertResult  )  [static]

Given a vertex program output attribute, return the corresponding fragment program input attribute.

Returns:
-1 for vertex outputs that have no corresponding fragment input

Definition at line 92 of file st_atom_shader.c.

00093 {
00094    if (vertResult >= VERT_RESULT_TEX0 &&
00095        vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
00096       return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
00097 
00098    if (vertResult >= VERT_RESULT_VAR0 &&
00099        vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
00100       return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
00101 
00102    switch (vertResult) {
00103    case VERT_RESULT_HPOS:
00104       return FRAG_ATTRIB_WPOS;
00105    case VERT_RESULT_COL0:
00106       return FRAG_ATTRIB_COL0;
00107    case VERT_RESULT_COL1:
00108       return FRAG_ATTRIB_COL1;
00109    case VERT_RESULT_FOGC:
00110       return FRAG_ATTRIB_FOGC;
00111    default:
00112       /* Back-face colors, edge flags, etc */
00113       return -1;
00114    }
00115 }


Variable Documentation

struct st_tracked_state st_update_shader

Initial value:

 {
   "st_update_shader",                                  
   {                                                    
      0,                                                
       0x4  |  0x2      
   },
   update_linkage                                       
}

Definition at line 362 of file st_atom_shader.c.


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