~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/gallium/auxiliary/tgsi/tgsi_scan.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
 
46
46
 
47
47
static bool
48
 
is_memory_file(unsigned file)
 
48
is_memory_file(enum tgsi_file_type file)
49
49
{
50
50
   return file == TGSI_FILE_SAMPLER ||
51
51
          file == TGSI_FILE_SAMPLER_VIEW ||
191
191
            case TGSI_INTERPOLATE_PERSPECTIVE:
192
192
               switch (info->input_interpolate_loc[input]) {
193
193
               case TGSI_INTERPOLATE_LOC_CENTER:
194
 
                  info->uses_persp_center = TRUE;
 
194
                  info->uses_persp_center = true;
195
195
                  break;
196
196
               case TGSI_INTERPOLATE_LOC_CENTROID:
197
 
                  info->uses_persp_centroid = TRUE;
 
197
                  info->uses_persp_centroid = true;
198
198
                  break;
199
199
               case TGSI_INTERPOLATE_LOC_SAMPLE:
200
 
                  info->uses_persp_sample = TRUE;
 
200
                  info->uses_persp_sample = true;
201
201
                  break;
202
202
               }
203
203
               break;
204
204
            case TGSI_INTERPOLATE_LINEAR:
205
205
               switch (info->input_interpolate_loc[input]) {
206
206
               case TGSI_INTERPOLATE_LOC_CENTER:
207
 
                  info->uses_linear_center = TRUE;
 
207
                  info->uses_linear_center = true;
208
208
                  break;
209
209
               case TGSI_INTERPOLATE_LOC_CENTROID:
210
 
                  info->uses_linear_centroid = TRUE;
 
210
                  info->uses_linear_centroid = true;
211
211
                  break;
212
212
               case TGSI_INTERPOLATE_LOC_SAMPLE:
213
 
                  info->uses_linear_sample = TRUE;
 
213
                  info->uses_linear_sample = true;
214
214
                  break;
215
215
               }
216
216
               break;
303
303
      }
304
304
 
