st_mesa_to_tgsi.c revision c5b52b5e0e6f6e47c3953076fa788921b1c5a5e2
1/**************************************************************************
2 *
3 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28/*
29 * \author
30 * Michal Krol
31 */
32
33#include "pipe/p_compiler.h"
34#include "pipe/p_shader_tokens.h"
35#include "tgsi/tgsi_parse.h"
36#include "tgsi/tgsi_build.h"
37#include "tgsi/tgsi_util.h"
38#include "tgsi/tgsi_dump.h"
39#include "tgsi/tgsi_sanity.h"
40#include "st_mesa_to_tgsi.h"
41#include "shader/prog_instruction.h"
42#include "shader/prog_parameter.h"
43#include "shader/prog_print.h"
44#include "pipe/p_debug.h"
45
46/*
47 * Map mesa register file to TGSI register file.
48 */
49static GLuint
50map_register_file(
51   enum register_file file,
52   GLuint index,
53   const GLuint immediateMapping[],
54   GLboolean indirectAccess )
55{
56   switch( file ) {
57   case PROGRAM_UNDEFINED:
58      return TGSI_FILE_NULL;
59   case PROGRAM_TEMPORARY:
60      return TGSI_FILE_TEMPORARY;
61   /*case PROGRAM_LOCAL_PARAM:*/
62   /*case PROGRAM_ENV_PARAM:*/
63
64      /* Because of the longstanding problem with mesa arb shaders
65       * where constants, immediates and state variables are all
66       * bundled together as PROGRAM_STATE_VAR, we can't tell from the
67       * mesa register file whether this is a CONSTANT or an
68       * IMMEDIATE, hence we need all the other information.
69       */
70   case PROGRAM_STATE_VAR:
71   case PROGRAM_NAMED_PARAM:
72   case PROGRAM_UNIFORM:
73      if (!indirectAccess && immediateMapping && immediateMapping[index] != ~0)
74         return TGSI_FILE_IMMEDIATE;
75      else
76	 return TGSI_FILE_CONSTANT;
77   case PROGRAM_CONSTANT:
78      if (indirectAccess)
79         return TGSI_FILE_CONSTANT;
80      assert(immediateMapping[index] != ~0);
81      return TGSI_FILE_IMMEDIATE;
82   case PROGRAM_INPUT:
83      return TGSI_FILE_INPUT;
84   case PROGRAM_OUTPUT:
85      return TGSI_FILE_OUTPUT;
86   case PROGRAM_ADDRESS:
87      return TGSI_FILE_ADDRESS;
88   default:
89      assert( 0 );
90      return TGSI_FILE_NULL;
91   }
92}
93
94/**
95 * Map mesa register file index to TGSI index.
96 * Take special care when processing input and output indices.
97 * \param file  one of TGSI_FILE_x
98 * \param index  the mesa register file index
99 * \param inputMapping  maps Mesa input indexes to TGSI input indexes
100 * \param outputMapping  maps Mesa output indexes to TGSI output indexes
101 */
102static GLuint
103map_register_file_index(
104   GLuint file,
105   GLuint index,
106   const GLuint inputMapping[],
107   const GLuint outputMapping[],
108   const GLuint immediateMapping[],
109   GLboolean indirectAccess )
110{
111   switch( file ) {
112   case TGSI_FILE_INPUT:
113      /* inputs are mapped according to the user-defined map */
114      return inputMapping[index];
115
116   case TGSI_FILE_OUTPUT:
117      return outputMapping[index];
118
119   case TGSI_FILE_IMMEDIATE:
120      if (indirectAccess)
121         return index;
122      assert(immediateMapping[index] != ~0);
123      return immediateMapping[index];
124
125   default:
126      return index;
127   }
128}
129
130/*
131 * Map mesa texture target to TGSI texture target.
132 */
133static GLuint
134map_texture_target(
135   GLuint textarget )
136{
137   switch( textarget ) {
138   case TEXTURE_1D_INDEX:
139      return TGSI_TEXTURE_1D;
140   case TEXTURE_2D_INDEX:
141      return TGSI_TEXTURE_2D;
142   case TEXTURE_3D_INDEX:
143      return TGSI_TEXTURE_3D;
144   case TEXTURE_CUBE_INDEX:
145      return TGSI_TEXTURE_CUBE;
146   case TEXTURE_RECT_INDEX:
147      return TGSI_TEXTURE_RECT;
148   default:
149      assert( 0 );
150   }
151
152   return TGSI_TEXTURE_1D;
153}
154
155static GLuint
156convert_sat(
157   GLuint sat )
158{
159   switch( sat ) {
160   case SATURATE_OFF:
161      return TGSI_SAT_NONE;
162   case SATURATE_ZERO_ONE:
163      return TGSI_SAT_ZERO_ONE;
164   case SATURATE_PLUS_MINUS_ONE:
165      return TGSI_SAT_MINUS_PLUS_ONE;
166   default:
167      assert( 0 );
168      return TGSI_SAT_NONE;
169   }
170}
171
172static GLuint
173convert_writemask(
174   GLuint writemask )
175{
176   assert( WRITEMASK_X == TGSI_WRITEMASK_X );
177   assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
178   assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
179   assert( WRITEMASK_W == TGSI_WRITEMASK_W );
180   assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
181
182   return writemask;
183}
184
185static struct tgsi_full_immediate
186make_immediate(const float *value, uint size)
187{
188   struct tgsi_full_immediate imm;
189
190   imm = tgsi_default_full_immediate();
191   imm.Immediate.Size += size;
192   imm.Immediate.DataType = TGSI_IMM_FLOAT32;
193   imm.u.Pointer = value;
194   return imm;
195}
196
197static void
198compile_instruction(
199   const struct prog_instruction *inst,
200   struct tgsi_full_instruction *fullinst,
201   const GLuint inputMapping[],
202   const GLuint outputMapping[],
203   const GLuint immediateMapping[],
204   GLboolean indirectAccess,
205   GLuint preamble_size,
206   GLuint processor,
207   GLboolean *insideSubroutine)
208{
209   GLuint i;
210   struct tgsi_full_dst_register *fulldst;
211   struct tgsi_full_src_register *fullsrc;
212
213   *fullinst = tgsi_default_full_instruction();
214
215   fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
216   fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode );
217   fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
218
219   fulldst = &fullinst->FullDstRegisters[0];
220   fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE );
221   fulldst->DstRegister.Index = map_register_file_index(
222      fulldst->DstRegister.File,
223      inst->DstReg.Index,
224      inputMapping,
225      outputMapping,
226      NULL,
227      GL_FALSE );
228   fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
229
230   for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
231      GLuint j;
232
233      fullsrc = &fullinst->FullSrcRegisters[i];
234      fullsrc->SrcRegister.File = map_register_file(
235         inst->SrcReg[i].File,
236         inst->SrcReg[i].Index,
237         immediateMapping,
238         indirectAccess );
239      fullsrc->SrcRegister.Index = map_register_file_index(
240         fullsrc->SrcRegister.File,
241         inst->SrcReg[i].Index,
242         inputMapping,
243         outputMapping,
244         immediateMapping,
245         indirectAccess );
246
247
248      /* swizzle (ext swizzle also depends on negation) */
249      {
250         GLuint swz[4];
251         GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE &&
252                               inst->SrcReg[i].NegateBase != NEGATE_XYZW);
253         for( j = 0; j < 4; j++ ) {
254            swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
255            if (swz[j] > SWIZZLE_W)
256               extended = GL_TRUE;
257         }
258         if (extended) {
259            for (j = 0; j < 4; j++) {
260               tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
261                                                     swz[j], j);
262            }
263         }
264         else {
265            for (j = 0; j < 4; j++) {
266               tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
267                                                  swz[j], j);
268            }
269         }
270      }
271
272      if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
273         fullsrc->SrcRegister.Negate = 1;
274      }
275      else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
276         if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
277            fullsrc->SrcRegisterExtSwz.NegateX = 1;
278         }
279         if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
280            fullsrc->SrcRegisterExtSwz.NegateY = 1;
281         }
282         if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
283            fullsrc->SrcRegisterExtSwz.NegateZ = 1;
284         }
285         if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
286            fullsrc->SrcRegisterExtSwz.NegateW = 1;
287         }
288      }
289
290      if( inst->SrcReg[i].Abs ) {
291         fullsrc->SrcRegisterExtMod.Absolute = 1;
292      }
293
294      if( inst->SrcReg[i].NegateAbs ) {
295         fullsrc->SrcRegisterExtMod.Negate = 1;
296      }
297
298      if( inst->SrcReg[i].RelAddr ) {
299         fullsrc->SrcRegister.Indirect = 1;
300
301         fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
302         fullsrc->SrcRegisterInd.Index = 0;
303      }
304   }
305
306   switch( inst->Opcode ) {
307   case OPCODE_ARL:
308      fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
309      break;
310   case OPCODE_ABS:
311      fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
312      break;
313   case OPCODE_ADD:
314      fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
315      break;
316   case OPCODE_BGNLOOP:
317      fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2;
318      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
319      break;
320   case OPCODE_BGNSUB:
321      fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
322      *insideSubroutine = GL_TRUE;
323      break;
324   case OPCODE_BRA:
325      fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
326      break;
327   case OPCODE_BRK:
328      fullinst->Instruction.Opcode = TGSI_OPCODE_BRK;
329      break;
330   case OPCODE_CAL:
331      fullinst->Instruction.Opcode = TGSI_OPCODE_CAL;
332      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
333      break;
334   case OPCODE_CMP:
335      fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
336      break;
337   case OPCODE_CONT:
338      fullinst->Instruction.Opcode = TGSI_OPCODE_CONT;
339      break;
340   case OPCODE_COS:
341      fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
342      break;
343   case OPCODE_DDX:
344      fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
345      break;
346   case OPCODE_DDY:
347      fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
348      break;
349   case OPCODE_DP2:
350      fullinst->Instruction.Opcode = TGSI_OPCODE_DP2;
351      break;
352   case OPCODE_DP2A:
353      fullinst->Instruction.Opcode = TGSI_OPCODE_DP2A;
354      break;
355   case OPCODE_DP3:
356      fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
357      break;
358   case OPCODE_DP4:
359      fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
360      break;
361   case OPCODE_DPH:
362      fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
363      break;
364   case OPCODE_DST:
365      fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
366      break;
367   case OPCODE_ELSE:
368      fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
369      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
370      break;
371   case OPCODE_ENDIF:
372      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
373      break;
374   case OPCODE_ENDLOOP:
375      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
376      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
377      break;
378   case OPCODE_ENDSUB:
379      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
380      *insideSubroutine = GL_FALSE;
381      break;
382   case OPCODE_EX2:
383      fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
384      break;
385   case OPCODE_EXP:
386      fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
387      break;
388   case OPCODE_FLR:
389      fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
390      break;
391   case OPCODE_FRC:
392      fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
393      break;
394   case OPCODE_IF:
395      fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
396      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
397      break;
398   case OPCODE_TRUNC:
399      fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC;
400      break;
401   case OPCODE_KIL:
402      /* conditional */
403      fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
404      break;
405   case OPCODE_KIL_NV:
406      /* predicated */
407      assert(inst->DstReg.CondMask == COND_TR);
408      fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
409      break;
410   case OPCODE_LG2:
411      fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
412      break;
413   case OPCODE_LOG:
414      fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
415      break;
416   case OPCODE_LIT:
417      fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
418      break;
419   case OPCODE_LRP:
420      fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
421      break;
422   case OPCODE_MAD:
423      fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
424      break;
425   case OPCODE_MAX:
426      fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
427      break;
428   case OPCODE_MIN:
429      fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
430      break;
431   case OPCODE_MOV:
432      fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
433      break;
434   case OPCODE_MUL:
435      fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
436      break;
437   case OPCODE_NOISE1:
438      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
439      break;
440   case OPCODE_NOISE2:
441      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
442      break;
443   case OPCODE_NOISE3:
444      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
445      break;
446   case OPCODE_NOISE4:
447      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
448      break;
449   case OPCODE_NOP:
450      fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
451      break;
452   case OPCODE_NRM3:
453      fullinst->Instruction.Opcode = TGSI_OPCODE_NRM;
454      break;
455   case OPCODE_NRM4:
456      fullinst->Instruction.Opcode = TGSI_OPCODE_NRM4;
457      break;
458   case OPCODE_POW:
459      fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
460      break;
461   case OPCODE_RCP:
462      fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
463      break;
464   case OPCODE_RET:
465      /* If RET is used inside main (not a real subroutine) we may want
466       * to execute END instead of RET.  TBD...
467       */
468      if (1 /*  *insideSubroutine */) {
469         fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
470      }
471      else {
472         /* inside main() pseudo-function */
473         fullinst->Instruction.Opcode = TGSI_OPCODE_END;
474      }
475      break;
476   case OPCODE_RSQ:
477      fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
478      tgsi_util_set_full_src_register_sign_mode(
479         &fullinst->FullSrcRegisters[0],
480         TGSI_UTIL_SIGN_CLEAR );
481      break;
482   case OPCODE_SCS:
483      fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
484      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
485      break;
486   case OPCODE_SEQ:
487      fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
488      break;
489   case OPCODE_SGE:
490      fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
491      break;
492   case OPCODE_SGT:
493      fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
494      break;
495   case OPCODE_SIN:
496      fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
497      break;
498   case OPCODE_SLE:
499      fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
500      break;
501   case OPCODE_SLT:
502      fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
503      break;
504   case OPCODE_SNE:
505      fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
506      break;
507   case OPCODE_SSG:
508      fullinst->Instruction.Opcode = TGSI_OPCODE_SSG;
509      break;
510   case OPCODE_SUB:
511      fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
512      break;
513   case OPCODE_SWZ:
514      fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
515      break;
516   case OPCODE_TEX:
517      /* ordinary texture lookup */
518      fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
519      fullinst->Instruction.NumSrcRegs = 2;
520      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
521      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
522      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
523      break;
524   case OPCODE_TXB:
525      /* texture lookup with LOD bias */
526      fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
527      fullinst->Instruction.NumSrcRegs = 2;
528      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
529      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
530      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
531      break;
532   case OPCODE_TXD:
533      /* texture lookup with explicit partial derivatives */
534      fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
535      fullinst->Instruction.NumSrcRegs = 4;
536      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
537      /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
538      fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
539      fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
540      break;
541   case OPCODE_TXL:
542      /* texture lookup with explicit LOD */
543      fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
544      fullinst->Instruction.NumSrcRegs = 2;
545      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
546      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
547      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
548      break;
549   case OPCODE_TXP:
550      /* texture lookup with divide by Q component */
551      /* convert to TEX w/ special flag for division */
552      fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
553      fullinst->Instruction.NumSrcRegs = 2;
554      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
555      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
556      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
557      break;
558   case OPCODE_XPD:
559      fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
560      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
561      break;
562   case OPCODE_END:
563      fullinst->Instruction.Opcode = TGSI_OPCODE_END;
564      break;
565   default:
566      assert( 0 );
567   }
568}
569
570/**
571 * \param usage_mask  bitfield of TGSI_WRITEMASK_{XYZW} tokens
572 */
573static struct tgsi_full_declaration
574make_input_decl(
575   GLuint index,
576   GLboolean interpolate_info,
577   GLuint interpolate,
578   GLuint usage_mask,
579   GLboolean semantic_info,
580   GLuint semantic_name,
581   GLbitfield semantic_index,
582   GLbitfield input_flags)
583{
584   struct tgsi_full_declaration decl;
585
586   assert(semantic_name < TGSI_SEMANTIC_COUNT);
587
588   decl = tgsi_default_full_declaration();
589   decl.Declaration.File = TGSI_FILE_INPUT;
590   decl.Declaration.UsageMask = usage_mask;
591   decl.Declaration.Semantic = semantic_info;
592   decl.DeclarationRange.First = index;
593   decl.DeclarationRange.Last = index;
594   if (semantic_info) {
595      decl.Semantic.SemanticName = semantic_name;
596      decl.Semantic.SemanticIndex = semantic_index;
597   }
598   if (interpolate_info) {
599      decl.Declaration.Interpolate = interpolate;
600   }
601   if (input_flags & PROG_PARAM_BIT_CENTROID)
602      decl.Declaration.Centroid = 1;
603   if (input_flags & PROG_PARAM_BIT_INVARIANT)
604      decl.Declaration.Invariant = 1;
605
606   return decl;
607}
608
609/**
610 * \param usage_mask  bitfield of TGSI_WRITEMASK_{XYZW} tokens
611 */
612static struct tgsi_full_declaration
613make_output_decl(
614   GLuint index,
615   GLuint semantic_name,
616   GLuint semantic_index,
617   GLuint usage_mask,
618   GLbitfield output_flags)
619{
620   struct tgsi_full_declaration decl;
621
622   assert(semantic_name < TGSI_SEMANTIC_COUNT);
623
624   decl = tgsi_default_full_declaration();
625   decl.Declaration.File = TGSI_FILE_OUTPUT;
626   decl.Declaration.UsageMask = usage_mask;
627   decl.Declaration.Semantic = 1;
628   decl.DeclarationRange.First = index;
629   decl.DeclarationRange.Last = index;
630   decl.Semantic.SemanticName = semantic_name;
631   decl.Semantic.SemanticIndex = semantic_index;
632   if (output_flags & PROG_PARAM_BIT_CENTROID)
633      decl.Declaration.Centroid = 1;
634   if (output_flags & PROG_PARAM_BIT_INVARIANT)
635      decl.Declaration.Invariant = 1;
636
637   return decl;
638}
639
640
641static struct tgsi_full_declaration
642make_temp_decl(
643   GLuint start_index,
644   GLuint end_index )
645{
646   struct tgsi_full_declaration decl;
647   decl = tgsi_default_full_declaration();
648   decl.Declaration.File = TGSI_FILE_TEMPORARY;
649   decl.DeclarationRange.First = start_index;
650   decl.DeclarationRange.Last = end_index;
651   return decl;
652}
653
654static struct tgsi_full_declaration
655make_addr_decl(
656   GLuint start_index,
657   GLuint end_index )
658{
659   struct tgsi_full_declaration decl;
660
661   decl = tgsi_default_full_declaration();
662   decl.Declaration.File = TGSI_FILE_ADDRESS;
663   decl.DeclarationRange.First = start_index;
664   decl.DeclarationRange.Last = end_index;
665   return decl;
666}
667
668static struct tgsi_full_declaration
669make_sampler_decl(GLuint index)
670{
671   struct tgsi_full_declaration decl;
672   decl = tgsi_default_full_declaration();
673   decl.Declaration.File = TGSI_FILE_SAMPLER;
674   decl.DeclarationRange.First = index;
675   decl.DeclarationRange.Last = index;
676   return decl;
677}
678
679/** Reference into a constant buffer */
680static struct tgsi_full_declaration
681make_constant_decl(GLuint first, GLuint last)
682{
683   struct tgsi_full_declaration decl;
684   decl = tgsi_default_full_declaration();
685   decl.Declaration.File = TGSI_FILE_CONSTANT;
686   decl.DeclarationRange.First = first;
687   decl.DeclarationRange.Last = last;
688   return decl;
689}
690
691
692
693/**
694 * Find the temporaries which are used in the given program.
695 */
696static void
697find_temporaries(const struct gl_program *program,
698                 GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
699{
700   GLuint i, j;
701
702   for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
703      tempsUsed[i] = GL_FALSE;
704
705   for (i = 0; i < program->NumInstructions; i++) {
706      const struct prog_instruction *inst = program->Instructions + i;
707      const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
708      for (j = 0; j < n; j++) {
709         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
710            tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
711         if (inst->DstReg.File == PROGRAM_TEMPORARY)
712            tempsUsed[inst->DstReg.Index] = GL_TRUE;
713      }
714   }
715}
716
717
718
719
720/**
721 * Translate Mesa program to TGSI format.
722 * \param program  the program to translate
723 * \param numInputs  number of input registers used
724 * \param inputMapping  maps Mesa fragment program inputs to TGSI generic
725 *                      input indexes
726 * \param inputSemanticName  the TGSI_SEMANTIC flag for each input
727 * \param inputSemanticIndex  the semantic index (ex: which texcoord) for each input
728 * \param interpMode  the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
729
730 * \param numOutputs  number of output registers used
731 * \param outputMapping  maps Mesa fragment program outputs to TGSI
732 *                       generic outputs
733 * \param outputSemanticName  the TGSI_SEMANTIC flag for each output
734 * \param outputSemanticIndex  the semantic index (ex: which texcoord) for each output
735 * \param tokens  array to store translated tokens in
736 * \param maxTokens  size of the tokens array
737 *
738 * \return number of tokens placed in 'tokens' buffer, or zero if error
739 */
740GLuint
741st_translate_mesa_program(
742   uint procType,
743   const struct gl_program *program,
744   GLuint numInputs,
745   const GLuint inputMapping[],
746   const ubyte inputSemanticName[],
747   const ubyte inputSemanticIndex[],
748   const GLuint interpMode[],
749   const GLbitfield inputFlags[],
750   GLuint numOutputs,
751   const GLuint outputMapping[],
752   const ubyte outputSemanticName[],
753   const ubyte outputSemanticIndex[],
754   const GLbitfield outputFlags[],
755   struct tgsi_token *tokens,
756   GLuint maxTokens )
757{
758   GLuint i;
759   GLuint ti;  /* token index */
760   struct tgsi_header *header;
761   struct tgsi_processor *processor;
762   struct tgsi_full_instruction fullinst;
763   GLuint preamble_size = 0;
764   GLuint immediates[1000];
765   GLuint numImmediates = 0;
766   GLboolean insideSubroutine = GL_FALSE;
767   GLboolean indirectAccess = GL_FALSE;
768
769   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
770          procType == TGSI_PROCESSOR_VERTEX);
771
772   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
773
774   header = (struct tgsi_header *) &tokens[1];
775   *header = tgsi_build_header();
776
777   processor = (struct tgsi_processor *) &tokens[2];
778   *processor = tgsi_build_processor( procType, header );
779
780   ti = 3;
781
782   /*
783    * Declare input attributes.
784    */
785   if (procType == TGSI_PROCESSOR_FRAGMENT) {
786      for (i = 0; i < numInputs; i++) {
787         struct tgsi_full_declaration fulldecl;
788         fulldecl = make_input_decl(i,
789                                    GL_TRUE, interpMode[i],
790                                    TGSI_WRITEMASK_XYZW,
791                                    GL_TRUE, inputSemanticName[i],
792                                    inputSemanticIndex[i],
793                                    inputFlags[i]);
794         ti += tgsi_build_full_declaration(&fulldecl,
795                                           &tokens[ti],
796                                           header,
797                                           maxTokens - ti );
798      }
799   }
800   else {
801      /* vertex prog */
802      /* XXX: this could probaby be merged with the clause above.
803       * the only difference is the semantic tags.
804       */
805      for (i = 0; i < numInputs; i++) {
806         struct tgsi_full_declaration fulldecl;
807         fulldecl = make_input_decl(i,
808                                    GL_FALSE, 0,
809                                    TGSI_WRITEMASK_XYZW,
810                                    GL_FALSE, 0, 0,
811                                    inputFlags[i]);
812         ti += tgsi_build_full_declaration(&fulldecl,
813                                           &tokens[ti],
814                                           header,
815                                           maxTokens - ti );
816      }
817   }
818
819   /*
820    * Declare output attributes.
821    */
822   if (procType == TGSI_PROCESSOR_FRAGMENT) {
823      for (i = 0; i < numOutputs; i++) {
824         struct tgsi_full_declaration fulldecl;
825         switch (outputSemanticName[i]) {
826         case TGSI_SEMANTIC_POSITION:
827            fulldecl = make_output_decl(i,
828                                        TGSI_SEMANTIC_POSITION, /* Z / Depth */
829                                        outputSemanticIndex[i],
830                                        TGSI_WRITEMASK_Z,
831                                        outputFlags[i]);
832            break;
833         case TGSI_SEMANTIC_COLOR:
834            fulldecl = make_output_decl(i,
835                                        TGSI_SEMANTIC_COLOR,
836                                        outputSemanticIndex[i],
837                                        TGSI_WRITEMASK_XYZW,
838                                        outputFlags[i]);
839            break;
840         default:
841            assert(0);
842            return 0;
843         }
844         ti += tgsi_build_full_declaration(&fulldecl,
845                                           &tokens[ti],
846                                           header,
847                                           maxTokens - ti );
848      }
849   }
850   else {
851      /* vertex prog */
852      for (i = 0; i < numOutputs; i++) {
853         struct tgsi_full_declaration fulldecl;
854         fulldecl = make_output_decl(i,
855                                     outputSemanticName[i],
856                                     outputSemanticIndex[i],
857                                     TGSI_WRITEMASK_XYZW,
858                                     outputFlags[i]);
859         ti += tgsi_build_full_declaration(&fulldecl,
860                                           &tokens[ti],
861                                           header,
862                                           maxTokens - ti );
863      }
864   }
865
866   /* temporary decls */
867   {
868      GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
869      GLboolean inside_range = GL_FALSE;
870      GLuint start_range = 0;
871
872      find_temporaries(program, tempsUsed);
873      tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
874      for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
875         if (tempsUsed[i] && !inside_range) {
876            inside_range = GL_TRUE;
877            start_range = i;
878         }
879         else if (!tempsUsed[i] && inside_range) {
880            struct tgsi_full_declaration fulldecl;
881
882            inside_range = GL_FALSE;
883            fulldecl = make_temp_decl( start_range, i - 1 );
884            ti += tgsi_build_full_declaration(
885               &fulldecl,
886               &tokens[ti],
887               header,
888               maxTokens - ti );
889         }
890      }
891   }
892
893   /* Declare address register.
894   */
895   if (program->NumAddressRegs > 0) {
896      struct tgsi_full_declaration fulldecl;
897
898      assert( program->NumAddressRegs == 1 );
899
900      fulldecl = make_addr_decl( 0, 0 );
901      ti += tgsi_build_full_declaration(
902         &fulldecl,
903         &tokens[ti],
904         header,
905         maxTokens - ti );
906
907      indirectAccess = GL_TRUE;
908   }
909
910   /* immediates/literals */
911   memset(immediates, ~0, sizeof(immediates));
912
913   /* Emit immediates only when there is no address register in use.
914    * FIXME: Be smarter and recognize param arrays -- indirect addressing is
915    *        only valid within the referenced array.
916    */
917   if (program->Parameters && !indirectAccess) {
918      for (i = 0; i < program->Parameters->NumParameters; i++) {
919         if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
920            struct tgsi_full_immediate fullimm;
921
922            fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
923            ti += tgsi_build_full_immediate(
924               &fullimm,
925               &tokens[ti],
926               header,
927               maxTokens - ti );
928            immediates[i] = numImmediates;
929            numImmediates++;
930         }
931      }
932   }
933
934   /* constant buffer refs */
935   if (program->Parameters) {
936      GLint start = -1, end = -1;
937
938      for (i = 0; i < program->Parameters->NumParameters; i++) {
939         GLboolean emit = (i == program->Parameters->NumParameters - 1);
940         GLboolean matches;
941
942         switch (program->Parameters->Parameters[i].Type) {
943         case PROGRAM_ENV_PARAM:
944         case PROGRAM_STATE_VAR:
945         case PROGRAM_NAMED_PARAM:
946         case PROGRAM_UNIFORM:
947            matches = GL_TRUE;
948            break;
949         case PROGRAM_CONSTANT:
950            matches = indirectAccess;
951            break;
952         default:
953            matches = GL_FALSE;
954         }
955
956         if (matches) {
957            if (start == -1) {
958               /* begin a sequence */
959               start = i;
960               end = i;
961            }
962            else {
963               /* continue sequence */
964               end = i;
965            }
966         }
967         else {
968            if (start != -1) {
969               /* end of sequence */
970               emit = GL_TRUE;
971            }
972         }
973
974         if (emit && start >= 0) {
975            struct tgsi_full_declaration fulldecl;
976
977            fulldecl = make_constant_decl( start, end );
978            ti += tgsi_build_full_declaration(
979               &fulldecl,
980               &tokens[ti],
981               header,
982               maxTokens - ti );
983            start = end = -1;
984         }
985      }
986   }
987
988   /* texture samplers */
989   for (i = 0; i < 8; i++) {
990      if (program->SamplersUsed & (1 << i)) {
991         struct tgsi_full_declaration fulldecl;
992
993         fulldecl = make_sampler_decl( i );
994         ti += tgsi_build_full_declaration(
995            &fulldecl,
996            &tokens[ti],
997            header,
998            maxTokens - ti );
999      }
1000   }
1001
1002   for (i = 0; i < program->NumInstructions; i++) {
1003      compile_instruction(
1004         &program->Instructions[i],
1005         &fullinst,
1006         inputMapping,
1007         outputMapping,
1008         immediates,
1009         indirectAccess,
1010         preamble_size,
1011         procType,
1012         &insideSubroutine );
1013
1014      ti += tgsi_build_full_instruction(
1015         &fullinst,
1016         &tokens[ti],
1017         header,
1018         maxTokens - ti );
1019   }
1020
1021#if DEBUG
1022   if(!tgsi_sanity_check(tokens)) {
1023      debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
1024      debug_printf("\nOriginal program:\n%s", program->String);
1025      debug_printf("\nMesa program:\n");
1026      _mesa_print_program(program);
1027      debug_printf("\nTGSI program:\n");
1028      tgsi_dump(tokens, 0);
1029      assert(0);
1030   }
1031#endif
1032
1033   return ti;
1034}
1035