st_program.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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   * Authors:
00029   *   Keith Whitwell <keith@tungstengraphics.com>
00030   *   Brian Paul
00031   */
00032 
00033 
00034 #include "main/imports.h"
00035 #include "main/mtypes.h"
00036 #include "shader/prog_print.h"
00037 #include "shader/programopt.h"
00038 
00039 #include "pipe/p_context.h"
00040 #include "pipe/p_defines.h"
00041 #include "pipe/p_shader_tokens.h"
00042 #include "draw/draw_context.h"
00043 #include "tgsi/tgsi_dump.h"
00044 
00045 #include "st_context.h"
00046 #include "st_atom.h"
00047 #include "st_program.h"
00048 #include "st_mesa_to_tgsi.h"
00049 #include "cso_cache/cso_context.h"
00050 
00051 
00052 #define ST_MAX_SHADER_TOKENS 4096
00053 
00054 
00055 #define TGSI_DEBUG 0
00056 
00057 
00061 static INLINE void *
00062 mem_dup(const void *src, uint size)
00063 {
00064    void *dup = MALLOC(size);
00065    if (dup)
00066       memcpy(dup, src, size);
00067    return dup;
00068 }
00069 
00070 
00071 
00079 void
00080 st_translate_vertex_program(struct st_context *st,
00081                             struct st_vertex_program *stvp,
00082                             const GLuint outputMapping[],
00083                             const ubyte *outputSemanticName,
00084                             const ubyte *outputSemanticIndex)
00085 {
00086    struct pipe_context *pipe = st->pipe;
00087    struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
00088    GLuint defaultOutputMapping[VERT_RESULT_MAX];
00089    struct pipe_shader_state vs;
00090    GLuint attr, i;
00091    GLuint num_generic = 0;
00092    GLuint num_tokens;
00093 
00094    ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS];
00095    ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS];
00096    uint vs_num_inputs = 0;
00097 
00098    ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
00099    ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
00100    uint vs_num_outputs = 0;
00101 
00102    GLbitfield input_flags[MAX_PROGRAM_INPUTS];
00103    GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
00104 
00105    memset(&vs, 0, sizeof(vs));
00106    memset(input_flags, 0, sizeof(input_flags));
00107    memset(output_flags, 0, sizeof(output_flags));
00108 
00109    if (stvp->Base.IsPositionInvariant)
00110       _mesa_insert_mvp_code(st->ctx, &stvp->Base);
00111 
00112    /*
00113     * Determine number of inputs, the mappings between VERT_ATTRIB_x
00114     * and TGSI generic input indexes, plus input attrib semantic info.
00115     */
00116    for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
00117       if (stvp->Base.Base.InputsRead & (1 << attr)) {
00118          const GLuint slot = vs_num_inputs;
00119 
00120          vs_num_inputs++;
00121 
00122          stvp->input_to_index[attr] = slot;
00123          stvp->index_to_input[slot] = attr;
00124 
00125          switch (attr) {
00126          case VERT_ATTRIB_POS:
00127             vs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
00128             vs_input_semantic_index[slot] = 0;
00129             break;
00130          case VERT_ATTRIB_WEIGHT:
00131             /* fall-through */
00132          case VERT_ATTRIB_NORMAL:
00133             /* just label as a generic */
00134             vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
00135             vs_input_semantic_index[slot] = 0;
00136             break;
00137          case VERT_ATTRIB_COLOR0:
00138             vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
00139             vs_input_semantic_index[slot] = 0;
00140             break;
00141          case VERT_ATTRIB_COLOR1:
00142             vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
00143             vs_input_semantic_index[slot] = 1;
00144             break;
00145          case VERT_ATTRIB_FOG:
00146             vs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
00147             vs_input_semantic_index[slot] = 0;
00148             break;
00149          case VERT_ATTRIB_POINT_SIZE:
00150             vs_input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
00151             vs_input_semantic_index[slot] = 0;
00152             break;
00153          case VERT_ATTRIB_TEX0:
00154          case VERT_ATTRIB_TEX1:
00155          case VERT_ATTRIB_TEX2:
00156          case VERT_ATTRIB_TEX3:
00157          case VERT_ATTRIB_TEX4:
00158          case VERT_ATTRIB_TEX5:
00159          case VERT_ATTRIB_TEX6:
00160          case VERT_ATTRIB_TEX7:
00161             vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
00162             vs_input_semantic_index[slot] = num_generic++;
00163             break;
00164          case VERT_ATTRIB_GENERIC0:
00165          case VERT_ATTRIB_GENERIC1:
00166          case VERT_ATTRIB_GENERIC2:
00167          case VERT_ATTRIB_GENERIC3:
00168          case VERT_ATTRIB_GENERIC4:
00169          case VERT_ATTRIB_GENERIC5:
00170          case VERT_ATTRIB_GENERIC6:
00171          case VERT_ATTRIB_GENERIC7:
00172             assert(attr < VERT_ATTRIB_MAX);
00173             vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
00174             vs_input_semantic_index[slot] = num_generic++;
00175             break;
00176          default:
00177             assert(0);
00178          }
00179 
00180          input_flags[slot] = stvp->Base.Base.InputFlags[attr];
00181       }
00182    }
00183 
00184 #if 0
00185    if (outputMapping && outputSemanticName) {
00186       printf("VERT_RESULT  written  out_slot  semantic_name  semantic_index\n");
00187       for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
00188          printf("    %-2d          %c       %3d          %2d              %2d\n",
00189                 attr, 
00190                 ((stvp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '),
00191                 outputMapping[attr],
00192                 outputSemanticName[attr],
00193                 outputSemanticIndex[attr]);
00194       }
00195    }
00196 #endif
00197 
00198    /* initialize output semantics to defaults */
00199    for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
00200       vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
00201       vs_output_semantic_index[i] = 0;
00202       output_flags[i] = 0x0;
00203    }
00204 
00205    num_generic = 0;
00206    /*
00207     * Determine number of outputs, the (default) output register
00208     * mapping and the semantic information for each output.
00209     */
00210    for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
00211       if (stvp->Base.Base.OutputsWritten & (1 << attr)) {
00212          GLuint slot;
00213 
00214          /* XXX
00215           * Pass in the fragment program's input's semantic info.
00216           * Use the generic semantic indexes from there, instead of
00217           * guessing below.
00218           */
00219 
00220          if (outputMapping) {
00221             slot = outputMapping[attr];
00222             assert(slot != ~0);
00223          }
00224          else {
00225             slot = vs_num_outputs;
00226             vs_num_outputs++;
00227             defaultOutputMapping[attr] = slot;
00228          }
00229 
00230          switch (attr) {
00231          case VERT_RESULT_HPOS:
00232             assert(slot == 0);
00233             vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
00234             vs_output_semantic_index[slot] = 0;
00235             break;
00236          case VERT_RESULT_COL0:
00237             vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
00238             vs_output_semantic_index[slot] = 0;
00239             break;
00240          case VERT_RESULT_COL1:
00241             vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
00242             vs_output_semantic_index[slot] = 1;
00243             break;
00244          case VERT_RESULT_BFC0:
00245             vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
00246             vs_output_semantic_index[slot] = 0;
00247             break;
00248          case VERT_RESULT_BFC1:
00249             vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
00250             vs_output_semantic_index[slot] = 1;
00251             break;
00252          case VERT_RESULT_FOGC:
00253             vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
00254             vs_output_semantic_index[slot] = 0;
00255             break;
00256          case VERT_RESULT_PSIZ:
00257             vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
00258             vs_output_semantic_index[slot] = 0;
00259             break;
00260          case VERT_RESULT_EDGE:
00261             assert(0);
00262             break;
00263          case VERT_RESULT_TEX0:
00264          case VERT_RESULT_TEX1:
00265          case VERT_RESULT_TEX2:
00266          case VERT_RESULT_TEX3:
00267          case VERT_RESULT_TEX4:
00268          case VERT_RESULT_TEX5:
00269          case VERT_RESULT_TEX6:
00270          case VERT_RESULT_TEX7:
00271             /* fall-through */
00272          case VERT_RESULT_VAR0:
00273             /* fall-through */
00274          default:
00275             if (outputSemanticName) {
00276                /* use provided semantic into */
00277                assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT);
00278                vs_output_semantic_name[slot] = outputSemanticName[attr];
00279                vs_output_semantic_index[slot] = outputSemanticIndex[attr];
00280             }
00281             else {
00282                /* use default semantic info */
00283                vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
00284                vs_output_semantic_index[slot] = num_generic++;
00285             }
00286          }
00287 
00288          output_flags[slot] = stvp->Base.Base.OutputFlags[attr];
00289       }
00290    }
00291 
00292    assert(vs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
00293 
00294 
00295    if (outputMapping) {
00296       /* find max output slot referenced to compute vs_num_outputs */
00297       GLuint maxSlot = 0;
00298       for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
00299          if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
00300             maxSlot = outputMapping[attr];
00301       }
00302       vs_num_outputs = maxSlot + 1;
00303    }
00304    else {
00305       outputMapping = defaultOutputMapping;
00306    }
00307 
00308    /* free old shader state, if any */
00309    if (stvp->state.tokens) {
00310       FREE((void *) stvp->state.tokens);
00311       stvp->state.tokens = NULL;
00312    }
00313    if (stvp->driver_shader) {
00314       cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
00315       stvp->driver_shader = NULL;
00316    }
00317 
00318    /* XXX: fix static allocation of tokens:
00319     */
00320    num_tokens = st_translate_mesa_program(TGSI_PROCESSOR_VERTEX,
00321                                           &stvp->Base.Base,
00322                                           /* inputs */
00323                                           vs_num_inputs,
00324                                           stvp->input_to_index,
00325                                           vs_input_semantic_name,
00326                                           vs_input_semantic_index,
00327                                           NULL,
00328                                           input_flags,
00329                                           /* outputs */
00330                                           vs_num_outputs,
00331                                           outputMapping,
00332                                           vs_output_semantic_name,
00333                                           vs_output_semantic_index,
00334                                           output_flags,
00335                                           /* tokenized result */
00336                                           tokens, ST_MAX_SHADER_TOKENS);
00337 
00338    assert(num_tokens < ST_MAX_SHADER_TOKENS);
00339 
00340    vs.tokens = (struct tgsi_token *)
00341       mem_dup(tokens, num_tokens * sizeof(tokens[0]));
00342 
00343    stvp->num_inputs = vs_num_inputs;
00344    stvp->state = vs; /* struct copy */
00345    stvp->driver_shader = pipe->create_vs_state(pipe, &vs);
00346 
00347    if (0)
00348       _mesa_print_program(&stvp->Base.Base);
00349 
00350    if (TGSI_DEBUG)
00351       tgsi_dump( vs.tokens, 0 );
00352 }
00353 
00354 
00355 
00363 void
00364 st_translate_fragment_program(struct st_context *st,
00365                               struct st_fragment_program *stfp,
00366                               const GLuint inputMapping[])
00367 {
00368    struct pipe_context *pipe = st->pipe;
00369    struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
00370    GLuint outputMapping[FRAG_RESULT_MAX];
00371    GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
00372    struct pipe_shader_state fs;
00373    GLuint interpMode[16];  /* XXX size? */
00374    GLuint attr;
00375    const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
00376    GLuint vslot = 0;
00377    GLuint num_generic = 0;
00378    GLuint num_tokens;
00379 
00380    uint fs_num_inputs = 0;
00381 
00382    ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
00383    ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
00384    uint fs_num_outputs = 0;
00385 
00386    GLbitfield input_flags[MAX_PROGRAM_INPUTS];
00387    GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
00388 
00389    memset(&fs, 0, sizeof(fs));
00390    memset(input_flags, 0, sizeof(input_flags));
00391    memset(output_flags, 0, sizeof(output_flags));
00392 
00393    /* which vertex output goes to the first fragment input: */
00394    if (inputsRead & FRAG_BIT_WPOS)
00395       vslot = 0;
00396    else
00397       vslot = 1;
00398 
00399    /*
00400     * Convert Mesa program inputs to TGSI input register semantics.
00401     */
00402    for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
00403       if (inputsRead & (1 << attr)) {
00404          const GLuint slot = fs_num_inputs;
00405 
00406          defaultInputMapping[attr] = slot;
00407 
00408          stfp->input_map[slot] = vslot++;
00409 
00410          fs_num_inputs++;
00411 
00412          switch (attr) {
00413          case FRAG_ATTRIB_WPOS:
00414             stfp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
00415             stfp->input_semantic_index[slot] = 0;
00416             interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
00417             break;
00418          case FRAG_ATTRIB_COL0:
00419             stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
00420             stfp->input_semantic_index[slot] = 0;
00421             interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
00422             break;
00423          case FRAG_ATTRIB_COL1:
00424             stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
00425             stfp->input_semantic_index[slot] = 1;
00426             interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
00427             break;
00428          case FRAG_ATTRIB_FOGC:
00429             if (stfp->Base.UsesPointCoord)
00430                stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
00431             else
00432                stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
00433             stfp->input_semantic_index[slot] = 0;
00434             interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
00435             break;
00436          case FRAG_ATTRIB_TEX0:
00437          case FRAG_ATTRIB_TEX1:
00438          case FRAG_ATTRIB_TEX2:
00439          case FRAG_ATTRIB_TEX3:
00440          case FRAG_ATTRIB_TEX4:
00441          case FRAG_ATTRIB_TEX5:
00442          case FRAG_ATTRIB_TEX6:
00443          case FRAG_ATTRIB_TEX7:
00444             stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
00445             stfp->input_semantic_index[slot] = num_generic++;
00446             interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
00447             break;
00448          case FRAG_ATTRIB_VAR0:
00449             /* fall-through */
00450          default:
00451             stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
00452             stfp->input_semantic_index[slot] = num_generic++;
00453             interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
00454          }
00455 
00456          input_flags[slot] = stfp->Base.Base.InputFlags[attr];
00457       }
00458    }
00459 
00460    /*
00461     * Semantics and mapping for outputs
00462     */
00463    {
00464       uint numColors = 0;
00465       GLbitfield outputsWritten = stfp->Base.Base.OutputsWritten;
00466 
00467       /* if z is written, emit that first */
00468       if (outputsWritten & (1 << FRAG_RESULT_DEPR)) {
00469          fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
00470          fs_output_semantic_index[fs_num_outputs] = 0;
00471          outputMapping[FRAG_RESULT_DEPR] = fs_num_outputs;
00472          fs_num_outputs++;
00473          outputsWritten &= ~(1 << FRAG_RESULT_DEPR);
00474       }
00475 
00476       /* handle remaning outputs (color) */
00477       for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
00478          if (outputsWritten & (1 << attr)) {
00479             switch (attr) {
00480             case FRAG_RESULT_DEPR:
00481                /* handled above */
00482                assert(0);
00483                break;
00484             case FRAG_RESULT_COLR:
00485                fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
00486                fs_output_semantic_index[fs_num_outputs] = numColors;
00487                outputMapping[attr] = fs_num_outputs;
00488                numColors++;
00489                break;
00490             default:
00491                assert(0);
00492             }
00493 
00494             output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr];
00495 
00496             fs_num_outputs++;
00497          }
00498       }
00499    }
00500 
00501    if (!inputMapping)
00502       inputMapping = defaultInputMapping;
00503 
00504    /* XXX: fix static allocation of tokens:
00505     */
00506    num_tokens = st_translate_mesa_program(TGSI_PROCESSOR_FRAGMENT,
00507                                           &stfp->Base.Base,
00508                                           /* inputs */
00509                                           fs_num_inputs,
00510                                           inputMapping,
00511                                           stfp->input_semantic_name,
00512                                           stfp->input_semantic_index,
00513                                           interpMode,
00514                                           input_flags,
00515                                           /* outputs */
00516                                           fs_num_outputs,
00517                                           outputMapping,
00518                                           fs_output_semantic_name,
00519                                           fs_output_semantic_index,
00520                                           output_flags,
00521                                           /* tokenized result */
00522                                           tokens, ST_MAX_SHADER_TOKENS);
00523 
00524    assert(num_tokens < ST_MAX_SHADER_TOKENS);
00525 
00526    fs.tokens = (struct tgsi_token *)
00527       mem_dup(tokens, num_tokens * sizeof(tokens[0]));
00528 
00529    stfp->state = fs; /* struct copy */
00530    stfp->driver_shader = pipe->create_fs_state(pipe, &fs);
00531 
00532    if (0)
00533       _mesa_print_program(&stfp->Base.Base);
00534 
00535    if (TGSI_DEBUG)
00536       tgsi_dump( fs.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
00537 }
00538 
00539 
00543 void
00544 st_print_shaders(GLcontext *ctx)
00545 {
00546    struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
00547    if (shProg) {
00548       GLuint i;
00549       for (i = 0; i < shProg->NumShaders; i++) {
00550          printf("GLSL shader %u of %u:\n", i, shProg->NumShaders);
00551          printf("%s\n", shProg->Shaders[i]->Source);
00552       }
00553    }
00554 }

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