st_mesa_to_tgsi.c revision 3225bc84932f08a52db7025367ae206a9d2f8fef
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_DP3:
350      fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
351      break;
352   case OPCODE_DP4:
353      fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
354      break;
355   case OPCODE_DPH:
356      fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
357      break;
358   case OPCODE_DST:
359      fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
360      break;
361   case OPCODE_ELSE:
362      fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
363      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
364      break;
365   case OPCODE_ENDIF:
366      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
367      break;
368   case OPCODE_ENDLOOP:
369      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
370      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
371      break;
372   case OPCODE_ENDSUB:
373      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
374      *insideSubroutine = GL_FALSE;
375      break;
376   case OPCODE_EX2:
377      fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
378      break;
379   case OPCODE_EXP:
380      fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
381      break;
382   case OPCODE_FLR:
383      fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
384      break;
385   case OPCODE_FRC:
386      fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
387      break;
388   case OPCODE_IF:
389      fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
390      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
391      break;
392   case OPCODE_TRUNC:
393      fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC;
394      break;
395   case OPCODE_KIL:
396      /* conditional */
397      fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
398      break;
399   case OPCODE_KIL_NV:
400      /* predicated */
401      assert(inst->DstReg.CondMask == COND_TR);
402      fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
403      break;
404   case OPCODE_LG2:
405      fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
406      break;
407   case OPCODE_LOG:
408      fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
409      break;
410   case OPCODE_LIT:
411      fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
412      break;
413   case OPCODE_LRP:
414      fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
415      break;
416   case OPCODE_MAD:
417      fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
418      break;
419   case OPCODE_MAX:
420      fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
421      break;
422   case OPCODE_MIN:
423      fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
424      break;
425   case OPCODE_MOV:
426      fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
427      break;
428   case OPCODE_MUL:
429      fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
430      break;
431   case OPCODE_NOISE1:
432      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
433      break;
434   case OPCODE_NOISE2:
435      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
436      break;
437   case OPCODE_NOISE3:
438      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
439      break;
440   case OPCODE_NOISE4:
441      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
442      break;
443   case OPCODE_NOP:
444      fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
445      break;
446   case OPCODE_POW:
447      fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
448      break;
449   case OPCODE_RCP:
450      fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
451      break;
452   case OPCODE_RET:
453      /* If RET is used inside main (not a real subroutine) we may want
454       * to execute END instead of RET.  TBD...
455       */
456      if (1 /*  *insideSubroutine */) {
457         fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
458      }
459      else {
460         /* inside main() pseudo-function */
461         fullinst->Instruction.Opcode = TGSI_OPCODE_END;
462      }
463      break;
464   case OPCODE_RSQ:
465      fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
466      tgsi_util_set_full_src_register_sign_mode(
467         &fullinst->FullSrcRegisters[0],
468         TGSI_UTIL_SIGN_CLEAR );
469      break;
470   case OPCODE_SCS:
471      fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
472      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
473      break;
474   case OPCODE_SEQ:
475      fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
476      break;
477   case OPCODE_SGE:
478      fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
479      break;
480   case OPCODE_SGT:
481      fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
482      break;
483   case OPCODE_SIN:
484      fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
485      break;
486   case OPCODE_SLE:
487      fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
488      break;
489   case OPCODE_SLT:
490      fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
491      break;
492   case OPCODE_SNE:
493      fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
494      break;
495   case OPCODE_SUB:
496      fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
497      break;
498   case OPCODE_SWZ:
499      fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
500      break;
501   case OPCODE_TEX:
502      /* ordinary texture lookup */
503      fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
504      fullinst->Instruction.NumSrcRegs = 2;
505      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
506      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
507      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
508      break;
509   case OPCODE_TXB:
510      /* texture lookup with LOD bias */
511      fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
512      fullinst->Instruction.NumSrcRegs = 2;
513      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
514      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
515      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
516      break;
517   case OPCODE_TXD:
518      /* texture lookup with explicit partial derivatives */
519      fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
520      fullinst->Instruction.NumSrcRegs = 4;
521      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
522      /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
523      fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
524      fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
525      break;
526   case OPCODE_TXL:
527      /* texture lookup with explicit LOD */
528      fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
529      fullinst->Instruction.NumSrcRegs = 2;
530      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
531      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
532      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
533      break;
534   case OPCODE_TXP:
535      /* texture lookup with divide by Q component */
536      /* convert to TEX w/ special flag for division */
537      fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
538      fullinst->Instruction.NumSrcRegs = 2;
539      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
540      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
541      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
542      break;
543   case OPCODE_XPD:
544      fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
545      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
546      break;
547   case OPCODE_END:
548      fullinst->Instruction.Opcode = TGSI_OPCODE_END;
549      break;
550   default:
551      assert( 0 );
552   }
553}
554
555/**
556 * \param usage_mask  bitfield of TGSI_WRITEMASK_{XYZW} tokens
557 */
558static struct tgsi_full_declaration
559make_input_decl(
560   GLuint index,
561   GLboolean interpolate_info,
562   GLuint interpolate,
563   GLuint usage_mask,
564   GLboolean semantic_info,
565   GLuint semantic_name,
566   GLbitfield semantic_index )
567{
568   struct tgsi_full_declaration decl;
569
570   assert(semantic_name < TGSI_SEMANTIC_COUNT);
571
572   decl = tgsi_default_full_declaration();
573   decl.Declaration.File = TGSI_FILE_INPUT;
574   decl.Declaration.UsageMask = usage_mask;
575   decl.Declaration.Semantic = semantic_info;
576   decl.DeclarationRange.First = index;
577   decl.DeclarationRange.Last = index;
578   if (semantic_info) {
579      decl.Semantic.SemanticName = semantic_name;
580      decl.Semantic.SemanticIndex = semantic_index;
581   }
582   if (interpolate_info) {
583      decl.Declaration.Interpolate = interpolate;
584   }
585
586   return decl;
587}
588
589/**
590 * \param usage_mask  bitfield of TGSI_WRITEMASK_{XYZW} tokens
591 */
592static struct tgsi_full_declaration
593make_output_decl(
594   GLuint index,
595   GLuint semantic_name,
596   GLuint semantic_index,
597   GLbitfield usage_mask )
598{
599   struct tgsi_full_declaration decl;
600
601   assert(semantic_name < TGSI_SEMANTIC_COUNT);
602
603   decl = tgsi_default_full_declaration();
604   decl.Declaration.File = TGSI_FILE_OUTPUT;
605   decl.Declaration.UsageMask = usage_mask;
606   decl.Declaration.Semantic = 1;
607   decl.DeclarationRange.First = index;
608   decl.DeclarationRange.Last = index;
609   decl.Semantic.SemanticName = semantic_name;
610   decl.Semantic.SemanticIndex = semantic_index;
611
612   return decl;
613}
614
615
616static struct tgsi_full_declaration
617make_temp_decl(
618   GLuint start_index,
619   GLuint end_index )
620{
621   struct tgsi_full_declaration decl;
622   decl = tgsi_default_full_declaration();
623   decl.Declaration.File = TGSI_FILE_TEMPORARY;
624   decl.DeclarationRange.First = start_index;
625   decl.DeclarationRange.Last = end_index;
626   return decl;
627}
628
629static struct tgsi_full_declaration
630make_addr_decl(
631   GLuint start_index,
632   GLuint end_index )
633{
634   struct tgsi_full_declaration decl;
635
636   decl = tgsi_default_full_declaration();
637   decl.Declaration.File = TGSI_FILE_ADDRESS;
638   decl.DeclarationRange.First = start_index;
639   decl.DeclarationRange.Last = end_index;
640   return decl;
641}
642
643static struct tgsi_full_declaration
644make_sampler_decl(GLuint index)
645{
646   struct tgsi_full_declaration decl;
647   decl = tgsi_default_full_declaration();
648   decl.Declaration.File = TGSI_FILE_SAMPLER;
649   decl.DeclarationRange.First = index;
650   decl.DeclarationRange.Last = index;
651   return decl;
652}
653
654/** Reference into a constant buffer */
655static struct tgsi_full_declaration
656make_constant_decl(GLuint first, GLuint last)
657{
658   struct tgsi_full_declaration decl;
659   decl = tgsi_default_full_declaration();
660   decl.Declaration.File = TGSI_FILE_CONSTANT;
661   decl.DeclarationRange.First = first;
662   decl.DeclarationRange.Last = last;
663   return decl;
664}
665
666
667
668/**
669 * Find the temporaries which are used in the given program.
670 */
671static void
672find_temporaries(const struct gl_program *program,
673                 GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
674{
675   GLuint i, j;
676
677   for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
678      tempsUsed[i] = GL_FALSE;
679
680   for (i = 0; i < program->NumInstructions; i++) {
681      const struct prog_instruction *inst = program->Instructions + i;
682      const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
683      for (j = 0; j < n; j++) {
684         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
685            tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
686         if (inst->DstReg.File == PROGRAM_TEMPORARY)
687            tempsUsed[inst->DstReg.Index] = GL_TRUE;
688      }
689   }
690}
691
692
693
694
695/**
696 * Translate Mesa program to TGSI format.
697 * \param program  the program to translate
698 * \param numInputs  number of input registers used
699 * \param inputMapping  maps Mesa fragment program inputs to TGSI generic
700 *                      input indexes
701 * \param inputSemanticName  the TGSI_SEMANTIC flag for each input
702 * \param inputSemanticIndex  the semantic index (ex: which texcoord) for each input
703 * \param interpMode  the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
704
705 * \param numOutputs  number of output registers used
706 * \param outputMapping  maps Mesa fragment program outputs to TGSI
707 *                       generic outputs
708 * \param outputSemanticName  the TGSI_SEMANTIC flag for each output
709 * \param outputSemanticIndex  the semantic index (ex: which texcoord) for each output
710 * \param tokens  array to store translated tokens in
711 * \param maxTokens  size of the tokens array
712 *
713 * \return number of tokens placed in 'tokens' buffer, or zero if error
714 */
715GLuint
716st_translate_mesa_program(
717   uint procType,
718   const struct gl_program *program,
719   GLuint numInputs,
720   const GLuint inputMapping[],
721   const ubyte inputSemanticName[],
722   const ubyte inputSemanticIndex[],
723   const GLuint interpMode[],
724   GLuint numOutputs,
725   const GLuint outputMapping[],
726   const ubyte outputSemanticName[],
727   const ubyte outputSemanticIndex[],
728   struct tgsi_token *tokens,
729   GLuint maxTokens )
730{
731   GLuint i;
732   GLuint ti;  /* token index */
733   struct tgsi_header *header;
734   struct tgsi_processor *processor;
735   struct tgsi_full_instruction fullinst;
736   GLuint preamble_size = 0;
737   GLuint immediates[1000];
738   GLuint numImmediates = 0;
739   GLboolean insideSubroutine = GL_FALSE;
740   GLboolean indirectAccess = GL_FALSE;
741
742   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
743          procType == TGSI_PROCESSOR_VERTEX);
744
745   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
746
747   header = (struct tgsi_header *) &tokens[1];
748   *header = tgsi_build_header();
749
750   processor = (struct tgsi_processor *) &tokens[2];
751   *processor = tgsi_build_processor( procType, header );
752
753   ti = 3;
754
755   /*
756    * Declare input attributes.
757    */
758   if (procType == TGSI_PROCESSOR_FRAGMENT) {
759      for (i = 0; i < numInputs; i++) {
760         struct tgsi_full_declaration fulldecl;
761         fulldecl = make_input_decl(i,
762                                    GL_TRUE, interpMode[i],
763                                    TGSI_WRITEMASK_XYZW,
764                                    GL_TRUE, inputSemanticName[i],
765                                    inputSemanticIndex[i]);
766         ti += tgsi_build_full_declaration(&fulldecl,
767                                           &tokens[ti],
768                                           header,
769                                           maxTokens - ti );
770      }
771   }
772   else {
773      /* vertex prog */
774      /* XXX: this could probaby be merged with the clause above.
775       * the only difference is the semantic tags.
776       */
777      for (i = 0; i < numInputs; i++) {
778         struct tgsi_full_declaration fulldecl;
779         fulldecl = make_input_decl(i,
780                                    GL_FALSE, 0,
781                                    TGSI_WRITEMASK_XYZW,
782                                    GL_FALSE, 0, 0);
783         ti += tgsi_build_full_declaration(&fulldecl,
784                                           &tokens[ti],
785                                           header,
786                                           maxTokens - ti );
787      }
788   }
789
790   /*
791    * Declare output attributes.
792    */
793   if (procType == TGSI_PROCESSOR_FRAGMENT) {
794      for (i = 0; i < numOutputs; i++) {
795         struct tgsi_full_declaration fulldecl;
796         switch (outputSemanticName[i]) {
797         case TGSI_SEMANTIC_POSITION:
798            fulldecl = make_output_decl(i,
799                                        TGSI_SEMANTIC_POSITION, /* Z / Depth */
800                                        outputSemanticIndex[i],
801                                        TGSI_WRITEMASK_Z );
802            break;
803         case TGSI_SEMANTIC_COLOR:
804            fulldecl = make_output_decl(i,
805                                        TGSI_SEMANTIC_COLOR,
806                                        outputSemanticIndex[i],
807                                        TGSI_WRITEMASK_XYZW );
808            break;
809         default:
810            assert(0);
811            return 0;
812         }
813         ti += tgsi_build_full_declaration(&fulldecl,
814                                           &tokens[ti],
815                                           header,
816                                           maxTokens - ti );
817      }
818   }
819   else {
820      /* vertex prog */
821      for (i = 0; i < numOutputs; i++) {
822         struct tgsi_full_declaration fulldecl;
823         fulldecl = make_output_decl(i,
824                                     outputSemanticName[i],
825                                     outputSemanticIndex[i],
826                                     TGSI_WRITEMASK_XYZW );
827         ti += tgsi_build_full_declaration(&fulldecl,
828                                           &tokens[ti],
829                                           header,
830                                           maxTokens - ti );
831      }
832   }
833
834   /* temporary decls */
835   {
836      GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
837      GLboolean inside_range = GL_FALSE;
838      GLuint start_range = 0;
839
840      find_temporaries(program, tempsUsed);
841      tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
842      for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
843         if (tempsUsed[i] && !inside_range) {
844            inside_range = GL_TRUE;
845            start_range = i;
846         }
847         else if (!tempsUsed[i] && inside_range) {
848            struct tgsi_full_declaration fulldecl;
849
850            inside_range = GL_FALSE;
851            fulldecl = make_temp_decl( start_range, i - 1 );
852            ti += tgsi_build_full_declaration(
853               &fulldecl,
854               &tokens[ti],
855               header,
856               maxTokens - ti );
857         }
858      }
859   }
860
861   /* Declare address register.
862   */
863   if (program->NumAddressRegs > 0) {
864      struct tgsi_full_declaration fulldecl;
865
866      assert( program->NumAddressRegs == 1 );
867
868      fulldecl = make_addr_decl( 0, 0 );
869      ti += tgsi_build_full_declaration(
870         &fulldecl,
871         &tokens[ti],
872         header,
873         maxTokens - ti );
874
875      indirectAccess = GL_TRUE;
876   }
877
878   /* immediates/literals */
879   memset(immediates, ~0, sizeof(immediates));
880
881   /* Emit immediates only when there is no address register in use.
882    * FIXME: Be smarter and recognize param arrays -- indirect addressing is
883    *        only valid within the referenced array.
884    */
885   if (program->Parameters && !indirectAccess) {
886      for (i = 0; i < program->Parameters->NumParameters; i++) {
887         if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
888            struct tgsi_full_immediate fullimm;
889
890            fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
891            ti += tgsi_build_full_immediate(
892               &fullimm,
893               &tokens[ti],
894               header,
895               maxTokens - ti );
896            immediates[i] = numImmediates;
897            numImmediates++;
898         }
899      }
900   }
901
902   /* constant buffer refs */
903   if (program->Parameters) {
904      GLint start = -1, end = -1;
905
906      for (i = 0; i < program->Parameters->NumParameters; i++) {
907         GLboolean emit = (i == program->Parameters->NumParameters - 1);
908         GLboolean matches;
909
910         switch (program->Parameters->Parameters[i].Type) {
911         case PROGRAM_ENV_PARAM:
912         case PROGRAM_STATE_VAR:
913         case PROGRAM_NAMED_PARAM:
914         case PROGRAM_UNIFORM:
915            matches = GL_TRUE;
916            break;
917         case PROGRAM_CONSTANT:
918            matches = indirectAccess;
919            break;
920         default:
921            matches = GL_FALSE;
922         }
923
924         if (matches) {
925            if (start == -1) {
926               /* begin a sequence */
927               start = i;
928               end = i;
929            }
930            else {
931               /* continue sequence */
932               end = i;
933            }
934         }
935         else {
936            if (start != -1) {
937               /* end of sequence */
938               emit = GL_TRUE;
939            }
940         }
941
942         if (emit && start >= 0) {
943            struct tgsi_full_declaration fulldecl;
944
945            fulldecl = make_constant_decl( start, end );
946            ti += tgsi_build_full_declaration(
947               &fulldecl,
948               &tokens[ti],
949               header,
950               maxTokens - ti );
951            start = end = -1;
952         }
953      }
954   }
955
956   /* texture samplers */
957   for (i = 0; i < 8; i++) {
958      if (program->SamplersUsed & (1 << i)) {
959         struct tgsi_full_declaration fulldecl;
960
961         fulldecl = make_sampler_decl( i );
962         ti += tgsi_build_full_declaration(
963            &fulldecl,
964            &tokens[ti],
965            header,
966            maxTokens - ti );
967      }
968   }
969
970   for (i = 0; i < program->NumInstructions; i++) {
971      compile_instruction(
972         &program->Instructions[i],
973         &fullinst,
974         inputMapping,
975         outputMapping,
976         immediates,
977         indirectAccess,
978         preamble_size,
979         procType,
980         &insideSubroutine );
981
982      ti += tgsi_build_full_instruction(
983         &fullinst,
984         &tokens[ti],
985         header,
986         maxTokens - ti );
987   }
988
989#if DEBUG
990   if(!tgsi_sanity_check(tokens)) {
991      debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
992      debug_printf("\nOriginal program:\n%s", program->String);
993      debug_printf("\nMesa program:\n");
994      _mesa_print_program(program);
995      debug_printf("\nTGSI program:\n");
996      tgsi_dump(tokens, 0);
997      assert(0);
998   }
999#endif
1000
1001   return ti;
1002}
1003