mesa: Prefix main includes with dir to avoid conflicts.
[mesa.git] / src / mesa / state_tracker / st_mesa_to_tgsi.c
index 27dab5b9c06f50c7b394be3fe93fea21c8800e00..9029f12056f4fbc7ed9cdc06e38d1a664efb03c8 100644 (file)
 
 #include "pipe/p_compiler.h"
 #include "pipe/p_shader_tokens.h"
-#include "pipe/tgsi/util/tgsi_parse.h"
-#include "pipe/tgsi/util/tgsi_build.h"
-#include "pipe/tgsi/util/tgsi_util.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_build.h"
+#include "tgsi/util/tgsi_util.h"
 #include "st_mesa_to_tgsi.h"
 #include "shader/prog_instruction.h"
 #include "shader/prog_parameter.h"
 
-#define TGSI_DEBUG 0
-
 
 /*
  * Map mesa register file to TGSI register file.
  */
 static GLuint
 map_register_file(
-   enum register_file file )
+   enum register_file file,
+   GLuint index,
+   const GLuint immediateMapping[] )
 {
    switch( file ) {
    case PROGRAM_UNDEFINED:
       return TGSI_FILE_NULL;
    case PROGRAM_TEMPORARY:
       return TGSI_FILE_TEMPORARY;
-   //case PROGRAM_LOCAL_PARAM:
-   //case PROGRAM_ENV_PARAM:
+   /*case PROGRAM_LOCAL_PARAM:*/
+   /*case PROGRAM_ENV_PARAM:*/
+
+      /* Because of the longstanding problem with mesa arb shaders
+       * where constants, immediates and state variables are all
+       * bundled together as PROGRAM_STATE_VAR, we can't tell from the
+       * mesa register file whether this is a CONSTANT or an
+       * IMMEDIATE, hence we need all the other information.
+       */
    case PROGRAM_STATE_VAR:
    case PROGRAM_NAMED_PARAM:
    case PROGRAM_UNIFORM:
-      return TGSI_FILE_CONSTANT;
+      if (immediateMapping && immediateMapping[index] != ~0)
+         return TGSI_FILE_IMMEDIATE;
+      else
+        return TGSI_FILE_CONSTANT;
    case PROGRAM_CONSTANT:
       return TGSI_FILE_IMMEDIATE;
    case PROGRAM_INPUT:
@@ -180,7 +190,8 @@ compile_instruction(
    const GLuint outputMapping[],
    const GLuint immediateMapping[],
    GLuint preamble_size,
-   GLuint processor )
+   GLuint processor,
+   GLboolean *insideSubroutine)
 {
    GLuint i;
    struct tgsi_full_dst_register *fulldst;
@@ -193,7 +204,7 @@ compile_instruction(
    fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
 
    fulldst = &fullinst->FullDstRegisters[0];
-   fulldst->DstRegister.File = map_register_file( inst->DstReg.File );
+   fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL );
    fulldst->DstRegister.Index = map_register_file_index(
       fulldst->DstRegister.File,
       inst->DstReg.Index,
@@ -207,7 +218,9 @@ compile_instruction(
       GLuint j;
 
       fullsrc = &fullinst->FullSrcRegisters[i];
-      fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File );
+      fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File,
+                                                    inst->SrcReg[i].Index,
+                                                    immediateMapping );
       fullsrc->SrcRegister.Index = map_register_file_index(
          fullsrc->SrcRegister.File,
          inst->SrcReg[i].Index,
@@ -215,21 +228,27 @@ compile_instruction(
          outputMapping,
          immediateMapping);
 
-      for( j = 0; j < 4; j++ ) {
-         GLuint swz;
-
-         swz = GET_SWZ( inst->SrcReg[i].Swizzle, j );
-         if( swz > SWIZZLE_W ) {
-            tgsi_util_set_src_register_extswizzle(
-               &fullsrc->SrcRegisterExtSwz,
-               swz,
-               j );
+      /* swizzle (ext swizzle also depends on negation) */
+      {
+         GLuint swz[4];
+         GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE &&
+                               inst->SrcReg[i].NegateBase != NEGATE_XYZW);
+         for( j = 0; j < 4; j++ ) {
+            swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
+            if (swz[j] > SWIZZLE_W)
+               extended = GL_TRUE;
+         }
+         if (extended) {
+            for (j = 0; j < 4; j++) {
+               tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
+                                                     swz[j], j);
+            }
          }
          else {
-            tgsi_util_set_src_register_swizzle(
-               &fullsrc->SrcRegister,
-               swz,
-               j );
+            for (j = 0; j < 4; j++) {
+               tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
+                                                  swz[j], j);
+            }
          }
       }
 
@@ -283,6 +302,7 @@ compile_instruction(
       break;
    case OPCODE_BGNSUB:
       fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
+      *insideSubroutine = GL_TRUE;
       break;
    case OPCODE_BRA:
       fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
@@ -334,6 +354,7 @@ compile_instruction(
       break;
    case OPCODE_ENDSUB:
       fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
+      *insideSubroutine = GL_FALSE;
       break;
    case OPCODE_EX2:
       fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
@@ -412,7 +433,16 @@ compile_instruction(
       fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
       break;
    case OPCODE_RET:
-      fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+      /* If RET is used inside main (not a real subroutine) we may want
+       * to execute END instead of RET.  TBD...
+       */
+      if (1 /*  *insideSubroutine */) {
+         fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+      }
+      else {
+         /* inside main() pseudo-function */
+         fullinst->Instruction.Opcode = TGSI_OPCODE_END;
+      }
       break;
    case OPCODE_RSQ:
       fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
@@ -487,10 +517,9 @@ compile_instruction(
    case OPCODE_TXP:
       /* texture lookup with divide by Q component */
       /* convert to TEX w/ special flag for division */
-      fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
+      fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
       fullinst->Instruction.NumSrcRegs = 2;
       fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
-      fullinst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide = TGSI_EXTSWIZZLE_W;
       fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
       fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
       break;
@@ -499,7 +528,7 @@ compile_instruction(
       fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
       break;
    case OPCODE_END:
-      fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+      fullinst->Instruction.Opcode = TGSI_OPCODE_END;
       break;
    default:
       assert( 0 );
@@ -525,18 +554,16 @@ make_input_decl(
 
    decl = tgsi_default_full_declaration();
    decl.Declaration.File = TGSI_FILE_INPUT;
-   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
    decl.Declaration.UsageMask = usage_mask;
    decl.Declaration.Semantic = semantic_info;
-   decl.u.DeclarationRange.First = index;
-   decl.u.DeclarationRange.Last = index;
+   decl.DeclarationRange.First = index;
+   decl.DeclarationRange.Last = index;
    if (semantic_info) {
       decl.Semantic.SemanticName = semantic_name;
       decl.Semantic.SemanticIndex = semantic_index;
    }
    if (interpolate_info) {
-      decl.Declaration.Interpolate = 1;
-      decl.Interpolation.Interpolate = interpolate;
+      decl.Declaration.Interpolate = interpolate;
    }
 
    return decl;
@@ -558,11 +585,10 @@ make_output_decl(
 
    decl = tgsi_default_full_declaration();
    decl.Declaration.File = TGSI_FILE_OUTPUT;
-   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
    decl.Declaration.UsageMask = usage_mask;
    decl.Declaration.Semantic = 1;
-   decl.u.DeclarationRange.First = index;
-   decl.u.DeclarationRange.Last = index;
+   decl.DeclarationRange.First = index;
+   decl.DeclarationRange.Last = index;
    decl.Semantic.SemanticName = semantic_name;
    decl.Semantic.SemanticIndex = semantic_index;
 
@@ -578,13 +604,37 @@ make_temp_decl(
    struct tgsi_full_declaration decl;
    decl = tgsi_default_full_declaration();
    decl.Declaration.File = TGSI_FILE_TEMPORARY;
-   decl.Declaration.Declare = TGSI_DECLARE_RANGE;
-   decl.u.DeclarationRange.First = start_index;
-   decl.u.DeclarationRange.Last = end_index;
+   decl.DeclarationRange.First = start_index;
+   decl.DeclarationRange.Last = end_index;
+   return decl;
+}
+
+
+static struct tgsi_full_declaration
+make_sampler_decl(GLuint index)
+{
+   struct tgsi_full_declaration decl;
+   decl = tgsi_default_full_declaration();
+   decl.Declaration.File = TGSI_FILE_SAMPLER;
+   decl.DeclarationRange.First = index;
+   decl.DeclarationRange.Last = index;
+   return decl;
+}
+
+/** Reference into a constant buffer */
+static struct tgsi_full_declaration
+make_constant_decl(GLuint first, GLuint last)
+{
+   struct tgsi_full_declaration decl;
+   decl = tgsi_default_full_declaration();
+   decl.Declaration.File = TGSI_FILE_CONSTANT;
+   decl.DeclarationRange.First = first;
+   decl.DeclarationRange.Last = last;
    return decl;
 }
 
 
+
 /**
  * Find the temporaries which are used in the given program.
  */
@@ -630,8 +680,9 @@ find_temporaries(const struct gl_program *program,
  * \param tokens  array to store translated tokens in
  * \param maxTokens  size of the tokens array
  *
+ * \return number of tokens placed in 'tokens' buffer, or zero if error
  */
-GLboolean
+GLuint
 tgsi_translate_mesa_program(
    uint procType,
    const struct gl_program *program,
@@ -655,6 +706,7 @@ tgsi_translate_mesa_program(
    GLuint preamble_size = 0;
    GLuint immediates[1000];
    GLuint numImmediates = 0;
+   GLboolean insideSubroutine = GL_FALSE;
 
    assert(procType == TGSI_PROCESSOR_FRAGMENT ||
           procType == TGSI_PROCESSOR_VERTEX);
@@ -713,16 +765,19 @@ tgsi_translate_mesa_program(
          switch (outputSemanticName[i]) {
          case TGSI_SEMANTIC_POSITION:
             fulldecl = make_output_decl(i,
-                                        TGSI_SEMANTIC_POSITION, 0, /* Z / Depth */
+                                        TGSI_SEMANTIC_POSITION, /* Z / Depth */
+                                        outputSemanticIndex[i],
                                         TGSI_WRITEMASK_Z );
             break;
          case TGSI_SEMANTIC_COLOR:
             fulldecl = make_output_decl(i,
-                                        TGSI_SEMANTIC_COLOR, 0,
+                                        TGSI_SEMANTIC_COLOR,
+                                        outputSemanticIndex[i],
                                         TGSI_WRITEMASK_XYZW );
             break;
          default:
-            abort();
+            assert(0);
+            return 0;
          }
          ti += tgsi_build_full_declaration(&fulldecl,
                                            &tokens[ti],
@@ -749,7 +804,7 @@ tgsi_translate_mesa_program(
    {
       GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
       GLboolean inside_range = GL_FALSE;
-      GLuint start_range;
+      GLuint start_range = 0;
 
       find_temporaries(program, tempsUsed);
       tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
@@ -773,12 +828,13 @@ tgsi_translate_mesa_program(
    }
 
    /* immediates/literals */
+   memset(immediates, ~0, sizeof(immediates));
+
    for (i = 0; program->Parameters && i < program->Parameters->NumParameters;
-       i++) {
+        i++) {
       if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
          struct tgsi_full_immediate fullimm
-            = make_immediate(program->Parameters->ParameterValues[i],
-                             program->Parameters->Parameters[i].Size);
+            = make_immediate(program->Parameters->ParameterValues[i], 4);
          ti += tgsi_build_full_immediate(&fullimm,
                                          &tokens[ti],
                                          header,
@@ -788,6 +844,62 @@ tgsi_translate_mesa_program(
       }
    }
 
+   /* constant buffer refs */
+   {
+      GLint start = -1, end = -1;
+
+      for (i = 0;
+           program->Parameters && i < program->Parameters->NumParameters;
+           i++) {
+         GLboolean emit = (i == program->Parameters->NumParameters - 1);
+
+         switch (program->Parameters->Parameters[i].Type) {
+         case PROGRAM_ENV_PARAM:
+         case PROGRAM_STATE_VAR:
+         case PROGRAM_NAMED_PARAM:
+         case PROGRAM_UNIFORM:
+            if (start == -1) {
+               /* begin a sequence */
+               start = i;
+               end = i;
+            }
+            else {
+               /* continue sequence */
+               end = i;
+            }
+            break;
+         default:
+            if (start != -1) {
+               /* end of sequence */
+               emit = GL_TRUE;
+            }
+         }
+
+         if (emit && start >= 0) {
+            struct tgsi_full_declaration fulldecl;
+            fulldecl = make_constant_decl( start, end );
+            ti += tgsi_build_full_declaration(&fulldecl,
+                                              &tokens[ti],
+                                              header,
+                                              maxTokens - ti);
+            start = end = -1;
+         }
+      }
+   }
+
+   /* texture samplers */
+   for (i = 0; i < 8; i++) {
+      if (program->SamplersUsed & (1 << i)) {
+         struct tgsi_full_declaration fulldecl;
+         fulldecl = make_sampler_decl( i );
+         ti += tgsi_build_full_declaration(&fulldecl,
+                                           &tokens[ti],
+                                           header,
+                                           maxTokens - ti );
+      }
+   }
+
+
    for( i = 0; i < program->NumInstructions; i++ ) {
       compile_instruction(
             &program->Instructions[i],
@@ -796,7 +908,8 @@ tgsi_translate_mesa_program(
             outputMapping,
             immediates,
             preamble_size,
-            procType );
+            procType,
+            &insideSubroutine);
 
       ti += tgsi_build_full_instruction(
          &fullinst,
@@ -805,6 +918,6 @@ tgsi_translate_mesa_program(
          maxTokens - ti );
    }
 
-   return GL_TRUE;
+   return ti;
 }