Merge branch 'gallium-polygon-stipple'
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_exec.c
index 57ae56e96fd0c47de1a27fe4314a79239c581ceb..712e8aca794c4252804f8bb76f799bde68b3e60f 100644 (file)
@@ -477,8 +477,6 @@ enum tgsi_exec_datatype {
 #define TEMP_OUTPUT_C      TGSI_EXEC_TEMP_OUTPUT_C
 #define TEMP_PRIMITIVE_I   TGSI_EXEC_TEMP_PRIMITIVE_I
 #define TEMP_PRIMITIVE_C   TGSI_EXEC_TEMP_PRIMITIVE_C
-#define TEMP_CC_I          TGSI_EXEC_TEMP_CC_I
-#define TEMP_CC_C          TGSI_EXEC_TEMP_CC_C
 
 
 /** The execution mask depends on the conditional mask and the loop mask */
@@ -674,6 +672,31 @@ tgsi_exec_machine_bind_shader(
    mach->Processor = parse.FullHeader.Processor.Processor;
    mach->ImmLimit = 0;
 
+   if (mach->Processor == TGSI_PROCESSOR_GEOMETRY &&
+       !mach->UsedGeometryShader) {
+      struct tgsi_exec_vector *inputs =
+         align_malloc(sizeof(struct tgsi_exec_vector) *
+                      TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS,
+                      16);
+      struct tgsi_exec_vector *outputs =
+         align_malloc(sizeof(struct tgsi_exec_vector) *
+                      TGSI_MAX_TOTAL_VERTICES, 16);
+
+      if (!inputs)
+         return;
+      if (!outputs) {
+         align_free(inputs);
+         return;
+      }
+
+      align_free(mach->Inputs);
+      align_free(mach->Outputs);
+
+      mach->Inputs = inputs;
+      mach->Outputs = outputs;
+      mach->UsedGeometryShader = TRUE;
+   }
+
    declarations = (struct tgsi_full_declaration *)
       MALLOC( maxDeclarations * sizeof(struct tgsi_full_declaration) );
 
@@ -803,6 +826,11 @@ tgsi_exec_machine_create( void )
    mach->MaxGeometryShaderOutputs = TGSI_MAX_TOTAL_VERTICES;
    mach->Predicates = &mach->Temps[TGSI_EXEC_TEMP_P0];
 
+   mach->Inputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16);
+   mach->Outputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16);
+   if (!mach->Inputs || !mach->Outputs)
+      goto fail;
+
    /* Setup constants needed by the SSE2 executor. */
    for( i = 0; i < 4; i++ ) {
       mach->Temps[TGSI_EXEC_TEMP_00000000_I].xyzw[TGSI_EXEC_TEMP_00000000_C].u[i] = 0x00000000;
@@ -826,7 +854,11 @@ tgsi_exec_machine_create( void )
    return mach;
 
 fail:
-   align_free(mach);
+   if (mach) {
+      align_free(mach->Inputs);
+      align_free(mach->Outputs);
+      align_free(mach);
+   }
    return NULL;
 }
 
@@ -838,10 +870,13 @@ tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach)
       if (mach->Instructions)
          FREE(mach->Instructions);
       if (mach->Declarations)
-      FREE(mach->Declarations);
-   }
+         FREE(mach->Declarations);
 
-   align_free(mach);
+      align_free(mach->Inputs);
+      align_free(mach->Outputs);
+
+      align_free(mach);
+   }
 }
 
 static void
@@ -1040,7 +1075,6 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
       break;
 
    case TGSI_FILE_INPUT:
-   case TGSI_FILE_SYSTEM_VALUE:
       for (i = 0; i < QUAD_SIZE; i++) {
          /*
          if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
@@ -1050,11 +1084,20 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
                          }*/
          int pos = index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i];
          assert(pos >= 0);
-         assert(pos < Elements(mach->Inputs));
+         assert(pos < TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS);
          chan->u[i] = mach->Inputs[pos].xyzw[swizzle].u[i];
       }
       break;
 
