st_mesa_to_tgsi.c revision 8978627ad0e236796758d4912822b3428a649987
1/**************************************************************************
2 *
3 * Copyright 2007 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 "pipe/tgsi/util/tgsi_parse.h"
36#include "pipe/tgsi/util/tgsi_build.h"
37#include "pipe/tgsi/util/tgsi_util.h"
38#include "st_mesa_to_tgsi.h"
39#include "shader/prog_instruction.h"
40#include "shader/prog_parameter.h"
41
42#define TGSI_DEBUG 0
43
44
45/*
46 * Map mesa register file to TGSI register file.
47 */
48static GLuint
49map_register_file(
50   enum register_file file )
51{
52   switch( file ) {
53   case PROGRAM_UNDEFINED:
54      return TGSI_FILE_NULL;
55   case PROGRAM_TEMPORARY:
56      return TGSI_FILE_TEMPORARY;
57   //case PROGRAM_LOCAL_PARAM:
58   //case PROGRAM_ENV_PARAM:
59   case PROGRAM_STATE_VAR:
60   case PROGRAM_NAMED_PARAM:
61   case PROGRAM_UNIFORM:
62      return TGSI_FILE_CONSTANT;
63   case PROGRAM_CONSTANT:
64      return TGSI_FILE_IMMEDIATE;
65   case PROGRAM_INPUT:
66      return TGSI_FILE_INPUT;
67   case PROGRAM_OUTPUT:
68      return TGSI_FILE_OUTPUT;
69   case PROGRAM_ADDRESS:
70      return TGSI_FILE_ADDRESS;
71   default:
72      assert( 0 );
73      return TGSI_FILE_NULL;
74   }
75}
76
77/**
78 * Map mesa register file index to TGSI index.
79 * Take special care when processing input and output indices.
80 * \param file  one of TGSI_FILE_x
81 * \param index  the mesa register file index
82 * \param inputMapping  maps Mesa input indexes to TGSI input indexes
83 * \param outputMapping  maps Mesa output indexes to TGSI output indexes
84 */
85static GLuint
86map_register_file_index(
87   GLuint file,
88   GLuint index,
89   const GLuint inputMapping[],
90   const GLuint outputMapping[],
91   const GLuint immediateMapping[])
92{
93   switch( file ) {
94   case TGSI_FILE_INPUT:
95      /* inputs are mapped according to the user-defined map */
96      return inputMapping[index];
97
98   case TGSI_FILE_OUTPUT:
99      return outputMapping[index];
100
101   case TGSI_FILE_IMMEDIATE:
102      return immediateMapping[index];
103
104   default:
105      return index;
106   }
107}
108
109/*
110 * Map mesa texture target to TGSI texture target.
111 */
112static GLuint
113map_texture_target(
114   GLuint textarget )
115{
116   switch( textarget ) {
117   case TEXTURE_1D_INDEX:
118      return TGSI_TEXTURE_1D;
119   case TEXTURE_2D_INDEX:
120      return TGSI_TEXTURE_2D;
121   case TEXTURE_3D_INDEX:
122      return TGSI_TEXTURE_3D;
123   case TEXTURE_CUBE_INDEX:
124      return TGSI_TEXTURE_CUBE;
125   case TEXTURE_RECT_INDEX:
126      return TGSI_TEXTURE_RECT;
127   default:
128      assert( 0 );
129   }
130
131   return TGSI_TEXTURE_1D;
132}
133
134static GLuint
135convert_sat(
136   GLuint sat )
137{
138   switch( sat ) {
139   case SATURATE_OFF:
140      return TGSI_SAT_NONE;
141   case SATURATE_ZERO_ONE:
142      return TGSI_SAT_ZERO_ONE;
143   case SATURATE_PLUS_MINUS_ONE:
144      return TGSI_SAT_MINUS_PLUS_ONE;
145   default:
146      assert( 0 );
147      return TGSI_SAT_NONE;
148   }
149}
150
151static GLuint
152convert_writemask(
153   GLuint writemask )
154{
155   assert( WRITEMASK_X == TGSI_WRITEMASK_X );
156   assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
157   assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
158   assert( WRITEMASK_W == TGSI_WRITEMASK_W );
159   assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
160
161   return writemask;
162}
163
164static struct tgsi_full_immediate
165make_immediate(const float *value, uint size)
166{
167   struct tgsi_full_immediate imm;
168   imm.Immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
169   imm.Immediate.Size = 1 + size; /* one for the token itself */
170   imm.Immediate.DataType = TGSI_IMM_FLOAT32;
171   imm.u.ImmediateFloat32 = (struct tgsi_immediate_float32 *) value;
172   return imm;
173}
174
175static void
176compile_instruction(
177   const struct prog_instruction *inst,
178   struct tgsi_full_instruction *fullinst,
179   const GLuint inputMapping[],
180   const GLuint outputMapping[],
181   const GLuint immediateMapping[],
182   GLuint preamble_size,
183   GLuint processor )
184{
185   GLuint i;
186   struct tgsi_full_dst_register *fulldst;
187   struct tgsi_full_src_register *fullsrc;
188
189   *fullinst = tgsi_default_full_instruction();
190
191   fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
192   fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode );
193   fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
194
195   fulldst = &fullinst->FullDstRegisters[0];
196   fulldst->DstRegister.File = map_register_file( inst->DstReg.File );
197   fulldst->DstRegister.Index = map_register_file_index(
198      fulldst->DstRegister.File,
199      inst->DstReg.Index,
200      inputMapping,
201      outputMapping,
202      NULL
203      );
204   fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
205
206   for( i = 0; i < fullinst->Instruction.NumSrcRegs; i++ ) {
207      GLuint j;
208
209      fullsrc = &fullinst->FullSrcRegisters[i];
210      fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File );
211      fullsrc->SrcRegister.Index = map_register_file_index(
212         fullsrc->SrcRegister.File,
213         inst->SrcReg[i].Index,
214         inputMapping,
215         outputMapping,
216         immediateMapping);
217
218      for( j = 0; j < 4; j++ ) {
219         GLuint swz;
220
221         swz = GET_SWZ( inst->SrcReg[i].Swizzle, j );
222         if( swz > SWIZZLE_W ) {
223            tgsi_util_set_src_register_extswizzle(
224               &fullsrc->SrcRegisterExtSwz,
225               swz,
226               j );
227         }
228         else {
229            tgsi_util_set_src_register_swizzle(
230               &fullsrc->SrcRegister,
231               swz,
232               j );
233         }
234      }
235
236      if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
237         fullsrc->SrcRegister.Negate = 1;
238      }
239      else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
240         if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
241            fullsrc->SrcRegisterExtSwz.NegateX = 1;
242         }
243         if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
244            fullsrc->SrcRegisterExtSwz.NegateY = 1;
245         }
246         if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
247            fullsrc->SrcRegisterExtSwz.NegateZ = 1;
248         }
249         if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
250            fullsrc->SrcRegisterExtSwz.NegateW = 1;
251         }
252      }
253
254      if( inst->SrcReg[i].Abs ) {
255         fullsrc->SrcRegisterExtMod.Absolute = 1;
256      }
257
258      if( inst->SrcReg[i].NegateAbs ) {
259         fullsrc->SrcRegisterExtMod.Negate = 1;
260      }
261
262      if( inst->SrcReg[i].RelAddr ) {
263         fullsrc->SrcRegister.Indirect = 1;
264
265         fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
266         fullsrc->SrcRegisterInd.Index = 0;
267      }
268   }
269
270   switch( inst->Opcode ) {
271   case OPCODE_ARL:
272      fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
273      break;
274   case OPCODE_ABS:
275      fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
276      break;
277   case OPCODE_ADD:
278      fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
279      break;
280   case OPCODE_BGNLOOP:
281      fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2;
282      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
283      break;
284   case OPCODE_BGNSUB:
285      fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
286      break;
287   case OPCODE_BRA:
288      fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
289      break;
290   case OPCODE_BRK:
291      fullinst->Instruction.Opcode = TGSI_OPCODE_BRK;
292      break;
293   case OPCODE_CAL:
294      fullinst->Instruction.Opcode = TGSI_OPCODE_CAL;
295      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
296      break;
297   case OPCODE_CMP:
298      fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
299      break;
300   case OPCODE_CONT:
301      fullinst->Instruction.Opcode = TGSI_OPCODE_CONT;
302      break;
303   case OPCODE_COS:
304      fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
305      break;
306   case OPCODE_DDX:
307      fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
308      break;
309   case OPCODE_DDY:
310      fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
311      break;
312   case OPCODE_DP3:
313      fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
314      break;
315   case OPCODE_DP4:
316      fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
317      break;
318   case OPCODE_DPH:
319      fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
320      break;
321   case OPCODE_DST:
322      fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
323      break;
324   case OPCODE_ELSE:
325      fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
326      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
327      break;
328   case OPCODE_ENDIF:
329      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
330      break;
331   case OPCODE_ENDLOOP:
332      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
333      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
334      break;
335   case OPCODE_ENDSUB:
336      fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
337      break;
338   case OPCODE_EX2:
339      fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
340      break;
341   case OPCODE_EXP:
342      fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
343      break;
344   case OPCODE_FLR:
345      fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
346      break;
347   case OPCODE_FRC:
348      fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
349      break;
350   case OPCODE_IF:
351      fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
352      fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
353      break;
354   case OPCODE_INT:
355      fullinst->Instruction.Opcode = TGSI_OPCODE_INT;
356      break;
357   case OPCODE_KIL:
358      /* predicated w/ a register */
359      fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
360      break;
361   case OPCODE_KIL_NV:
362      /* unpredicated */
363      assert(inst->DstReg.CondMask == COND_TR);
364      fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
365      break;
366   case OPCODE_LG2:
367      fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
368      break;
369   case OPCODE_LOG:
370      fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
371      break;
372   case OPCODE_LIT:
373      fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
374      break;
375   case OPCODE_LRP:
376      fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
377      break;
378   case OPCODE_MAD:
379      fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
380      break;
381   case OPCODE_MAX:
382      fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
383      break;
384   case OPCODE_MIN:
385      fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
386      break;
387   case OPCODE_MOV:
388      fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
389      break;
390   case OPCODE_MUL:
391      fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
392      break;
393   case OPCODE_NOISE1:
394      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
395      break;
396   case OPCODE_NOISE2:
397      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
398      break;
399   case OPCODE_NOISE3:
400      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
401      break;
402   case OPCODE_NOISE4:
403      fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
404      break;
405   case OPCODE_NOP:
406      fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
407      break;
408   case OPCODE_POW:
409      fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
410      break;
411   case OPCODE_RCP:
412      fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
413      break;
414   case OPCODE_RET:
415      fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
416      break;
417   case OPCODE_RSQ:
418      fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
419      tgsi_util_set_full_src_register_sign_mode(
420         &fullinst->FullSrcRegisters[0],
421         TGSI_UTIL_SIGN_CLEAR );
422      break;
423   case OPCODE_SCS:
424      fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
425      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
426      break;
427   case OPCODE_SEQ:
428      fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
429      break;
430   case OPCODE_SGE:
431      fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
432      break;
433   case OPCODE_SGT:
434      fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
435      break;
436   case OPCODE_SIN:
437      fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
438      break;
439   case OPCODE_SLE:
440      fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
441      break;
442   case OPCODE_SLT:
443      fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
444      break;
445   case OPCODE_SNE:
446      fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
447      break;
448   case OPCODE_SUB:
449      fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
450      break;
451   case OPCODE_SWZ:
452      fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
453      break;
454   case OPCODE_TEX:
455      /* ordinary texture lookup */
456      fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
457      fullinst->Instruction.NumSrcRegs = 2;
458      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
459      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
460      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
461      break;
462   case OPCODE_TXB:
463      /* texture lookup with LOD bias */
464      fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
465      fullinst->Instruction.NumSrcRegs = 2;
466      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
467      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
468      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
469      break;
470   case OPCODE_TXD:
471      /* texture lookup with explicit partial derivatives */
472      fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
473      fullinst->Instruction.NumSrcRegs = 4;
474      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
475      /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
476      fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
477      fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
478      break;
479   case OPCODE_TXL:
480      /* texture lookup with explicit LOD */
481      fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
482      fullinst->Instruction.NumSrcRegs = 2;
483      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
484      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
485      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
486      break;
487   case OPCODE_TXP:
488      /* texture lookup with divide by Q component */
489      /* convert to TEX w/ special flag for division */
490      fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
491      fullinst->Instruction.NumSrcRegs = 2;
492      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
493      fullinst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide = TGSI_EXTSWIZZLE_W;
494      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
495      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
496      break;
497   case OPCODE_XPD:
498      fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
499      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
500      break;
501   case OPCODE_END:
502      fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
503      break;
504   default:
505      assert( 0 );
506   }
507}
508
509/**
510 * \param usage_mask  bitfield of TGSI_WRITEMASK_{XYZW} tokens
511 */
512static struct tgsi_full_declaration
513make_input_decl(
514   GLuint index,
515   GLboolean interpolate_info,
516   GLuint interpolate,
517   GLuint usage_mask,
518   GLboolean semantic_info,
519   GLuint semantic_name,
520   GLbitfield semantic_index )
521{
522   struct tgsi_full_declaration decl;
523
524   assert(semantic_name < TGSI_SEMANTIC_COUNT);
525
526   decl = tgsi_default_full_declaration();
527   decl.Declaration.File = TGSI_FILE_INPUT;
528   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
529   decl.Declaration.UsageMask = usage_mask;
530   decl.Declaration.Semantic = semantic_info;
531   decl.u.DeclarationRange.First = index;
532   decl.u.DeclarationRange.Last = index;
533   if (semantic_info) {
534      decl.Semantic.SemanticName = semantic_name;
535      decl.Semantic.SemanticIndex = semantic_index;
536   }
537   if (interpolate_info) {
538      decl.Declaration.Interpolate = 1;
539      decl.Interpolation.Interpolate = interpolate;
540   }
541
542   return decl;
543}
544
545/**
546 * \param usage_mask  bitfield of TGSI_WRITEMASK_{XYZW} tokens
547 */
548static struct tgsi_full_declaration
549make_output_decl(
550   GLuint index,
551   GLuint semantic_name,
552   GLuint semantic_index,
553   GLbitfield usage_mask )
554{
555   struct tgsi_full_declaration decl;
556
557   assert(semantic_name < TGSI_SEMANTIC_COUNT);
558
559   decl = tgsi_default_full_declaration();
560   decl.Declaration.File = TGSI_FILE_OUTPUT;
561   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
562   decl.Declaration.UsageMask = usage_mask;
563   decl.Declaration.Semantic = 1;
564   decl.u.DeclarationRange.First = index;
565   decl.u.DeclarationRange.Last = index;
566   decl.Semantic.SemanticName = semantic_name;
567   decl.Semantic.SemanticIndex = semantic_index;
568
569   return decl;
570}
571
572
573static struct tgsi_full_declaration
574make_temp_decl(
575   GLuint start_index,
576   GLuint end_index )
577{
578   struct tgsi_full_declaration decl;
579   decl = tgsi_default_full_declaration();
580   decl.Declaration.File = TGSI_FILE_TEMPORARY;
581   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
582   decl.u.DeclarationRange.First = start_index;
583   decl.u.DeclarationRange.Last = end_index;
584   return decl;
585}
586
587
588static struct tgsi_full_declaration
589make_sampler_decl(GLuint index)
590{
591   struct tgsi_full_declaration decl;
592   decl = tgsi_default_full_declaration();
593   decl.Declaration.File = TGSI_FILE_SAMPLER;
594   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
595   decl.u.DeclarationRange.First = index;
596   decl.u.DeclarationRange.Last = index;
597   return decl;
598}
599
600/** Reference into a constant buffer */
601static struct tgsi_full_declaration
602make_constant_decl(GLuint first, GLuint last)
603{
604   struct tgsi_full_declaration decl;
605   decl = tgsi_default_full_declaration();
606   decl.Declaration.File = TGSI_FILE_CONSTANT;
607   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
608   decl.u.DeclarationRange.First = first;
609   decl.u.DeclarationRange.Last = last;
610   return decl;
611}
612
613
614
615/**
616 * Find the temporaries which are used in the given program.
617 */
618static void
619find_temporaries(const struct gl_program *program,
620                 GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
621{
622   GLuint i, j;
623
624   for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
625      tempsUsed[i] = GL_FALSE;
626
627   for (i = 0; i < program->NumInstructions; i++) {
628      const struct prog_instruction *inst = program->Instructions + i;
629      const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
630      for (j = 0; j < n; j++) {
631         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
632            tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
633         if (inst->DstReg.File == PROGRAM_TEMPORARY)
634            tempsUsed[inst->DstReg.Index] = GL_TRUE;
635      }
636   }
637}
638
639
640
641
642/**
643 * Translate Mesa program to TGSI format.
644 * \param program  the program to translate
645 * \param numInputs  number of input registers used
646 * \param inputMapping  maps Mesa fragment program inputs to TGSI generic
647 *                      input indexes
648 * \param inputSemanticName  the TGSI_SEMANTIC flag for each input
649 * \param inputSemanticIndex  the semantic index (ex: which texcoord) for each input
650 * \param interpMode  the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
651
652 * \param numOutputs  number of output registers used
653 * \param outputMapping  maps Mesa fragment program outputs to TGSI
654 *                       generic outputs
655 * \param outputSemanticName  the TGSI_SEMANTIC flag for each output
656 * \param outputSemanticIndex  the semantic index (ex: which texcoord) for each output
657 * \param tokens  array to store translated tokens in
658 * \param maxTokens  size of the tokens array
659 *
660 */
661GLboolean
662tgsi_translate_mesa_program(
663   uint procType,
664   const struct gl_program *program,
665   GLuint numInputs,
666   const GLuint inputMapping[],
667   const ubyte inputSemanticName[],
668   const ubyte inputSemanticIndex[],
669   const GLuint interpMode[],
670   GLuint numOutputs,
671   const GLuint outputMapping[],
672   const ubyte outputSemanticName[],
673   const ubyte outputSemanticIndex[],
674   struct tgsi_token *tokens,
675   GLuint maxTokens )
676{
677   GLuint i;
678   GLuint ti;  /* token index */
679   struct tgsi_header *header;
680   struct tgsi_processor *processor;
681   struct tgsi_full_instruction fullinst;
682   GLuint preamble_size = 0;
683   GLuint immediates[1000];
684   GLuint numImmediates = 0;
685
686   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
687          procType == TGSI_PROCESSOR_VERTEX);
688
689   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
690
691   header = (struct tgsi_header *) &tokens[1];
692   *header = tgsi_build_header();
693
694   processor = (struct tgsi_processor *) &tokens[2];
695   *processor = tgsi_build_processor( procType, header );
696
697   ti = 3;
698
699   /*
700    * Declare input attributes.
701    */
702   if (procType == TGSI_PROCESSOR_FRAGMENT) {
703      for (i = 0; i < numInputs; i++) {
704         struct tgsi_full_declaration fulldecl;
705         fulldecl = make_input_decl(i,
706                                    GL_TRUE, interpMode[i],
707                                    TGSI_WRITEMASK_XYZW,
708                                    GL_TRUE, inputSemanticName[i],
709                                    inputSemanticIndex[i]);
710         ti += tgsi_build_full_declaration(&fulldecl,
711                                           &tokens[ti],
712                                           header,
713                                           maxTokens - ti );
714      }
715   }
716   else {
717      /* vertex prog */
718      /* XXX: this could probaby be merged with the clause above.
719       * the only difference is the semantic tags.
720       */
721      for (i = 0; i < numInputs; i++) {
722         struct tgsi_full_declaration fulldecl;
723         fulldecl = make_input_decl(i,
724                                    GL_FALSE, 0,
725                                    TGSI_WRITEMASK_XYZW,
726                                    GL_FALSE, 0, 0);
727         ti += tgsi_build_full_declaration(&fulldecl,
728                                           &tokens[ti],
729                                           header,
730                                           maxTokens - ti );
731      }
732   }
733
734   /*
735    * Declare output attributes.
736    */
737   if (procType == TGSI_PROCESSOR_FRAGMENT) {
738      for (i = 0; i < numOutputs; i++) {
739         struct tgsi_full_declaration fulldecl;
740         switch (outputSemanticName[i]) {
741         case TGSI_SEMANTIC_POSITION:
742            fulldecl = make_output_decl(i,
743                                        TGSI_SEMANTIC_POSITION, 0, /* Z / Depth */
744                                        TGSI_WRITEMASK_Z );
745            break;
746         case TGSI_SEMANTIC_COLOR:
747            fulldecl = make_output_decl(i,
748                                        TGSI_SEMANTIC_COLOR, 0,
749                                        TGSI_WRITEMASK_XYZW );
750            break;
751         default:
752            abort();
753         }
754         ti += tgsi_build_full_declaration(&fulldecl,
755                                           &tokens[ti],
756                                           header,
757                                           maxTokens - ti );
758      }
759   }
760   else {
761      /* vertex prog */
762      for (i = 0; i < numOutputs; i++) {
763         struct tgsi_full_declaration fulldecl;
764         fulldecl = make_output_decl(i,
765                                     outputSemanticName[i],
766                                     outputSemanticIndex[i],
767                                     TGSI_WRITEMASK_XYZW );
768         ti += tgsi_build_full_declaration(&fulldecl,
769                                           &tokens[ti],
770                                           header,
771                                           maxTokens - ti );
772      }
773   }
774
775   /* temporary decls */
776   {
777      GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
778      GLboolean inside_range = GL_FALSE;
779      GLuint start_range;
780
781      find_temporaries(program, tempsUsed);
782      tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
783      for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
784         if (tempsUsed[i] && !inside_range) {
785            inside_range = GL_TRUE;
786            start_range = i;
787         }
788         else if (!tempsUsed[i] && inside_range) {
789            struct tgsi_full_declaration fulldecl;
790
791            inside_range = GL_FALSE;
792            fulldecl = make_temp_decl( start_range, i - 1 );
793            ti += tgsi_build_full_declaration(
794                                              &fulldecl,
795                                              &tokens[ti],
796                                              header,
797                                              maxTokens - ti );
798         }
799      }
800   }
801
802   /* immediates/literals */
803   for (i = 0; program->Parameters && i < program->Parameters->NumParameters;
804        i++) {
805      if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
806         struct tgsi_full_immediate fullimm
807            = make_immediate(program->Parameters->ParameterValues[i],
808                             program->Parameters->Parameters[i].Size);
809         ti += tgsi_build_full_immediate(&fullimm,
810                                         &tokens[ti],
811                                         header,
812                                         maxTokens - ti);
813         immediates[i] = numImmediates;
814         numImmediates++;
815      }
816   }
817
818   /* constant buffer refs */
819   {
820      GLint start = -1, end = -1;
821
822      for (i = 0;
823           program->Parameters && i < program->Parameters->NumParameters;
824           i++) {
825         GLboolean emit = (i == program->Parameters->NumParameters - 1);
826
827         switch (program->Parameters->Parameters[i].Type) {
828         case PROGRAM_ENV_PARAM:
829         case PROGRAM_STATE_VAR:
830         case PROGRAM_NAMED_PARAM:
831         case PROGRAM_UNIFORM:
832            if (start == -1) {
833               /* begin a sequence */
834               start = i;
835               end = i;
836            }
837            else {
838               /* continue sequence */
839               end = i;
840            }
841            break;
842         default:
843            if (start != -1) {
844               /* end of sequence */
845               emit = GL_TRUE;
846            }
847         }
848
849         if (emit && start >= 0) {
850            struct tgsi_full_declaration fulldecl;
851            fulldecl = make_constant_decl( start, end );
852            ti += tgsi_build_full_declaration(&fulldecl,
853                                              &tokens[ti],
854                                              header,
855                                              maxTokens - ti);
856            start = end = -1;
857         }
858      }
859   }
860
861   /* texture samplers */
862   for (i = 0; i < 8; i++) {
863      if (program->SamplersUsed & (1 << i)) {
864         struct tgsi_full_declaration fulldecl;
865         fulldecl = make_sampler_decl( i );
866         ti += tgsi_build_full_declaration(&fulldecl,
867                                           &tokens[ti],
868                                           header,
869                                           maxTokens - ti );
870      }
871   }
872
873
874   for( i = 0; i < program->NumInstructions; i++ ) {
875      compile_instruction(
876            &program->Instructions[i],
877            &fullinst,
878            inputMapping,
879            outputMapping,
880            immediates,
881            preamble_size,
882            procType );
883
884      ti += tgsi_build_full_instruction(
885         &fullinst,
886         &tokens[ti],
887         header,
888         maxTokens - ti );
889   }
890
891   return GL_TRUE;
892}
893
894