gallium: fix tgsi SAMPLE_L opcode to use separate source for explicit lod
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_tgsi_info.c
index d1f82610025ef56bfdf67638069ffdc46c5d72cb..3a19fe2a64f760d8cba9d40605d1244609591090 100644 (file)
@@ -29,9 +29,9 @@
 #include "util/u_memory.h"
 #include "util/u_math.h"
 #include "tgsi/tgsi_parse.h"
-#include "tgsi/tgsi_text.h"
 #include "tgsi/tgsi_util.h"
 #include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_strings.h"
 #include "lp_bld_debug.h"
 #include "lp_bld_tgsi.h"
 
@@ -47,7 +47,7 @@ struct analysis_context
    struct lp_tgsi_info *info;
 
    unsigned num_imms;
-   float imm[32][4];
+   float imm[128][4];
 
    struct lp_tgsi_channel_info temp[32][4];
 };
@@ -96,6 +96,11 @@ is_immediate(const struct lp_tgsi_channel_info *chan_info, float value)
 }
 
 
+/**
+ * Analyse properties of tex instructions, in particular used
+ * to figure out if a texture is considered indirect.
+ * Not actually used by much except the tgsi dumping code.
+ */
 static void
 analyse_tex(struct analysis_context *ctx,
             const struct tgsi_full_instruction *inst,
@@ -106,7 +111,7 @@ analyse_tex(struct analysis_context *ctx,
 
    if (info->num_texs < Elements(info->tex)) {
       struct lp_tgsi_texture_info *tex_info = &info->tex[info->num_texs];
-      bool indirect = FALSE;
+      boolean indirect = FALSE;
       unsigned readmask = 0;
 
       tex_info->target = inst->Texture.Texture;
@@ -114,17 +119,24 @@ analyse_tex(struct analysis_context *ctx,
       case TGSI_TEXTURE_1D:
          readmask = TGSI_WRITEMASK_X;
          break;
+      case TGSI_TEXTURE_1D_ARRAY:
       case TGSI_TEXTURE_2D:
       case TGSI_TEXTURE_RECT:
          readmask = TGSI_WRITEMASK_XY;
          break;
       case TGSI_TEXTURE_SHADOW1D:
+      case TGSI_TEXTURE_SHADOW1D_ARRAY:
       case TGSI_TEXTURE_SHADOW2D:
       case TGSI_TEXTURE_SHADOWRECT:
+      case TGSI_TEXTURE_2D_ARRAY:
       case TGSI_TEXTURE_3D:
       case TGSI_TEXTURE_CUBE:
          readmask = TGSI_WRITEMASK_XYZ;
          break;
+      case TGSI_TEXTURE_SHADOW2D_ARRAY:
+      case TGSI_TEXTURE_SHADOWCUBE:
+         readmask = TGSI_WRITEMASK_XYZW;
+         break;
       default:
          assert(0);
          return;
@@ -133,14 +145,106 @@ analyse_tex(struct analysis_context *ctx,
       if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV) {
          /* We don't track explicit derivatives, although we could */
          indirect = TRUE;
-         tex_info->unit = inst->Src[3].Register.Index;
+         tex_info->sampler_unit = inst->Src[3].Register.Index;
+         tex_info->texture_unit = inst->Src[3].Register.Index;
       }  else {
          if (modifier == LP_BLD_TEX_MODIFIER_PROJECTED ||
              modifier == LP_BLD_TEX_MODIFIER_LOD_BIAS ||
              modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_LOD) {
             readmask |= TGSI_WRITEMASK_W;
          }
-         tex_info->unit = inst->Src[1].Register.Index;
+         tex_info->sampler_unit = inst->Src[1].Register.Index;
+         tex_info->texture_unit = inst->Src[1].Register.Index;
+      }
+
+      for (chan = 0; chan < 4; ++chan) {
+         struct lp_tgsi_channel_info *chan_info = &tex_info->coord[chan];
+         if (readmask & (1 << chan)) {
+            analyse_src(ctx, chan_info, &inst->Src[0].Register, chan);
+            if (chan_info->file != TGSI_FILE_INPUT) {
+               indirect = TRUE;
+            }
+         } else {
+            memset(chan_info, 0, sizeof *chan_info);
+         }
+      }
+
+      if (indirect) {
+         info->indirect_textures = TRUE;
+      }
+
+      ++info->num_texs;
+   } else {
+      info->indirect_textures = TRUE;
+   }
+}
+
+
+/**
+ * Analyse properties of sample instructions, in particular used
+ * to figure out if a texture is considered indirect.
+ * Not actually used by much except the tgsi dumping code.
+ */
+static void
+analyse_sample(struct analysis_context *ctx,
+               const struct tgsi_full_instruction *inst,
+               enum lp_build_tex_modifier modifier)
+{
+   struct lp_tgsi_info *info = ctx->info;
+   unsigned chan;
+
+   if (info->num_texs < Elements(info->tex)) {
+      struct lp_tgsi_texture_info *tex_info = &info->tex[info->num_texs];
+      boolean indirect = FALSE;
+      boolean shadow = FALSE;
+      unsigned readmask = 0;
+
+      tex_info->target = inst->Texture.Texture;
+      switch (inst->Texture.Texture) {
+      case TGSI_TEXTURE_SHADOW1D:
+         shadow = TRUE;
+         /* Fallthrough */
+      case TGSI_TEXTURE_1D:
+         readmask = TGSI_WRITEMASK_X;
+         break;
+      case TGSI_TEXTURE_SHADOW1D_ARRAY:
+      case TGSI_TEXTURE_SHADOW2D:
+      case TGSI_TEXTURE_SHADOWRECT:
+         shadow = TRUE;
+         /* Fallthrough */
+      case TGSI_TEXTURE_1D_ARRAY:
+      case TGSI_TEXTURE_2D:
+      case TGSI_TEXTURE_RECT:
+         readmask = TGSI_WRITEMASK_XY;
+         break;
+      case TGSI_TEXTURE_SHADOW2D_ARRAY:
+      case TGSI_TEXTURE_SHADOWCUBE:
+         shadow = TRUE;
+         /* Fallthrough */
+      case TGSI_TEXTURE_2D_ARRAY:
+      case TGSI_TEXTURE_3D:
+      case TGSI_TEXTURE_CUBE:
+         readmask = TGSI_WRITEMASK_XYZ;
+         break;
+      case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
+         shadow = TRUE;
+         /* Fallthrough */
+      case TGSI_TEXTURE_CUBE_ARRAY:
+         readmask = TGSI_WRITEMASK_XYZW;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+
+      tex_info->texture_unit = inst->Src[1].Register.Index;
+      tex_info->sampler_unit = inst->Src[2].Register.Index;
+
+      if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV ||
+          modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_LOD ||
+          modifier == LP_BLD_TEX_MODIFIER_LOD_BIAS || shadow) {
+         /* We don't track insts with additional regs, although we could */
+         indirect = TRUE;
       }
 
       for (chan = 0; chan < 4; ++chan) {
@@ -222,6 +326,22 @@ analyse_instruction(struct analysis_context *ctx,
       case TGSI_OPCODE_TXP:
          analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_PROJECTED);
          break;
+      case TGSI_OPCODE_SAMPLE:
+      case TGSI_OPCODE_SAMPLE_C:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_NONE);
+         break;
+      case TGSI_OPCODE_SAMPLE_C_LZ:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_ZERO);
+         break;
+      case TGSI_OPCODE_SAMPLE_D:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV);
+         break;
+      case TGSI_OPCODE_SAMPLE_B:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_BIAS);
+         break;
+      case TGSI_OPCODE_SAMPLE_L:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_LOD);
+         break;
       default:
          break;
       }
@@ -348,8 +468,9 @@ dump_info(const struct tgsi_token *tokens,
             debug_printf(" _");
          }
       }
-      debug_printf(", SAMP[%u], %s\n",
-                   tex_info->unit,
+      debug_printf(", RES[%u], SAMP[%u], %s\n",
+                   tex_info->texture_unit,
+                   tex_info->sampler_unit,
                    tgsi_texture_names[tex_info->target]);
    }
 
@@ -436,8 +557,12 @@ lp_build_tgsi_info(const struct tgsi_token *tokens,
             assert(size <= 4);
             if (ctx.num_imms < Elements(ctx.imm)) {
                for (chan = 0; chan < size; ++chan) {
-                  ctx.imm[ctx.num_imms][chan] =
-                        parse.FullToken.FullImmediate.u[chan].Float;
+                  float value = parse.FullToken.FullImmediate.u[chan].Float;
+                  ctx.imm[ctx.num_imms][chan] = value;
+
+                  if (value < 0.0f || value > 1.0f) {
+                     info->unclamped_immediates = TRUE;
+                  }
                }
                ++ctx.num_imms;
             }