305
305
      if (tgsi_get_opcode_info(fullinst->Instruction.Opcode)->is_store) {
306
 
         info->writes_memory = TRUE;
 
306
         info->writes_memory = true;
307
307
 
308
308
         if (src->Register.File == TGSI_FILE_IMAGE) {
309
309
            if (src->Register.Indirect)
451
451
      case TGSI_INTERPOLATE_PERSPECTIVE:
452
452
         switch (fullinst->Instruction.Opcode) {
453
453
         case TGSI_OPCODE_INTERP_CENTROID:
454
 
            info->uses_persp_opcode_interp_centroid = TRUE;
 
454
            info->uses_persp_opcode_interp_centroid = true;
455
455
            break;
456
456
         case TGSI_OPCODE_INTERP_OFFSET:
457
 
            info->uses_persp_opcode_interp_offset = TRUE;
 
457
            info->uses_persp_opcode_interp_offset = true;
458
458
            break;
459
459
         case TGSI_OPCODE_INTERP_SAMPLE:
460
 
            info->uses_persp_opcode_interp_sample = TRUE;
 
460
            info->uses_persp_opcode_interp_sample = true;
461
461
            break;
462
462
         }
463
463
         break;
465
465
      case TGSI_INTERPOLATE_LINEAR:
466
466
         switch (fullinst->Instruction.Opcode) {
467
467
         case TGSI_OPCODE_INTERP_CENTROID:
468
 
            info->uses_linear_opcode_interp_centroid = TRUE;
 
468
            info->uses_linear_opcode_interp_centroid = true;
469
469
            break;
470
470
         case TGSI_OPCODE_INTERP_OFFSET:
471
 
            info->uses_linear_opcode_interp_offset = TRUE;
 
471
            info->uses_linear_opcode_interp_offset = true;
472
472
            break;
473
473
         case TGSI_OPCODE_INTERP_SAMPLE:
474
 
            info->uses_linear_opcode_interp_sample = TRUE;
 
474
            info->uses_linear_opcode_interp_sample = true;
475
475
            break;
476
476
         }
477
477
         break;
486
486
       fullinst->Instruction.Opcode == TGSI_OPCODE_D2I64 ||
487
487
       fullinst->Instruction.Opcode == TGSI_OPCODE_U642D ||
488
488
       fullinst->Instruction.Opcode == TGSI_OPCODE_I642D)
489
 
      info->uses_doubles = TRUE;
 
489
      info->uses_doubles = true;
490
490
 
491
491
   for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
492
492
      scan_src_operand(info, fullinst, &fullinst->Src[i], i,
566
566
         assert(fullinst->Instruction.Opcode == TGSI_OPCODE_STORE);
567
567
 
568
568
         is_mem_inst = true;
569
 
         info->writes_memory = TRUE;
 
569
         info->writes_memory = true;
570
570
 
571
571
         if (dst->Register.File == TGSI_FILE_IMAGE) {
572
572
            if (fullinst->Memory.Texture == TGSI_TEXTURE_2D_MSAA ||
604
604
scan_declaration(struct tgsi_shader_info *info,
605
605
                 const struct tgsi_full_declaration *fulldecl)
606
606
{
607
 
   const uint file = fulldecl->Declaration.File;
 
607
   enum tgsi_file_type file = fulldecl->Declaration.File;
608
608
   const unsigned procType = info->processor;
609
 
   uint reg;
 
609
   unsigned reg;
610
610
 
611
611
   if (fulldecl->Declaration.Array) {
612
612
      unsigned array_id = fulldecl->Array.ArrayID;
620
620
         assert(array_id < ARRAY_SIZE(info->output_array_first));
621
621
         info->output_array_first[array_id] = fulldecl->Range.First;
622
622
         break;
 
623
 
 
624
      case TGSI_FILE_NULL:
 
625
         unreachable("unexpected file");
 
626
 
 
627
      default:
 
628
         break;
623
629
      }
624
630
      info->array_max[file] = MAX2(info->array_max[file], array_id);
625
631
   }
666
672
         break;
667
673
 
668
674
      case TGSI_FILE_INPUT:
669
 
         info->input_semantic_name[reg] = (ubyte) semName;
670
 
         info->input_semantic_index[reg] = (ubyte) semIndex;
671
 
         info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate;
672
 
         info->input_interpolate_loc[reg] = (ubyte)fulldecl->Interp.Location;
 
675
         info->input_semantic_name[reg] = (uint8_t) semName;
 
676
         info->input_semantic_index[reg] = (uint8_t) semIndex;
 
677
         info->input_interpolate[reg] = (uint8_t)fulldecl->Interp.Interpolate;
 
678
         info->input_interpolate_loc[reg] = (uint8_t)fulldecl->Interp.Location;
673
679
 
674
680
         /* Vertex shaders can have inputs with holes between them. */
675
681
         info->num_inputs = MAX2(info->num_inputs, reg + 1);
695
701
 
696
702
         switch (semName) {
697
703
         case TGSI_SEMANTIC_INSTANCEID:
698
 
            info->uses_instanceid = TRUE;
 
704
            info->uses_instanceid = true;
699
705
            break;
700
706
         case TGSI_SEMANTIC_VERTEXID:
701
 
            info->uses_vertexid = TRUE;
 
707
            info->uses_vertexid = true;
702
708
            break;
703
709
         case TGSI_SEMANTIC_VERTEXID_NOBASE:
704
 
            info->uses_vertexid_nobase = TRUE;
 
710
            info->uses_vertexid_nobase = true;
705
711
            break;
706
712
         case TGSI_SEMANTIC_BASEVERTEX:
707
 
            info->uses_basevertex = TRUE;
 
713
            info->uses_basevertex = true;
708
714
            break;
709
715
         case TGSI_SEMANTIC_DRAWID:
710
 
            info->uses_drawid = TRUE;
 
716
            info->uses_drawid = true;
711
717
            break;
712
718
         case TGSI_SEMANTIC_PRIMID:
713
 
            info->uses_primid = TRUE;
 
719
            info->uses_primid = true;
714
720
            break;
715
721
         case TGSI_SEMANTIC_INVOCATIONID:
716
 
            info->uses_invocationid = TRUE;
 
722
            info->uses_invocationid = true;
717
723
            break;
718
724
         case TGSI_SEMANTIC_POSITION:
719
 
            info->reads_position = TRUE;
 
725
            info->reads_position = true;
720
726
            break;
721
727
         case TGSI_SEMANTIC_FACE:
722
 
            info->uses_frontface = TRUE;
 
728
            info->uses_frontface = true;
723
729
            break;
724
730
         case TGSI_SEMANTIC_SAMPLEMASK:
725
 
            info->reads_samplemask = TRUE;
 
731
            info->reads_samplemask = true;
726
732
            break;
727
733
         case TGSI_SEMANTIC_TESSINNER:
728
734
         case TGSI_SEMANTIC_TESSOUTER:
732
738
         break;
733
739
 
734
740
      case TGSI_FILE_OUTPUT:
735
 
         info->output_semantic_name[reg] = (ubyte) semName;
736
 
         info->output_semantic_index[reg] = (ubyte) semIndex;
 
741
         info->output_semantic_name[reg] = (uint8_t) semName;
 
742
         info->output_semantic_index[reg] = (uint8_t) semIndex;
737
743
         info->output_usagemask[reg] |= fulldecl->Declaration.UsageMask;
738
744
         info->num_outputs = MAX2(info->num_outputs, reg + 1);
739
745
 
740
746
         if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_X) {
741
 
            info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamX;
 
747
            info->output_streams[reg] |= (uint8_t)fulldecl->Semantic.StreamX;
742
748
            info->num_stream_output_components[fulldecl->Semantic.StreamX]++;
743
749
         }
744
750
         if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_Y) {
745
 
            info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamY << 2;
 
751
            info->output_streams[reg] |= (uint8_t)fulldecl->Semantic.StreamY << 2;
746
752
            info->num_stream_output_components[fulldecl->Semantic.StreamY]++;
747
753
         }
748
754
         if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_Z) {
749
 
            info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamZ << 4;
 
755
            info->output_streams[reg] |= (uint8_t)fulldecl->Semantic.StreamZ << 4;
750
756
            info->num_stream_output_components[fulldecl->Semantic.StreamZ]++;
751
757
         }
752
758
         if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_W) {
753
 
            info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamW << 6;
 
759
            info->output_streams[reg] |= (uint8_t)fulldecl->Semantic.StreamW << 6;
754
760
            info->num_stream_output_components[fulldecl->Semantic.StreamW]++;
755
761
         }
756
762
 
811
817
            assert(info->sampler_type[reg] == type);
812
818
         }
