st_mesa_to_tgsi.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007-2008 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 /*
00029  * \author
00030  * Michal Krol
00031  */
00032 
00033 #include "pipe/p_compiler.h"
00034 #include "pipe/p_shader_tokens.h"
00035 #include "tgsi/tgsi_parse.h"
00036 #include "tgsi/tgsi_build.h"
00037 #include "tgsi/tgsi_util.h"
00038 #include "tgsi/tgsi_dump.h"
00039 #include "tgsi/tgsi_sanity.h"
00040 #include "st_mesa_to_tgsi.h"
00041 #include "shader/prog_instruction.h"
00042 #include "shader/prog_parameter.h"
00043 #include "shader/prog_print.h"
00044 #include "pipe/p_debug.h"
00045 
00046 /*
00047  * Map mesa register file to TGSI register file.
00048  */
00049 static GLuint
00050 map_register_file(
00051    enum register_file file,
00052    GLuint index,
00053    const GLuint immediateMapping[],
00054    GLboolean indirectAccess )
00055 {
00056    switch( file ) {
00057    case PROGRAM_UNDEFINED:
00058       return TGSI_FILE_NULL;
00059    case PROGRAM_TEMPORARY:
00060       return TGSI_FILE_TEMPORARY;
00061    /*case PROGRAM_LOCAL_PARAM:*/
00062    /*case PROGRAM_ENV_PARAM:*/
00063 
00064       /* Because of the longstanding problem with mesa arb shaders
00065        * where constants, immediates and state variables are all
00066        * bundled together as PROGRAM_STATE_VAR, we can't tell from the
00067        * mesa register file whether this is a CONSTANT or an
00068        * IMMEDIATE, hence we need all the other information.
00069        */
00070    case PROGRAM_STATE_VAR:
00071    case PROGRAM_NAMED_PARAM:
00072    case PROGRAM_UNIFORM:
00073       if (!indirectAccess && immediateMapping && immediateMapping[index] != ~0)
00074          return TGSI_FILE_IMMEDIATE;
00075       else
00076          return TGSI_FILE_CONSTANT;
00077    case PROGRAM_CONSTANT:
00078       if (indirectAccess)
00079          return TGSI_FILE_CONSTANT;
00080       assert(immediateMapping[index] != ~0);
00081       return TGSI_FILE_IMMEDIATE;
00082    case PROGRAM_INPUT:
00083       return TGSI_FILE_INPUT;
00084    case PROGRAM_OUTPUT:
00085       return TGSI_FILE_OUTPUT;
00086    case PROGRAM_ADDRESS:
00087       return TGSI_FILE_ADDRESS;
00088    default:
00089       assert( 0 );
00090       return TGSI_FILE_NULL;
00091    }
00092 }
00093 
00102 static GLuint
00103 map_register_file_index(
00104    GLuint file,
00105    GLuint index,
00106    const GLuint inputMapping[],
00107    const GLuint outputMapping[],
00108    const GLuint immediateMapping[],
00109    GLboolean indirectAccess )
00110 {
00111    switch( file ) {
00112    case TGSI_FILE_INPUT:
00113       /* inputs are mapped according to the user-defined map */
00114       return inputMapping[index];
00115 
00116    case TGSI_FILE_OUTPUT:
00117       return outputMapping[index];
00118 
00119    case TGSI_FILE_IMMEDIATE:
00120       if (indirectAccess)
00121          return index;
00122       assert(immediateMapping[index] != ~0);
00123       return immediateMapping[index];
00124 
00125    default:
00126       return index;
00127    }
00128 }
00129 
00130 /*
00131  * Map mesa texture target to TGSI texture target.
00132  */
00133 static GLuint
00134 map_texture_target(
00135    GLuint textarget )
00136 {
00137    switch( textarget ) {
00138    case TEXTURE_1D_INDEX:
00139       return TGSI_TEXTURE_1D;
00140    case TEXTURE_2D_INDEX:
00141       return TGSI_TEXTURE_2D;
00142    case TEXTURE_3D_INDEX:
00143       return TGSI_TEXTURE_3D;
00144    case TEXTURE_CUBE_INDEX:
00145       return TGSI_TEXTURE_CUBE;
00146    case TEXTURE_RECT_INDEX:
00147       return TGSI_TEXTURE_RECT;
00148    default:
00149       assert( 0 );
00150    }
00151 
00152    return TGSI_TEXTURE_1D;
00153 }
00154 
00155 static GLuint
00156 convert_sat(
00157    GLuint sat )
00158 {
00159    switch( sat ) {
00160    case SATURATE_OFF:
00161       return TGSI_SAT_NONE;
00162    case SATURATE_ZERO_ONE:
00163       return TGSI_SAT_ZERO_ONE;
00164    case SATURATE_PLUS_MINUS_ONE:
00165       return TGSI_SAT_MINUS_PLUS_ONE;
00166    default:
00167       assert( 0 );
00168       return TGSI_SAT_NONE;
00169    }
00170 }
00171 
00172 static GLuint
00173 convert_writemask(
00174    GLuint writemask )
00175 {
00176    assert( WRITEMASK_X == TGSI_WRITEMASK_X );
00177    assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
00178    assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
00179    assert( WRITEMASK_W == TGSI_WRITEMASK_W );
00180    assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
00181 
00182    return writemask;
00183 }
00184 
00185 static struct tgsi_full_immediate
00186 make_immediate(const float *value, uint size)
00187 {
00188    struct tgsi_full_immediate imm;
00189 
00190    imm = tgsi_default_full_immediate();
00191    imm.Immediate.Size += size;
00192    imm.Immediate.DataType = TGSI_IMM_FLOAT32;
00193    imm.u.Pointer = value;
00194    return imm;
00195 }
00196 
00197 static void
00198 compile_instruction(
00199    const struct prog_instruction *inst,
00200    struct tgsi_full_instruction *fullinst,
00201    const GLuint inputMapping[],
00202    const GLuint outputMapping[],
00203    const GLuint immediateMapping[],
00204    GLboolean indirectAccess,
00205    GLuint preamble_size,
00206    GLuint processor,
00207    GLboolean *insideSubroutine)
00208 {
00209    GLuint i;
00210    struct tgsi_full_dst_register *fulldst;
00211    struct tgsi_full_src_register *fullsrc;
00212 
00213    *fullinst = tgsi_default_full_instruction();
00214 
00215    fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
00216    fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode );
00217    fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
00218 
00219    fulldst = &fullinst->FullDstRegisters[0];
00220    fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE );
00221    fulldst->DstRegister.Index = map_register_file_index(
00222       fulldst->DstRegister.File,
00223       inst->DstReg.Index,
00224       inputMapping,
00225       outputMapping,
00226       NULL,
00227       GL_FALSE );
00228    fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
00229 
00230    for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
00231       GLuint j;
00232 
00233       fullsrc = &fullinst->FullSrcRegisters[i];
00234       fullsrc->SrcRegister.File = map_register_file(
00235          inst->SrcReg[i].File,
00236          inst->SrcReg[i].Index,
00237          immediateMapping,
00238          indirectAccess );
00239       fullsrc->SrcRegister.Index = map_register_file_index(
00240          fullsrc->SrcRegister.File,
00241          inst->SrcReg[i].Index,
00242          inputMapping,
00243          outputMapping,
00244          immediateMapping,
00245          indirectAccess );
00246 
00247 
00248       /* swizzle (ext swizzle also depends on negation) */
00249       {
00250          GLuint swz[4];
00251          GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE &&
00252                                inst->SrcReg[i].NegateBase != NEGATE_XYZW);
00253          for( j = 0; j < 4; j++ ) {
00254             swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
00255             if (swz[j] > SWIZZLE_W)
00256                extended = GL_TRUE;
00257          }
00258          if (extended) {
00259             for (j = 0; j < 4; j++) {
00260                tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
00261                                                      swz[j], j);
00262             }
00263          }
00264          else {
00265             for (j = 0; j < 4; j++) {
00266                tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
00267                                                   swz[j], j);
00268             }
00269          }
00270       }
00271 
00272       if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
00273          fullsrc->SrcRegister.Negate = 1;
00274       }
00275       else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
00276          if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
00277             fullsrc->SrcRegisterExtSwz.NegateX = 1;
00278          }
00279          if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
00280             fullsrc->SrcRegisterExtSwz.NegateY = 1;
00281          }
00282          if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
00283             fullsrc->SrcRegisterExtSwz.NegateZ = 1;
00284          }
00285          if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
00286             fullsrc->SrcRegisterExtSwz.NegateW = 1;
00287          }
00288       }
00289 
00290       if( inst->SrcReg[i].Abs ) {
00291          fullsrc->SrcRegisterExtMod.Absolute = 1;
00292       }
00293 
00294       if( inst->SrcReg[i].NegateAbs ) {
00295          fullsrc->SrcRegisterExtMod.Negate = 1;
00296       }
00297 
00298       if( inst->SrcReg[i].RelAddr ) {
00299          fullsrc->SrcRegister.Indirect = 1;
00300 
00301          fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
00302          fullsrc->SrcRegisterInd.Index = 0;
00303       }
00304    }
00305 
00306    switch( inst->Opcode ) {
00307    case OPCODE_ARL:
00308       fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
00309       break;
00310    case OPCODE_ABS:
00311       fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
00312       break;
00313    case OPCODE_ADD:
00314       fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
00315       break;
00316    case OPCODE_BGNLOOP:
00317       fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2;
00318       fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
00319       break;
00320    case OPCODE_BGNSUB:
00321       fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
00322       *insideSubroutine = GL_TRUE;
00323       break;
00324    case OPCODE_BRA:
00325       fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
00326       break;
00327    case OPCODE_BRK:
00328       fullinst->Instruction.Opcode = TGSI_OPCODE_BRK;
00329       break;
00330    case OPCODE_CAL:
00331       fullinst->Instruction.Opcode = TGSI_OPCODE_CAL;
00332       fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
00333       break;
00334    case OPCODE_CMP:
00335       fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
00336       break;
00337    case OPCODE_CONT:
00338       fullinst->Instruction.Opcode = TGSI_OPCODE_CONT;
00339       break;
00340    case OPCODE_COS:
00341       fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
00342       break;
00343    case OPCODE_DDX:
00344       fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
00345       break;
00346    case OPCODE_DDY:
00347       fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
00348       break;
00349    case OPCODE_DP3:
00350       fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
00351       break;
00352    case OPCODE_DP4:
00353       fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
00354       break;
00355    case OPCODE_DPH:
00356       fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
00357       break;
00358    case OPCODE_DST:
00359       fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
00360       break;
00361    case OPCODE_ELSE:
00362       fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
00363       fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
00364       break;
00365    case OPCODE_ENDIF:
00366       fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
00367       break;
00368    case OPCODE_ENDLOOP:
00369       fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
00370       fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
00371       break;
00372    case OPCODE_ENDSUB:
00373       fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
00374       *insideSubroutine = GL_FALSE;
00375       break;
00376    case OPCODE_EX2:
00377       fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
00378       break;
00379    case OPCODE_EXP:
00380       fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
00381       break;
00382    case OPCODE_FLR:
00383       fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
00384       break;
00385    case OPCODE_FRC:
00386       fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
00387       break;
00388    case OPCODE_IF:
00389       fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
00390       fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
00391       break;
00392    case OPCODE_INT:
00393       fullinst->Instruction.Opcode = TGSI_OPCODE_INT;
00394       break;
00395    case OPCODE_KIL:
00396       /* conditional */
00397       fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
00398       break;
00399    case OPCODE_KIL_NV:
00400       /* predicated */
00401       assert(inst->DstReg.CondMask == COND_TR);
00402       fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
00403       break;
00404    case OPCODE_LG2:
00405       fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
00406       break;
00407    case OPCODE_LOG:
00408       fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
00409       break;
00410    case OPCODE_LIT:
00411       fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
00412       break;
00413    case OPCODE_LRP:
00414       fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
00415       break;
00416    case OPCODE_MAD:
00417       fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
00418       break;
00419    case OPCODE_MAX:
00420       fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
00421       break;
00422    case OPCODE_MIN:
00423       fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
00424       break;
00425    case OPCODE_MOV:
00426       fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
00427       break;
00428    case OPCODE_MUL:
00429       fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
00430       break;
00431    case OPCODE_NOISE1:
00432       fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
00433       break;
00434    case OPCODE_NOISE2:
00435       fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
00436       break;
00437    case OPCODE_NOISE3:
00438       fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
00439       break;
00440    case OPCODE_NOISE4:
00441       fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
00442       break;
00443    case OPCODE_NOP:
00444       fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
00445       break;
00446    case OPCODE_POW:
00447       fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
00448       break;
00449    case OPCODE_RCP:
00450       fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
00451       break;
00452    case OPCODE_RET:
00453       /* If RET is used inside main (not a real subroutine) we may want
00454        * to execute END instead of RET.  TBD...
00455        */
00456       if (1 /*  *insideSubroutine */) {
00457          fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
00458       }
00459       else {
00460          /* inside main() pseudo-function */
00461          fullinst->Instruction.Opcode = TGSI_OPCODE_END;
00462       }
00463       break;
00464    case OPCODE_RSQ:
00465       fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
00466 
00467       /* KW: Don't do this here.  If particular hardware needs to do
00468        * this, can do so in the driver..
00469        */
00470 #if 0
00471        tgsi_util_set_full_src_register_sign_mode(
00472           &fullinst->FullSrcRegisters[0],
00473           TGSI_UTIL_SIGN_CLEAR ); 
00474 #endif
00475       break;
00476    case OPCODE_SCS:
00477       fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
00478       fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
00479       break;
00480    case OPCODE_SEQ:
00481       fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
00482       break;
00483    case OPCODE_SGE:
00484       fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
00485       break;
00486    case OPCODE_SGT:
00487       fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
00488       break;
00489    case OPCODE_SIN:
00490       fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
00491       break;
00492    case OPCODE_SLE:
00493       fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
00494       break;
00495    case OPCODE_SLT:
00496       fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
00497       break;
00498    case OPCODE_SNE:
00499       fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
00500       break;
00501    case OPCODE_SUB:
00502       fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
00503       break;
00504    case OPCODE_SWZ:
00505       fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
00506       break;
00507    case OPCODE_TEX:
00508       /* ordinary texture lookup */
00509       fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
00510       fullinst->Instruction.NumSrcRegs = 2;
00511       fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
00512       fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
00513       fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
00514       break;
00515    case OPCODE_TXB:
00516       /* texture lookup with LOD bias */
00517       fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
00518       fullinst->Instruction.NumSrcRegs = 2;
00519       fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
00520       fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
00521       fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
00522       break;
00523    case OPCODE_TXD:
00524       /* texture lookup with explicit partial derivatives */
00525       fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
00526       fullinst->Instruction.NumSrcRegs = 4;
00527       fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
00528       /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
00529       fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
00530       fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
00531       break;
00532    case OPCODE_TXL:
00533       /* texture lookup with explicit LOD */
00534       fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
00535       fullinst->Instruction.NumSrcRegs = 2;
00536       fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
00537       fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
00538       fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
00539       break;
00540    case OPCODE_TXP:
00541       /* texture lookup with divide by Q component */
00542       /* convert to TEX w/ special flag for division */
00543       fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
00544       fullinst->Instruction.NumSrcRegs = 2;
00545       fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
00546       fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
00547       fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
00548       break;
00549    case OPCODE_XPD:
00550       fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
00551       fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
00552       break;
00553    case OPCODE_END:
00554       fullinst->Instruction.Opcode = TGSI_OPCODE_END;
00555       break;
00556    default:
00557       assert( 0 );
00558    }
00559 }
00560 
00564 static struct tgsi_full_declaration
00565 make_input_decl(
00566    GLuint index,
00567    GLboolean interpolate_info,
00568    GLuint interpolate,
00569    GLuint usage_mask,
00570    GLboolean semantic_info,
00571    GLuint semantic_name,
00572    GLbitfield semantic_index,
00573    GLbitfield input_flags)
00574 {
00575    struct tgsi_full_declaration decl;
00576 
00577    assert(semantic_name < TGSI_SEMANTIC_COUNT);
00578 
00579    decl = tgsi_default_full_declaration();
00580    decl.Declaration.File = TGSI_FILE_INPUT;
00581    decl.Declaration.UsageMask = usage_mask;
00582    decl.Declaration.Semantic = semantic_info;
00583    decl.DeclarationRange.First = index;
00584    decl.DeclarationRange.Last = index;
00585    if (semantic_info) {
00586       decl.Semantic.SemanticName = semantic_name;
00587       decl.Semantic.SemanticIndex = semantic_index;
00588    }
00589    if (interpolate_info) {
00590       decl.Declaration.Interpolate = interpolate;
00591    }
00592    if (input_flags & PROG_PARAM_BIT_CENTROID)
00593       decl.Declaration.Centroid = 1;
00594    if (input_flags & PROG_PARAM_BIT_INVARIANT)
00595       decl.Declaration.Invariant = 1;
00596 
00597    return decl;
00598 }
00599 
00603 static struct tgsi_full_declaration
00604 make_output_decl(
00605    GLuint index,
00606    GLuint semantic_name,
00607    GLuint semantic_index,
00608    GLuint usage_mask,
00609    GLbitfield output_flags)
00610 {
00611    struct tgsi_full_declaration decl;
00612 
00613    assert(semantic_name < TGSI_SEMANTIC_COUNT);
00614 
00615    decl = tgsi_default_full_declaration();
00616    decl.Declaration.File = TGSI_FILE_OUTPUT;
00617    decl.Declaration.UsageMask = usage_mask;
00618    decl.Declaration.Semantic = 1;
00619    decl.DeclarationRange.First = index;
00620    decl.DeclarationRange.Last = index;
00621    decl.Semantic.SemanticName = semantic_name;
00622    decl.Semantic.SemanticIndex = semantic_index;
00623    if (output_flags & PROG_PARAM_BIT_CENTROID)
00624       decl.Declaration.Centroid = 1;
00625    if (output_flags & PROG_PARAM_BIT_INVARIANT)
00626       decl.Declaration.Invariant = 1;
00627 
00628    return decl;
00629 }
00630 
00631 
00632 static struct tgsi_full_declaration
00633 make_temp_decl(
00634    GLuint start_index,
00635    GLuint end_index )
00636 {
00637    struct tgsi_full_declaration decl;
00638    decl = tgsi_default_full_declaration();
00639    decl.Declaration.File = TGSI_FILE_TEMPORARY;
00640    decl.DeclarationRange.First = start_index;
00641    decl.DeclarationRange.Last = end_index;
00642    return decl;
00643 }
00644 
00645 static struct tgsi_full_declaration
00646 make_addr_decl(
00647    GLuint start_index,
00648    GLuint end_index )
00649 {
00650    struct tgsi_full_declaration decl;
00651 
00652    decl = tgsi_default_full_declaration();
00653    decl.Declaration.File = TGSI_FILE_ADDRESS;
00654    decl.DeclarationRange.First = start_index;
00655    decl.DeclarationRange.Last = end_index;
00656    return decl;
00657 }
00658 
00659 static struct tgsi_full_declaration
00660 make_sampler_decl(GLuint index)
00661 {
00662    struct tgsi_full_declaration decl;
00663    decl = tgsi_default_full_declaration();
00664    decl.Declaration.File = TGSI_FILE_SAMPLER;
00665    decl.DeclarationRange.First = index;
00666    decl.DeclarationRange.Last = index;
00667    return decl;
00668 }
00669 
00671 static struct tgsi_full_declaration
00672 make_constant_decl(GLuint first, GLuint last)
00673 {
00674    struct tgsi_full_declaration decl;
00675    decl = tgsi_default_full_declaration();
00676    decl.Declaration.File = TGSI_FILE_CONSTANT;
00677    decl.DeclarationRange.First = first;
00678    decl.DeclarationRange.Last = last;
00679    return decl;
00680 }
00681 
00682 
00683 
00687 static void
00688 find_temporaries(const struct gl_program *program,
00689                  GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
00690 {
00691    GLuint i, j;
00692 
00693    for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
00694       tempsUsed[i] = GL_FALSE;
00695 
00696    for (i = 0; i < program->NumInstructions; i++) {
00697       const struct prog_instruction *inst = program->Instructions + i;
00698       const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
00699       for (j = 0; j < n; j++) {
00700          if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
00701             tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
00702          if (inst->DstReg.File == PROGRAM_TEMPORARY)
00703             tempsUsed[inst->DstReg.Index] = GL_TRUE;
00704       }
00705    }
00706 }
00707 
00708 
00709 
00710 
00731 GLuint
00732 st_translate_mesa_program(
00733    uint procType,
00734    const struct gl_program *program,
00735    GLuint numInputs,
00736    const GLuint inputMapping[],
00737    const ubyte inputSemanticName[],
00738    const ubyte inputSemanticIndex[],
00739    const GLuint interpMode[],
00740    const GLbitfield inputFlags[],
00741    GLuint numOutputs,
00742    const GLuint outputMapping[],
00743    const ubyte outputSemanticName[],
00744    const ubyte outputSemanticIndex[],
00745    const GLbitfield outputFlags[],
00746    struct tgsi_token *tokens,
00747    GLuint maxTokens )
00748 {
00749    GLuint i;
00750    GLuint ti;  /* token index */
00751    struct tgsi_header *header;
00752    struct tgsi_processor *processor;
00753    struct tgsi_full_instruction fullinst;
00754    GLuint preamble_size = 0;
00755    GLuint immediates[1000];
00756    GLuint numImmediates = 0;
00757    GLboolean insideSubroutine = GL_FALSE;
00758    GLboolean indirectAccess = GL_FALSE;
00759 
00760    assert(procType == TGSI_PROCESSOR_FRAGMENT ||
00761           procType == TGSI_PROCESSOR_VERTEX);
00762 
00763    *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
00764 
00765    header = (struct tgsi_header *) &tokens[1];
00766    *header = tgsi_build_header();
00767 
00768    processor = (struct tgsi_processor *) &tokens[2];
00769    *processor = tgsi_build_processor( procType, header );
00770 
00771    ti = 3;
00772 
00773    /*
00774     * Declare input attributes.
00775     */
00776    if (procType == TGSI_PROCESSOR_FRAGMENT) {
00777       for (i = 0; i < numInputs; i++) {
00778          struct tgsi_full_declaration fulldecl;
00779          fulldecl = make_input_decl(i,
00780                                     GL_TRUE, interpMode[i],
00781                                     TGSI_WRITEMASK_XYZW,
00782                                     GL_TRUE, inputSemanticName[i],
00783                                     inputSemanticIndex[i],
00784                                     inputFlags[i]);
00785          ti += tgsi_build_full_declaration(&fulldecl,
00786                                            &tokens[ti],
00787                                            header,
00788                                            maxTokens - ti );
00789       }
00790    }
00791    else {
00792       /* vertex prog */
00793       /* XXX: this could probaby be merged with the clause above.
00794        * the only difference is the semantic tags.
00795        */
00796       for (i = 0; i < numInputs; i++) {
00797          struct tgsi_full_declaration fulldecl;
00798          fulldecl = make_input_decl(i,
00799                                     GL_FALSE, 0,
00800                                     TGSI_WRITEMASK_XYZW,
00801                                     GL_FALSE, 0, 0,
00802                                     inputFlags[i]);
00803          ti += tgsi_build_full_declaration(&fulldecl,
00804                                            &tokens[ti],
00805                                            header,
00806                                            maxTokens - ti );
00807       }
00808    }
00809 
00810    /*
00811     * Declare output attributes.
00812     */
00813    if (procType == TGSI_PROCESSOR_FRAGMENT) {
00814       for (i = 0; i < numOutputs; i++) {
00815          struct tgsi_full_declaration fulldecl;
00816          switch (outputSemanticName[i]) {
00817          case TGSI_SEMANTIC_POSITION:
00818             fulldecl = make_output_decl(i,
00819                                         TGSI_SEMANTIC_POSITION, /* Z / Depth */
00820                                         outputSemanticIndex[i],
00821                                         TGSI_WRITEMASK_Z,
00822                                         outputFlags[i]);
00823             break;
00824          case TGSI_SEMANTIC_COLOR:
00825             fulldecl = make_output_decl(i,
00826                                         TGSI_SEMANTIC_COLOR,
00827                                         outputSemanticIndex[i],
00828                                         TGSI_WRITEMASK_XYZW,
00829                                         outputFlags[i]);
00830             break;
00831          default:
00832             assert(0);
00833             return 0;
00834          }
00835          ti += tgsi_build_full_declaration(&fulldecl,
00836                                            &tokens[ti],
00837                                            header,
00838                                            maxTokens - ti );
00839       }
00840    }
00841    else {
00842       /* vertex prog */
00843       for (i = 0; i < numOutputs; i++) {
00844          struct tgsi_full_declaration fulldecl;
00845          fulldecl = make_output_decl(i,
00846                                      outputSemanticName[i],
00847                                      outputSemanticIndex[i],
00848                                      TGSI_WRITEMASK_XYZW,
00849                                      outputFlags[i]);
00850          ti += tgsi_build_full_declaration(&fulldecl,
00851                                            &tokens[ti],
00852                                            header,
00853                                            maxTokens - ti );
00854       }
00855    }
00856 
00857    /* temporary decls */
00858    {
00859       GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
00860       GLboolean inside_range = GL_FALSE;
00861       GLuint start_range = 0;
00862 
00863       find_temporaries(program, tempsUsed);
00864       tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
00865       for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
00866          if (tempsUsed[i] && !inside_range) {
00867             inside_range = GL_TRUE;
00868             start_range = i;
00869          }
00870          else if (!tempsUsed[i] && inside_range) {
00871             struct tgsi_full_declaration fulldecl;
00872 
00873             inside_range = GL_FALSE;
00874             fulldecl = make_temp_decl( start_range, i - 1 );
00875             ti += tgsi_build_full_declaration(
00876                &fulldecl,
00877                &tokens[ti],
00878                header,
00879                maxTokens - ti );
00880          }
00881       }
00882    }
00883 
00884    /* Declare address register.
00885    */
00886    if (program->NumAddressRegs > 0) {
00887       struct tgsi_full_declaration fulldecl;
00888 
00889       assert( program->NumAddressRegs == 1 );
00890 
00891       fulldecl = make_addr_decl( 0, 0 );
00892       ti += tgsi_build_full_declaration(
00893          &fulldecl,
00894          &tokens[ti],
00895          header,
00896          maxTokens - ti );
00897 
00898       indirectAccess = GL_TRUE;
00899    }
00900 
00901    /* immediates/literals */
00902    memset(immediates, ~0, sizeof(immediates));
00903 
00904    /* Emit immediates only when there is no address register in use.
00905     * FIXME: Be smarter and recognize param arrays -- indirect addressing is
00906     *        only valid within the referenced array.
00907     */
00908    if (program->Parameters && !indirectAccess) {
00909       for (i = 0; i < program->Parameters->NumParameters; i++) {
00910          if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
00911             struct tgsi_full_immediate fullimm;
00912 
00913             fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
00914             ti += tgsi_build_full_immediate(
00915                &fullimm,
00916                &tokens[ti],
00917                header,
00918                maxTokens - ti );
00919             immediates[i] = numImmediates;
00920             numImmediates++;
00921          }
00922       }
00923    }
00924 
00925    /* constant buffer refs */
00926    if (program->Parameters) {
00927       GLint start = -1, end = -1;
00928 
00929       for (i = 0; i < program->Parameters->NumParameters; i++) {
00930          GLboolean emit = (i == program->Parameters->NumParameters - 1);
00931          GLboolean matches;
00932 
00933          switch (program->Parameters->Parameters[i].Type) {
00934          case PROGRAM_ENV_PARAM:
00935          case PROGRAM_STATE_VAR:
00936          case PROGRAM_NAMED_PARAM:
00937          case PROGRAM_UNIFORM:
00938             matches = GL_TRUE;
00939             break;
00940          case PROGRAM_CONSTANT:
00941             matches = indirectAccess;
00942             break;
00943          default:
00944             matches = GL_FALSE;
00945          }
00946 
00947          if (matches) {
00948             if (start == -1) {
00949                /* begin a sequence */
00950                start = i;
00951                end = i;
00952             }
00953             else {
00954                /* continue sequence */
00955                end = i;
00956             }
00957          }
00958          else {
00959             if (start != -1) {
00960                /* end of sequence */
00961                emit = GL_TRUE;
00962             }
00963          }
00964 
00965          if (emit && start >= 0) {
00966             struct tgsi_full_declaration fulldecl;
00967 
00968             fulldecl = make_constant_decl( start, end );
00969             ti += tgsi_build_full_declaration(
00970                &fulldecl,
00971                &tokens[ti],
00972                header,
00973                maxTokens - ti );
00974             start = end = -1;
00975          }
00976       }
00977    }
00978 
00979    /* texture samplers */
00980    for (i = 0; i < 8; i++) {
00981       if (program->SamplersUsed & (1 << i)) {
00982          struct tgsi_full_declaration fulldecl;
00983 
00984          fulldecl = make_sampler_decl( i );
00985          ti += tgsi_build_full_declaration(
00986             &fulldecl,
00987             &tokens[ti],
00988             header,
00989             maxTokens - ti );
00990       }
00991    }
00992 
00993    for (i = 0; i < program->NumInstructions; i++) {
00994       compile_instruction(
00995          &program->Instructions[i],
00996          &fullinst,
00997          inputMapping,
00998          outputMapping,
00999          immediates,
01000          indirectAccess,
01001          preamble_size,
01002          procType,
01003          &insideSubroutine );
01004 
01005       ti += tgsi_build_full_instruction(
01006          &fullinst,
01007          &tokens[ti],
01008          header,
01009          maxTokens - ti );
01010    }
01011 
01012 #if DEBUG
01013    if(!tgsi_sanity_check(tokens)) {
01014       debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
01015       debug_printf("\nOriginal program:\n%s", program->String);
01016       debug_printf("\nMesa program:\n");
01017       _mesa_print_program(program);
01018       debug_printf("\nTGSI program:\n");
01019       tgsi_dump(tokens, 0);
01020       assert(0);
01021    }
01022 #endif
01023 
01024    return ti;
01025 }

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