+   case TGSI_FILE_SYSTEM_VALUE:
+      /* XXX no swizzling at this point.  Will be needed if we put
+       * gl_FragCoord, for example, in a sys value register.
+       */
+      for (i = 0; i < QUAD_SIZE; i++) {
+         chan->f[i] = mach->SystemValue[index->i[i]][0];
+      }
+      break;
+
    case TGSI_FILE_TEMPORARY:
       for (i = 0; i < QUAD_SIZE; i++) {
          assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
@@ -1744,6 +1787,36 @@ exec_tex(struct tgsi_exec_machine *mach,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
 
+   case TGSI_TEXTURE_1D_ARRAY:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[unit],
+                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
+   case TGSI_TEXTURE_2D_ARRAY:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[unit],
+                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
    case TGSI_TEXTURE_3D:
    case TGSI_TEXTURE_CUBE:
       FETCH(&r[0], 0, CHAN_X);
@@ -1766,6 +1839,17 @@ exec_tex(struct tgsi_exec_machine *mach,
       assert(0);
    }
 
+#if 0
+   debug_printf("fetch r: %g %g %g %g\n",
+         r[0].f[0], r[0].f[1], r[0].f[2], r[0].f[3]);
+   debug_printf("fetch g: %g %g %g %g\n",
+         r[1].f[0], r[1].f[1], r[1].f[2], r[1].f[3]);
+   debug_printf("fetch b: %g %g %g %g\n",
+         r[2].f[0], r[2].f[1], r[2].f[2], r[2].f[3]);
+   debug_printf("fetch a: %g %g %g %g\n",
+         r[3].f[0], r[3].f[1], r[3].f[2], r[3].f[3]);
+#endif
+
    for (chan = 0; chan < NUM_CHANNELS; chan++) {
       if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
          store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
@@ -1837,6 +1921,164 @@ exec_txd(struct tgsi_exec_machine *mach,
 }
 
 
+
+static void
+exec_sample(struct tgsi_exec_machine *mach,
+            const struct tgsi_full_instruction *inst,
+            uint modifier)
+{
+   const uint resource_unit = inst->Src[1].Register.Index;
+   const uint sampler_unit = inst->Src[2].Register.Index;
+   union tgsi_exec_channel r[4];
+   const union tgsi_exec_channel *lod = &ZeroVec;
+   enum tgsi_sampler_control control;
+   uint chan;
+
+   if (modifier != TEX_MODIFIER_NONE) {
+      if (modifier == TEX_MODIFIER_LOD_BIAS)
+         FETCH(&r[3], 3, CHAN_X);
+      else /*TEX_MODIFIER_LOD*/
+         FETCH(&r[3], 0, CHAN_W);
+
+      if (modifier != TEX_MODIFIER_PROJECTED) {
+         lod = &r[3];
+      }
+   }
+
+   if (modifier == TEX_MODIFIER_EXPLICIT_LOD) {
+      control = tgsi_sampler_lod_explicit;
+   } else {
+      control = tgsi_sampler_lod_bias;
+   }
+
+   switch (mach->Resources[resource_unit].Resource) {
+   case TGSI_TEXTURE_1D:
+   case TGSI_TEXTURE_SHADOW1D:
+      FETCH(&r[0], 0, CHAN_X);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &ZeroVec, &ZeroVec, lod,  /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
+      break;
+
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWRECT:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+         micro_div(&r[2], &r[2], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+         micro_div(&r[2], &r[2], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], lod,
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);
+      break;
+
+   default:
+      assert(0);
+   }
+
+   for (chan = 0; chan < NUM_CHANNELS; chan++) {
+      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+      }
+   }
+}
+
+static void
+exec_sample_d(struct tgsi_exec_machine *mach,
+              const struct tgsi_full_instruction *inst)
+{
+   const uint resource_unit = inst->Src[1].Register.Index;
+   const uint sampler_unit = inst->Src[2].Register.Index;
+   union tgsi_exec_channel r[4];
+   uint chan;
+   /*
+    * XXX: This is fake SAMPLE_D -- the derivatives are not taken into account, yet.
+    */
+
+   switch (mach->Resources[resource_unit].Resource) {
+   case TGSI_TEXTURE_1D:
+   case TGSI_TEXTURE_SHADOW1D:
+
+      FETCH(&r[0], 0, CHAN_X);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, BIAS */
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
+      break;
+
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWRECT:
+
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], &ZeroVec,   /* inputs */
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);     /* outputs */
+      break;
+
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], &ZeroVec,
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);
+      break;
+
+   default:
+      assert(0);
+   }
+
+   for (chan = 0; chan < NUM_CHANNELS; chan++) {
+      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+      }
+   }
+}
+
+
 /**
  * Evaluate a constant-valued coefficient at the position of the
  * current quad.
@@ -1908,9 +2150,13 @@ static void
 exec_declaration(struct tgsi_exec_machine *mach,
                  const struct tgsi_full_declaration *decl)
 {
+   if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+      mach->Resources[decl->Range.First] = decl->Resource;
+      return;
+   }
+
    if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
-      if (decl->Declaration.File == TGSI_FILE_INPUT ||
-          decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) {
+      if (decl->Declaration.File == TGSI_FILE_INPUT) {
          uint first, last, mask;
 
          first = decl->Range.First;
@@ -1923,6 +2169,7 @@ exec_declaration(struct tgsi_exec_machine *mach,
           * ureg code to emit the right UsageMask value (WRITEMASK_X).
           * Then, we could remove the tgsi_exec_machine::Face field.
           */
+         /* XXX make FACE a system value */
          if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
             uint i;
 
@@ -1964,8 +2211,13 @@ exec_declaration(struct tgsi_exec_machine *mach,
          }
       }
    }
+
+   if (decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) {
+      mach->SysSemanticToIndex[decl->Declaration.Semantic] = decl->Range.First;
+   }
 }
 
+
 typedef void (* micro_op)(union tgsi_exec_channel *dst);
 
 static void
@@ -3677,6 +3929,54 @@ exec_instruction(
       exec_endswitch(mach);
       break;
 
+   case TGSI_OPCODE_LOAD:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_LOAD_MS:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE:
+      exec_sample(mach, inst, TEX_MODIFIER_NONE);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_B:
+      exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_C:
+      exec_sample(mach, inst, TEX_MODIFIER_NONE);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_C_LZ:
+      exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_D:
+      exec_sample_d(mach, inst);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_L:
+      exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD);
+      break;
+
+   case TGSI_OPCODE_GATHER4:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_RESINFO:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_POS:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_INFO:
+      assert(0);
+      break;
+
    default:
       assert( 0 );
    }
@@ -3719,14 +4019,6 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach )
       mach->Primitives[0] = 0;
    }
 
-   for (i = 0; i < QUAD_SIZE; i++) {
-      mach->Temps[TEMP_CC_I].xyzw[TEMP_CC_C].u[i] =
-         (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_X_SHIFT) |
-         (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_Y_SHIFT) |
-         (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_Z_SHIFT) |
-         (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_W_SHIFT);
-   }
-
    /* execute declarations (interpolants) */
    for (i = 0; i < mach->NumDeclarations; i++) {
       exec_declaration( mach, mach->Declarations+i );