813
819
         break;
 
820
 
 
821
      case TGSI_FILE_NULL:
 
822
         unreachable("unexpected file");
 
823
 
 
824
      default:
 
825
         break;
814
826
      }
815
827
   }
816
828
}
819
831
static void
820
832
scan_immediate(struct tgsi_shader_info *info)
821
833
{
822
 
   uint reg = info->immediate_count++;
823
 
   uint file = TGSI_FILE_IMMEDIATE;
 
834
   unsigned reg = info->immediate_count++;
 
835
   enum tgsi_file_type file = TGSI_FILE_IMMEDIATE;
824
836
 
825
837
   info->file_mask[file] |= (1 << reg);
826
838
   info->file_count[file]++;
860
872
tgsi_scan_shader(const struct tgsi_token *tokens,
861
873
                 struct tgsi_shader_info *info)
862
874
{
863
 
   uint procType, i;
 
875
   unsigned procType, i;
864
876
   struct tgsi_parse_context parse;
865
877
   unsigned current_depth = 0;
866
878
 
939
951
   tgsi_parse_free(&parse);
940
952
}
941
953
 
942
 
/**
943
 
 * Collect information about the arrays of a given register file.
944
 
 *
945
 
 * @param tokens TGSI shader
946
 
 * @param file the register file to scan through
947
 
 * @param max_array_id number of entries in @p arrays; should be equal to the
948
 
 *                     highest array id, i.e. tgsi_shader_info::array_max[file].
949
 
 * @param arrays info for array of each ID will be written to arrays[ID - 1].
950
 
 */
951
 
void
952
 
tgsi_scan_arrays(const struct tgsi_token *tokens,
953
 
                 unsigned file,
954
 
                 unsigned max_array_id,
955
 
                 struct tgsi_array_info *arrays)
956
 
{
957
 
   struct tgsi_parse_context parse;
958
 
 
959
 
   if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
960
 
      debug_printf("tgsi_parse_init() failed in tgsi_scan_arrays()!\n");
961
 
      return;
962
 
   }
963
 
 
964
 
   memset(arrays, 0, sizeof(arrays[0]) * max_array_id);
965
 
 
966
 
   while (!tgsi_parse_end_of_tokens(&parse)) {
967
 
      struct tgsi_full_instruction *inst;
968
 
 
969
 
      tgsi_parse_token(&parse);
970
 
 
971
 
      if (parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_DECLARATION) {
972
 
         struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration;
973
 
 
974
 
         if (decl->Declaration.Array && decl->Declaration.File == file &&
975
 
             decl->Array.ArrayID > 0 && decl->Array.ArrayID <= max_array_id) {
976
 
            struct tgsi_array_info *array = &arrays[decl->Array.ArrayID - 1];
977
 
            assert(!array->declared);
978
 
            array->declared = true;
979
 
            array->range = decl->Range;
980
 
         }
981
 
      }
982
 
 
983
 
      if (parse.FullToken.Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION)
984
 
         continue;
985
 
 
986
 
      inst = &parse.FullToken.FullInstruction;
987
 
      for (unsigned i = 0; i < inst->Instruction.NumDstRegs; i++) {
988
 
         const struct tgsi_full_dst_register *dst = &inst->Dst[i];
989
 
         if (dst->Register.File != file)
990
 
            continue;
991
 
 
992
 
         if (dst->Register.Indirect) {
993
 
            if (dst->Indirect.ArrayID > 0 &&
994
 
                dst->Indirect.ArrayID <= max_array_id) {
995
 
               arrays[dst->Indirect.ArrayID - 1].writemask |= dst->Register.WriteMask;
996
 
            } else {
997
 
               /* Indirect writes without an ArrayID can write anywhere. */
998
 
               for (unsigned j = 0; j < max_array_id; ++j)
999
 
                  arrays[j].writemask |= dst->Register.WriteMask;
1000
 
            }
1001
 
         } else {
1002
 
            /* Check whether the write falls into any of the arrays anyway. */
1003
 
            for (unsigned j = 0; j < max_array_id; ++j) {
1004
 
               struct tgsi_array_info *array = &arrays[j];
1005
 
               if (array->declared &&
1006
 
                   dst->Register.Index >= array->range.First &&
1007
 
                   dst->Register.Index <= array->range.Last)
1008
 
                  array->writemask |= dst->Register.WriteMask;
1009
 
            }
1010
 
         }
1011
 
      }
1012
 
   }
1013
 
 
1014
 
   tgsi_parse_free(&parse);
1015
 
 
1016
 
   return;
1017
 
}
1018
 
 
1019
 
