radeonsi/gfx10: fix the vertex order for triangle strips emitted by a GS
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_tgsi_info.c
index ab393ed942a022c9025b49d2a6bc5e7bf2c107a1..9738770abe251ac2f6ed98b551eccad5d2e83789 100644 (file)
@@ -47,7 +47,8 @@ struct analysis_context
    struct lp_tgsi_info *info;
 
    unsigned num_imms;
-   float imm[32][4];
+   float imm[LP_MAX_TGSI_IMMEDIATES][4];
+   unsigned sample_target[PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
    struct lp_tgsi_channel_info temp[32][4];
 };
@@ -66,14 +67,14 @@ analyse_src(struct analysis_context *ctx,
    if (!src->Indirect && !src->Absolute && !src->Negate) {
       unsigned swizzle = tgsi_util_get_src_register_swizzle(src, chan);
       if (src->File == TGSI_FILE_TEMPORARY) {
-         if (src->Index < Elements(ctx->temp)) {
+         if (src->Index < ARRAY_SIZE(ctx->temp)) {
             *chan_info = ctx->temp[src->Index][swizzle];
          }
       } else {
          chan_info->file = src->File;
          if (src->File == TGSI_FILE_IMMEDIATE) {
-            assert(src->Index < Elements(ctx->imm));
-            if (src->Index < Elements(ctx->imm)) {
+            assert(src->Index < ARRAY_SIZE(ctx->imm));
+            if (src->Index < ARRAY_SIZE(ctx->imm)) {
                chan_info->u.value = ctx->imm[src->Index][swizzle];
             }
          } else {
@@ -96,6 +97,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,
@@ -104,7 +110,7 @@ analyse_tex(struct analysis_context *ctx,
    struct lp_tgsi_info *info = ctx->info;
    unsigned chan;
 
-   if (info->num_texs < Elements(info->tex)) {
+   if (info->num_texs < ARRAY_SIZE(info->tex)) {
       struct lp_tgsi_texture_info *tex_info = &info->tex[info->num_texs];
       boolean indirect = FALSE;
       unsigned readmask = 0;
@@ -124,12 +130,24 @@ analyse_tex(struct analysis_context *ctx,
       case TGSI_TEXTURE_SHADOW2D:
       case TGSI_TEXTURE_SHADOWRECT:
       case TGSI_TEXTURE_2D_ARRAY:
+      case TGSI_TEXTURE_2D_MSAA:
       case TGSI_TEXTURE_3D:
       case TGSI_TEXTURE_CUBE:
          readmask = TGSI_WRITEMASK_XYZ;
          break;
       case TGSI_TEXTURE_SHADOW2D_ARRAY:
+      case TGSI_TEXTURE_SHADOWCUBE:
+      case TGSI_TEXTURE_2D_ARRAY_MSAA:
+      case TGSI_TEXTURE_CUBE_ARRAY:
+         readmask = TGSI_WRITEMASK_XYZW;
+         /* modifier would be in another not analyzed reg so just say indirect */
+         if (modifier != LP_BLD_TEX_MODIFIER_NONE) {
+            indirect = TRUE;
+         }
+         break;
+      case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
          readmask = TGSI_WRITEMASK_XYZW;
+         indirect = TRUE;
          break;
       default:
          assert(0);
@@ -139,14 +157,101 @@ 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,
+               boolean shadow)
+{
+   struct lp_tgsi_info *info = ctx->info;
+   unsigned chan;
+
+   if (info->num_texs < ARRAY_SIZE(info->tex)) {
+      struct lp_tgsi_texture_info *tex_info = &info->tex[info->num_texs];
+      unsigned target = ctx->sample_target[inst->Src[1].Register.Index];
+      boolean indirect = FALSE;
+      boolean shadow = FALSE;
+      unsigned readmask;
+
+      switch (target) {
+      /* note no shadow targets here */
+      case TGSI_TEXTURE_BUFFER:
+      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_2D_ARRAY:
+      case TGSI_TEXTURE_2D_MSAA:
+      case TGSI_TEXTURE_3D:
+      case TGSI_TEXTURE_CUBE:
+         readmask = TGSI_WRITEMASK_XYZ;
+         break;
+      case TGSI_TEXTURE_CUBE_ARRAY:
+      case TGSI_TEXTURE_2D_ARRAY_MSAA:
+         readmask = TGSI_WRITEMASK_XYZW;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+
+      tex_info->target = target;
+      tex_info->texture_unit = inst->Src[1].Register.Index;
+      tex_info->sampler_unit = inst->Src[2].Register.Index;
+
+      if (tex_info->texture_unit != tex_info->sampler_unit) {
+         info->sampler_texture_units_different = TRUE;
+      }
+
+      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) {
@@ -196,12 +301,17 @@ analyse_instruction(struct analysis_context *ctx,
 
       if (dst->File == TGSI_FILE_TEMPORARY) {
          regs = ctx->temp;
-         max_regs = Elements(ctx->temp);
+         max_regs = ARRAY_SIZE(ctx->temp);
       } else if (dst->File == TGSI_FILE_OUTPUT) {
          regs = info->output;
-         max_regs = Elements(info->output);
-      } else if (dst->File == TGSI_FILE_ADDRESS ||
-                 dst->File == TGSI_FILE_PREDICATE) {
+         max_regs = ARRAY_SIZE(info->output);
+      } else if (dst->File == TGSI_FILE_ADDRESS) {
+         continue;
+      } else if (dst->File == TGSI_FILE_BUFFER) {
+         continue;
+      } else if (dst->File == TGSI_FILE_IMAGE) {
+         continue;
+      } else if (dst->File == TGSI_FILE_MEMORY) {
          continue;
       } else {
          assert(0);
@@ -228,6 +338,33 @@ analyse_instruction(struct analysis_context *ctx,
       case TGSI_OPCODE_TXP:
          analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_PROJECTED);
          break;
+      case TGSI_OPCODE_TEX2:
+         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_NONE);
+         break;
+      case TGSI_OPCODE_TXB2:
+         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_BIAS);
+         break;
+      case TGSI_OPCODE_TXL2:
+         analyse_tex(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_LOD);
+         break;
+      case TGSI_OPCODE_SAMPLE:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_NONE, FALSE);
+         break;
+      case TGSI_OPCODE_SAMPLE_C:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_NONE, TRUE);
+         break;
+      case TGSI_OPCODE_SAMPLE_C_LZ:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_ZERO, TRUE);
+         break;
+      case TGSI_OPCODE_SAMPLE_D:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_DERIV, FALSE);
+         break;
+      case TGSI_OPCODE_SAMPLE_B:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_LOD_BIAS, FALSE);
+         break;
+      case TGSI_OPCODE_SAMPLE_L:
+         analyse_sample(ctx, inst, LP_BLD_TEX_MODIFIER_EXPLICIT_LOD, FALSE);
+         break;
       default:
          break;
       }
@@ -257,8 +394,7 @@ analyse_instruction(struct analysis_context *ctx,
 
          memset(res, 0, sizeof res);
 
-         if (!inst->Instruction.Predicate &&
-             !inst->Instruction.Saturate) {
+         if (!inst->Instruction.Saturate) {
             for (chan = 0; chan < 4; ++chan) {
                if (dst->WriteMask & (1 << chan)) {
                   if (inst->Instruction.Opcode == TGSI_OPCODE_MOV) {
@@ -303,15 +439,13 @@ analyse_instruction(struct analysis_context *ctx,
 
    switch (inst->Instruction.Opcode) {
    case TGSI_OPCODE_IF:
-   case TGSI_OPCODE_IFC:
+   case TGSI_OPCODE_UIF:
    case TGSI_OPCODE_ELSE:
    case TGSI_OPCODE_ENDIF:
    case TGSI_OPCODE_BGNLOOP:
    case TGSI_OPCODE_BRK:
-   case TGSI_OPCODE_BREAKC:
    case TGSI_OPCODE_CONT:
    case TGSI_OPCODE_ENDLOOP:
-   case TGSI_OPCODE_CALLNZ:
    case TGSI_OPCODE_CAL:
    case TGSI_OPCODE_BGNSUB:
    case TGSI_OPCODE_ENDSUB:
@@ -330,7 +464,7 @@ analyse_instruction(struct analysis_context *ctx,
 }
 
 
-static INLINE void
+static inline void
 dump_info(const struct tgsi_token *tokens,
           struct lp_tgsi_info *info)
 {
@@ -347,15 +481,16 @@ dump_info(const struct tgsi_token *tokens,
                &tex_info->coord[chan];
          if (chan_info->file != TGSI_FILE_NULL) {
             debug_printf(" %s[%u].%c",
-                         tgsi_file_names[chan_info->file],
+                         tgsi_file_name(chan_info->file),
                          chan_info->u.index,
                          "xyzw01"[chan_info->swizzle]);
          } else {
             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]);
    }
 
@@ -400,7 +535,7 @@ lp_build_tgsi_info(const struct tgsi_token *tokens,
                    struct lp_tgsi_info *info)
 {
    struct tgsi_parse_context parse;
-   struct analysis_context ctx;
+   struct analysis_context *ctx;
    unsigned index;
    unsigned chan;
 
@@ -408,8 +543,8 @@ lp_build_tgsi_info(const struct tgsi_token *tokens,
 
    tgsi_scan_shader(tokens, &info->base);
 
-   memset(&ctx, 0, sizeof ctx);
-   ctx.info = info;
+   ctx = CALLOC(1, sizeof(struct analysis_context));
+   ctx->info = info;
 
    tgsi_parse_init(&parse, tokens);
 
@@ -417,7 +552,14 @@ lp_build_tgsi_info(const struct tgsi_token *tokens,
       tgsi_parse_token(&parse);
 
       switch (parse.FullToken.Token.Type) {
-      case TGSI_TOKEN_TYPE_DECLARATION:
+      case TGSI_TOKEN_TYPE_DECLARATION: {
+         struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration;
+         if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
+            for (index = decl->Range.First; index <= decl->Range.Last; index++) {
+               ctx->sample_target[index] = decl->SamplerView.Resource;
+            }
+         }
+      }
          break;
 
       case TGSI_TOKEN_TYPE_INSTRUCTION:
@@ -431,7 +573,7 @@ lp_build_tgsi_info(const struct tgsi_token *tokens,
                goto finished;
             }
 
-            analyse_instruction(&ctx, inst);
+            analyse_instruction(ctx, inst);
          }
          break;
 
@@ -440,16 +582,16 @@ lp_build_tgsi_info(const struct tgsi_token *tokens,
             const unsigned size =
                   parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
             assert(size <= 4);
-            if (ctx.num_imms < Elements(ctx.imm)) {
+            if (ctx->num_imms < ARRAY_SIZE(ctx->imm)) {
                for (chan = 0; chan < size; ++chan) {
                   float value = parse.FullToken.FullImmediate.u[chan].Float;
-                  ctx.imm[ctx.num_imms][chan] = value;
+                  ctx->imm[ctx->num_imms][chan] = value;
 
                   if (value < 0.0f || value > 1.0f) {
                      info->unclamped_immediates = TRUE;
                   }
                }
-               ++ctx.num_imms;
+               ++ctx->num_imms;
             }
          }
          break;
@@ -464,6 +606,7 @@ lp_build_tgsi_info(const struct tgsi_token *tokens,
 finished:
 
    tgsi_parse_free(&parse);
+   FREE(ctx);
 
 
    /*
@@ -471,7 +614,7 @@ finished:
     */
 
    for (index = 0; index < PIPE_MAX_COLOR_BUFS; ++index) {
-      const struct lp_tgsi_channel_info null_output[4];
+      static const struct lp_tgsi_channel_info null_output[4];
       info->cbuf[index] = null_output;
    }