tgsi: skip texture query opcodes when examining texture targets
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_scan.c
index 4199dbe54de884f4d0eb822286cfc96def57d7e8..d90fb1d68df831066474fefccfd79c0c642312f4 100644 (file)
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_prim.h"
+#include "tgsi/tgsi_info.h"
 #include "tgsi/tgsi_parse.h"
 #include "tgsi/tgsi_util.h"
 #include "tgsi/tgsi_scan.h"
 
 
+static bool
+is_memory_file(unsigned file)
+{
+   return file == TGSI_FILE_SAMPLER ||
+          file == TGSI_FILE_SAMPLER_VIEW ||
+          file == TGSI_FILE_IMAGE ||
+          file == TGSI_FILE_BUFFER;
+}
+
+
+/**
+ * Is the opcode a "true" texture instruction which samples from a
+ * texture map?
+ */
+static bool
+is_texture_inst(unsigned opcode)
+{
+   return (opcode != TGSI_OPCODE_TXQ &&
+           opcode != TGSI_OPCODE_TXQS &&
+           opcode != TGSI_OPCODE_TXQ_LZ &&
+           opcode != TGSI_OPCODE_LODQ &&
+           tgsi_get_opcode_info(opcode)->is_tex);
+}
 
 static void
 scan_instruction(struct tgsi_shader_info *info,
@@ -50,6 +74,7 @@ scan_instruction(struct tgsi_shader_info *info,
                  unsigned *current_depth)
 {
    unsigned i;
+   bool is_mem_inst = false;
 
    assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
    info->opcode_count[fullinst->Instruction.Opcode]++;
@@ -89,13 +114,13 @@ scan_instruction(struct tgsi_shader_info *info,
       case TGSI_INTERPOLATE_PERSPECTIVE:
          switch (fullinst->Instruction.Opcode) {
          case TGSI_OPCODE_INTERP_CENTROID:
-            info->uses_persp_opcode_interp_centroid = true;
+            info->uses_persp_opcode_interp_centroid = TRUE;
             break;
          case TGSI_OPCODE_INTERP_OFFSET:
-            info->uses_persp_opcode_interp_offset = true;
+            info->uses_persp_opcode_interp_offset = TRUE;
             break;
          case TGSI_OPCODE_INTERP_SAMPLE:
-            info->uses_persp_opcode_interp_sample = true;
+            info->uses_persp_opcode_interp_sample = TRUE;
             break;
          }
          break;
@@ -103,13 +128,13 @@ scan_instruction(struct tgsi_shader_info *info,
       case TGSI_INTERPOLATE_LINEAR:
          switch (fullinst->Instruction.Opcode) {
          case TGSI_OPCODE_INTERP_CENTROID:
-            info->uses_linear_opcode_interp_centroid = true;
+            info->uses_linear_opcode_interp_centroid = TRUE;
             break;
          case TGSI_OPCODE_INTERP_OFFSET:
-            info->uses_linear_opcode_interp_offset = true;
+            info->uses_linear_opcode_interp_offset = TRUE;
             break;
          case TGSI_OPCODE_INTERP_SAMPLE:
-            info->uses_linear_opcode_interp_sample = true;
+            info->uses_linear_opcode_interp_sample = TRUE;
             break;
          }
          break;
@@ -118,7 +143,7 @@ scan_instruction(struct tgsi_shader_info *info,
 
    if (fullinst->Instruction.Opcode >= TGSI_OPCODE_F2D &&
        fullinst->Instruction.Opcode <= TGSI_OPCODE_DSSG)
-      info->uses_doubles = true;
+      info->uses_doubles = TRUE;
 
    for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
       const struct tgsi_full_src_register *src = &fullinst->Src[i];
@@ -170,15 +195,47 @@ scan_instruction(struct tgsi_shader_info *info,
          info->indirect_files_read |= (1 << src->Register.File);
       }
 
-      /* MSAA samplers */
+      /* Texture samplers */
       if (src->Register.File == TGSI_FILE_SAMPLER) {
+         const unsigned index = src->Register.Index;
+
          assert(fullinst->Instruction.Texture);
-         assert(src->Register.Index < Elements(info->is_msaa_sampler));
+         assert(index < Elements(info->is_msaa_sampler));
+         assert(index < PIPE_MAX_SAMPLERS);
+
+         if (is_texture_inst(fullinst->Instruction.Opcode)) {
+            const unsigned target = fullinst->Texture.Texture;
+            assert(target < TGSI_TEXTURE_UNKNOWN);
+            /* for texture instructions, check that the texture instruction
+             * target matches the previous sampler view declaration (if there
+             * was one.)
+             */
+            if (info->sampler_targets[index] == TGSI_TEXTURE_UNKNOWN) {
+               /* probably no sampler view declaration */
+               info->sampler_targets[index] = target;
+            } else {
+               /* Make sure the texture instruction's sampler/target info
+                * agrees with the sampler view declaration.
+                */
+               assert(info->sampler_targets[index] == target);
+            }
+            /* MSAA samplers */
+            if (target == TGSI_TEXTURE_2D_MSAA ||
+                target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
+               info->is_msaa_sampler[src->Register.Index] = TRUE;
+            }
+         }
+      }
+
+      if (is_memory_file(src->Register.File)) {
+         is_mem_inst = true;
 
-         if (fullinst->Instruction.Texture &&
-             (fullinst->Texture.Texture == TGSI_TEXTURE_2D_MSAA ||
-              fullinst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA)) {
-            info->is_msaa_sampler[src->Register.Index] = TRUE;
+         if (tgsi_get_opcode_info(fullinst->Instruction.Opcode)->is_store) {
+            info->writes_memory = TRUE;
+
+            if (src->Register.File == TGSI_FILE_IMAGE &&
+                !src->Register.Indirect)
+               info->images_writemask |= 1 << src->Register.Index;
          }
       }
    }
@@ -190,8 +247,22 @@ scan_instruction(struct tgsi_shader_info *info,
          info->indirect_files |= (1 << dst->Register.File);
          info->indirect_files_written |= (1 << dst->Register.File);
       }
+
+      if (is_memory_file(dst->Register.File)) {
+         assert(fullinst->Instruction.Opcode == TGSI_OPCODE_STORE);
+
+         is_mem_inst = true;
+         info->writes_memory = TRUE;
+
+         if (dst->Register.File == TGSI_FILE_IMAGE &&
+             !dst->Register.Indirect)
+            info->images_writemask |= 1 << dst->Register.Index;
+      }
    }
 
+   if (is_mem_inst)
+      info->num_memory_instructions++;
+
    info->num_instructions++;
 }
      
@@ -247,7 +318,14 @@ scan_declaration(struct tgsi_shader_info *info,
          info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate;
          info->input_interpolate_loc[reg] = (ubyte)fulldecl->Interp.Location;
          info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
-         info->num_inputs++;
+
+         /* Vertex shaders can have inputs with holes between them. */
+         if (info->processor == TGSI_PROCESSOR_VERTEX)
+            info->num_inputs = MAX2(info->num_inputs, reg + 1);
+         else {
+            info->num_inputs++;
+            assert(reg < info->num_inputs);
+         }
 
          /* Only interpolated varyings. Don't include POSITION.
           * Don't include integer varyings, because they are not
@@ -265,26 +343,26 @@ scan_declaration(struct tgsi_shader_info *info,
             case TGSI_INTERPOLATE_PERSPECTIVE:
                switch (fulldecl->Interp.Location) {
                case TGSI_INTERPOLATE_LOC_CENTER:
-                  info->uses_persp_center = true;
+                  info->uses_persp_center = TRUE;
                   break;
                case TGSI_INTERPOLATE_LOC_CENTROID:
-                  info->uses_persp_centroid = true;
+                  info->uses_persp_centroid = TRUE;
                   break;
                case TGSI_INTERPOLATE_LOC_SAMPLE:
-                  info->uses_persp_sample = true;
+                  info->uses_persp_sample = TRUE;
                   break;
                }
                break;
             case TGSI_INTERPOLATE_LINEAR:
                switch (fulldecl->Interp.Location) {
                case TGSI_INTERPOLATE_LOC_CENTER:
-                  info->uses_linear_center = true;
+                  info->uses_linear_center = TRUE;
                   break;
                case TGSI_INTERPOLATE_LOC_CENTROID:
-                  info->uses_linear_centroid = true;
+                  info->uses_linear_centroid = TRUE;
                   break;
                case TGSI_INTERPOLATE_LOC_SAMPLE:
-                  info->uses_linear_sample = true;
+                  info->uses_linear_sample = TRUE;
                   break;
                }
                break;
@@ -307,33 +385,41 @@ scan_declaration(struct tgsi_shader_info *info,
          info->system_value_semantic_name[index] = semName;
          info->num_system_values = MAX2(info->num_system_values, index + 1);
 
-         if (semName == TGSI_SEMANTIC_INSTANCEID) {
+         switch (semName) {
+         case TGSI_SEMANTIC_INSTANCEID:
             info->uses_instanceid = TRUE;
-         }
-         else if (semName == TGSI_SEMANTIC_VERTEXID) {
+            break;
+         case TGSI_SEMANTIC_VERTEXID:
             info->uses_vertexid = TRUE;
-         }
-         else if (semName == TGSI_SEMANTIC_VERTEXID_NOBASE) {
+            break;
+         case TGSI_SEMANTIC_VERTEXID_NOBASE:
             info->uses_vertexid_nobase = TRUE;
-         }
-         else if (semName == TGSI_SEMANTIC_BASEVERTEX) {
+            break;
+         case TGSI_SEMANTIC_BASEVERTEX:
             info->uses_basevertex = TRUE;
-         }
-         else if (semName == TGSI_SEMANTIC_PRIMID) {
+            break;
+         case TGSI_SEMANTIC_PRIMID:
             info->uses_primid = TRUE;
-         } else if (semName == TGSI_SEMANTIC_INVOCATIONID) {
+            break;
+         case TGSI_SEMANTIC_INVOCATIONID:
             info->uses_invocationid = TRUE;
-         } else if (semName == TGSI_SEMANTIC_POSITION)
+            break;
+         case TGSI_SEMANTIC_POSITION:
             info->reads_position = TRUE;
-         else if (semName == TGSI_SEMANTIC_FACE)
+            break;
+         case TGSI_SEMANTIC_FACE:
             info->uses_frontface = TRUE;
-         else if (semName == TGSI_SEMANTIC_SAMPLEMASK)
+            break;
+         case TGSI_SEMANTIC_SAMPLEMASK:
             info->reads_samplemask = TRUE;
+            break;
+         }
       }
       else if (file == TGSI_FILE_OUTPUT) {
          info->output_semantic_name[reg] = (ubyte) semName;
          info->output_semantic_index[reg] = (ubyte) semIndex;
          info->num_outputs++;
+         assert(reg < info->num_outputs);
 
          if (semName == TGSI_SEMANTIC_COLOR)
             info->colors_written |= 1 << semIndex;
@@ -342,28 +428,33 @@ scan_declaration(struct tgsi_shader_info *info,
              procType == TGSI_PROCESSOR_GEOMETRY ||
              procType == TGSI_PROCESSOR_TESS_CTRL ||
              procType == TGSI_PROCESSOR_TESS_EVAL) {
-            if (semName == TGSI_SEMANTIC_VIEWPORT_INDEX) {
+            switch (semName) {
+            case TGSI_SEMANTIC_VIEWPORT_INDEX:
                info->writes_viewport_index = TRUE;
-            }
-            else if (semName == TGSI_SEMANTIC_LAYER) {
+               break;
+            case TGSI_SEMANTIC_LAYER:
                info->writes_layer = TRUE;
-            }
-            else if (semName == TGSI_SEMANTIC_PSIZE) {
+               break;
+            case TGSI_SEMANTIC_PSIZE:
                info->writes_psize = TRUE;
-            }
-            else if (semName == TGSI_SEMANTIC_CLIPVERTEX) {
+               break;
+            case TGSI_SEMANTIC_CLIPVERTEX:
                info->writes_clipvertex = TRUE;
+               break;
             }
          }
 
          if (procType == TGSI_PROCESSOR_FRAGMENT) {
-            if (semName == TGSI_SEMANTIC_POSITION) {
+            switch (semName) {
+            case TGSI_SEMANTIC_POSITION:
                info->writes_z = TRUE;
-            }
-            else if (semName == TGSI_SEMANTIC_STENCIL) {
+               break;
+            case TGSI_SEMANTIC_STENCIL:
                info->writes_stencil = TRUE;
-            } else if (semName == TGSI_SEMANTIC_SAMPLEMASK) {
+               break;
+            case TGSI_SEMANTIC_SAMPLEMASK:
                info->writes_samplemask = TRUE;
+               break;
             }
          }
 
@@ -374,6 +465,19 @@ scan_declaration(struct tgsi_shader_info *info,
          }
       } else if (file == TGSI_FILE_SAMPLER) {
          info->samplers_declared |= 1 << reg;
+      } else if (file == TGSI_FILE_SAMPLER_VIEW) {
+         unsigned target = fulldecl->SamplerView.Resource;
+         assert(target < TGSI_TEXTURE_UNKNOWN);
+         if (info->sampler_targets[reg] == TGSI_TEXTURE_UNKNOWN) {
+            /* Save sampler target for this sampler index */
+            info->sampler_targets[reg] = target;
+         } else {
+            /* if previously declared, make sure targets agree */
+            assert(info->sampler_targets[reg] == target);
+         }
+      } else if (file == TGSI_FILE_IMAGE) {
+         if (fulldecl->Image.Resource == TGSI_TEXTURE_BUFFER)
+            info->images_buffers |= 1 << reg;
       }
    }
 }
@@ -433,6 +537,8 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
    for (i = 0; i < Elements(info->const_file_max); i++)
       info->const_file_max[i] = -1;
    info->properties[TGSI_PROPERTY_GS_INVOCATIONS] = 1;
+   for (i = 0; i < Elements(info->sampler_targets); i++)
+      info->sampler_targets[i] = TGSI_TEXTURE_UNKNOWN;
 
    /**
     ** Setup to begin parsing input shader
@@ -450,12 +556,10 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
           procType == TGSI_PROCESSOR_COMPUTE);
    info->processor = procType;
 
-
    /**
     ** Loop over incoming program tokens/instructions
     */
-   while( !tgsi_parse_end_of_tokens( &parse ) ) {
-
+   while (!tgsi_parse_end_of_tokens(&parse)) {
       info->num_tokens++;
 
       tgsi_parse_token( &parse );
@@ -498,7 +602,7 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
       }
    }
 
-   tgsi_parse_free (&parse);
+   tgsi_parse_free(&parse);
 }