static void
1020
 
check_no_subroutines(const struct tgsi_full_instruction *inst)
1021
 
{
1022
 
   switch (inst->Instruction.Opcode) {
1023
 
   case TGSI_OPCODE_BGNSUB:
1024
 
   case TGSI_OPCODE_ENDSUB:
1025
 
   case TGSI_OPCODE_CAL:
1026
 
      unreachable("subroutines unhandled");
1027
 
   }
1028
 
}
1029
 
 
1030
 
static unsigned
1031
 
get_inst_tessfactor_writemask(const struct tgsi_shader_info *info,
1032
 
                              const struct tgsi_full_instruction *inst)
1033
 
{
1034
 
   unsigned writemask = 0;
1035
 
 
1036
 
   for (unsigned i = 0; i < inst->Instruction.NumDstRegs; i++) {
1037
 
      const struct tgsi_full_dst_register *dst = &inst->Dst[i];
1038
 
 
1039
 
      if (dst->Register.File == TGSI_FILE_OUTPUT &&
1040
 
          !dst->Register.Indirect) {
1041
 
         unsigned name = info->output_semantic_name[dst->Register.Index];
1042
 
 
1043
 
         if (name == TGSI_SEMANTIC_TESSINNER)
1044
 
            writemask |= dst->Register.WriteMask;
1045
 
         else if (name == TGSI_SEMANTIC_TESSOUTER)
1046
 
            writemask |= dst->Register.WriteMask << 4;
1047
 
      }
1048
 
   }
1049
 
   return writemask;
1050
 
}
1051
 
 
1052
 
static unsigned
1053
 
get_block_tessfactor_writemask(const struct tgsi_shader_info *info,
1054
 
                               struct tgsi_parse_context *parse,
1055
 
                               unsigned end_opcode)
1056
 
