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