{
1057
 
   struct tgsi_full_instruction *inst;
1058
 
   unsigned writemask = 0;
1059
 
 
1060
 
   tgsi_parse_token(parse);
1061
 
   assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
1062
 
   inst = &parse->FullToken.FullInstruction;
1063
 
   check_no_subroutines(inst);
1064
 
 
1065
 
   while (inst->Instruction.Opcode != end_opcode) {
1066
 
 
1067
 
      /* Recursively process nested blocks. */
1068
 
      switch (inst->Instruction.Opcode) {
1069
 
      case TGSI_OPCODE_IF:
1070
 
      case TGSI_OPCODE_UIF:
1071
 
         writemask |=
1072
 
            get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDIF);
1073
 
         break;
1074
 
 
1075
 
      case TGSI_OPCODE_BGNLOOP:
1076
 
         writemask |=
1077
 
            get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP);
1078
 
         break;
1079
 
 
1080
 
      case TGSI_OPCODE_BARRIER:
1081
 
         unreachable("nested BARRIER is illegal");
1082
 
         break;
1083
 
 
1084
 
      default:
1085
 
         writemask |= get_inst_tessfactor_writemask(info, inst);
1086
 
      }
1087
 
 
1088
 
      tgsi_parse_token(parse);
1089
 
      assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
1090
 
      inst = &parse->FullToken.FullInstruction;
1091
 
      check_no_subroutines(inst);
1092
 
   }
1093
 
 
1094
 
   return writemask;
1095
 
}
1096
 
 
1097
 
static void
1098
 
get_if_block_tessfactor_writemask(const struct tgsi_shader_info *info,
1099
 
                                  struct tgsi_parse_context *parse,
1100
 
                                  unsigned *upper_block_tf_writemask,
1101
 
                                  unsigned *cond_block_tf_writemask)
1102
 
{
1103
 
   struct tgsi_full_instruction *inst;
1104
 
   unsigned then_tessfactor_writemask = 0;
1105
 
   unsigned else_tessfactor_writemask = 0;
1106
 
   unsigned writemask;
1107
 
   bool is_then = true;
1108
 
 
1109
 
   tgsi_parse_token(parse);
1110
 
   assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
1111
 
   inst = &parse->FullToken.FullInstruction;
1112
 
   check_no_subroutines(inst);
1113
 
 
1114
 
   while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF) {
1115
 
 
1116
 
      switch (inst->Instruction.Opcode) {
1117
 
      case TGSI_OPCODE_ELSE:
1118
 
         is_then = false;
1119
 
         break;
1120
 
 
1121
 
      /* Recursively process nested blocks. */
1122
 
      case TGSI_OPCODE_IF:
1123
 
      case TGSI_OPCODE_UIF:
1124
 
         get_if_block_tessfactor_writemask(info, parse,
1125
 
                                           is_then ? &then_tessfactor_writemask :
1126
 
                                                     &else_tessfactor_writemask,
1127
 
                                           cond_block_tf_writemask);
1128
 
         break;
1129
 
 
1130
 
      case TGSI_OPCODE_BGNLOOP:
1131
 
         *cond_block_tf_writemask |=
1132
 
            get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP);
1133
 
         break;
1134
 
 
1135
 
      case TGSI_OPCODE_BARRIER:
1136
 
         unreachable("nested BARRIER is illegal");
1137
 
         break;
1138
 
      default:
1139
 
         /* Process an instruction in the current block. */
1140
 
         writemask = get_inst_tessfactor_writemask(info, inst);
1141
 
 
1142
 
         if (writemask) {
1143
 
            if (is_then)
1144
 
               then_tessfactor_writemask |= writemask;
1145
 
            else
1146
 
               else_tessfactor_writemask |= writemask;
1147
 
         }
1148
 
      }
1149
 
 
1150
 
      tgsi_parse_token(parse);
1151
 
      assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
1152
 
      inst = &parse->FullToken.FullInstruction;
1153
 
      check_no_subroutines(inst);
1154
 
   }
1155
 
 
1156
 
   if (then_tessfactor_writemask || else_tessfactor_writemask) {
1157
 
      /* If both statements write the same tess factor channels,
1158
 
       * we can say that the upper block writes them too. */
1159
 
      *upper_block_tf_writemask |= then_tessfactor_writemask &
1160
 
                                   else_tessfactor_writemask;
1161
 
      *cond_block_tf_writemask |= then_tessfactor_writemask |
1162
 
                                  else_tessfactor_writemask;
1163
 
   }
1164
 
}
1165
 
 
1166
 
void
1167
 
tgsi_scan_tess_ctrl(const struct tgsi_token *tokens,
1168
 
                    const struct tgsi_shader_info *info,
1169
 
                    struct tgsi_tessctrl_info *out)
1170
 
{
1171
 
   memset(out, 0, sizeof(*out));
1172
 
 
1173
 
   if (info->processor != PIPE_SHADER_TESS_CTRL)
1174
 
      return;
1175
 
 
1176
 
   struct tgsi_parse_context parse;
1177
 
   if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
1178
 
      debug_printf("tgsi_parse_init() failed in tgsi_scan_arrays()!\n");
1179
 
      return;
1180
 
   }
1181
 
 
1182
 
   /* The pass works as follows:
1183
 
    * If all codepaths write tess factors, we can say that all invocations
1184
 
    * define tess factors.
1185
 
    *
1186
 
    * Each tess factor channel is tracked separately.
1187
 
    */
1188
 
   unsigned main_block_tf_writemask = 0; /* if main block writes tess factors */
1189
 
   unsigned cond_block_tf_writemask = 0; /* if cond block writes tess factors */
1190
 
 
1191
 
   /* Initial value = true. Here the pass will accumulate results from multiple
1192
 
    * segments surrounded by barriers. If tess factors aren't written at all,
1193
 
    * it's a shader bug and we don't care if this will be true.
1194
 
    */
1195
 
   out->tessfactors_are_def_in_all_invocs = true;
1196
 
 
1197
 
   while (!tgsi_parse_end_of_tokens(&parse)) {
1198
 
      tgsi_parse_token(&parse);
1199
 
 
1200
 
      if (parse.FullToken.Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION)
1201
 
         continue;
1202
 
 
1203
 
      struct tgsi_full_instruction *inst = &parse.FullToken.FullInstruction;
1204
 
      check_no_subroutines(inst);
1205
 
 
1206
 
      /* Process nested blocks. */
1207
 
      switch (inst->Instruction.Opcode) {
1208
 
      case TGSI_OPCODE_IF:
1209
 
      case TGSI_OPCODE_UIF:
1210
 
         get_if_block_tessfactor_writemask(info, &parse,
1211
 
                                           &main_block_tf_writemask,
1212
 
                                           &cond_block_tf_writemask);
1213
 
         continue;
1214
 
 
1215
 
      case TGSI_OPCODE_BGNLOOP:
1216
 
         cond_block_tf_writemask |=
1217
 
            get_block_tessfactor_writemask(info, &parse, TGSI_OPCODE_ENDLOOP);
1218
 
         continue;
1219
 
 
1220
 
      case TGSI_OPCODE_BARRIER:
1221
 
         /* The following case must be prevented:
1222
 
          *    gl_TessLevelInner = ...;
1223
 
          *    barrier();
1224
 
          *    if (gl_InvocationID == 1)
1225
 
          *       gl_TessLevelInner = ...;
1226
 
          *
1227
 
          * If you consider disjoint code segments separated by barriers, each
1228
 
          * such segment that writes tess factor channels should write the same
1229
 
          * channels in all codepaths within that segment.
1230
 
          */
1231
 
         if (main_block_tf_writemask || cond_block_tf_writemask) {
1232
 
            /* Accumulate the result: */
1233
 
            out->tessfactors_are_def_in_all_invocs &=
1234
 
               !(cond_block_tf_writemask & ~main_block_tf_writemask);
1235
 
 
1236
 
            /* Analyze the next code segment from scratch. */
1237
 
            main_block_tf_writemask = 0;
1238
 
            cond_block_tf_writemask = 0;
1239
 
         }
1240
 
         continue;
1241
 
      }
1242
 
 
1243
 
      main_block_tf_writemask |= get_inst_tessfactor_writemask(info, inst);
1244
 
   }
1245
 
 
1246
 
   /* Accumulate the result for the last code segment separated by a barrier. */
1247
 
   if (main_block_tf_writemask || cond_block_tf_writemask) {
1248
 
      out->tessfactors_are_def_in_all_invocs &=
1249
 
         !(cond_block_tf_writemask & ~main_block_tf_writemask);
1250
 
   }
1251
 
 
1252
 
   tgsi_parse_free(&parse);
1253
 
}