• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 Google LLC.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Validates correctness of barrier SPIR-V instructions.
16 
17 #include "source/val/validate.h"
18 
19 #include <string>
20 
21 #include "source/diagnostic.h"
22 #include "source/opcode.h"
23 #include "source/spirv_constant.h"
24 #include "source/spirv_target_env.h"
25 #include "source/util/bitutils.h"
26 #include "source/val/instruction.h"
27 #include "source/val/validate_memory_semantics.h"
28 #include "source/val/validate_scopes.h"
29 #include "source/val/validation_state.h"
30 
31 namespace spvtools {
32 namespace val {
33 
34 // Validates correctness of barrier instructions.
BarriersPass(ValidationState_t & _,const Instruction * inst)35 spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
36   const SpvOp opcode = inst->opcode();
37   const uint32_t result_type = inst->type_id();
38 
39   switch (opcode) {
40     case SpvOpControlBarrier: {
41       if (spvVersionForTargetEnv(_.context()->target_env) <
42           SPV_SPIRV_VERSION_WORD(1, 3)) {
43         _.function(inst->function()->id())
44             ->RegisterExecutionModelLimitation(
45                 [](SpvExecutionModel model, std::string* message) {
46                   if (model != SpvExecutionModelTessellationControl &&
47                       model != SpvExecutionModelGLCompute &&
48                       model != SpvExecutionModelKernel &&
49                       model != SpvExecutionModelTaskNV &&
50                       model != SpvExecutionModelMeshNV) {
51                     if (message) {
52                       *message =
53                           "OpControlBarrier requires one of the following "
54                           "Execution "
55                           "Models: TessellationControl, GLCompute or Kernel";
56                     }
57                     return false;
58                   }
59                   return true;
60                 });
61       }
62 
63       const uint32_t execution_scope = inst->word(1);
64       const uint32_t memory_scope = inst->word(2);
65 
66       if (auto error = ValidateExecutionScope(_, inst, execution_scope)) {
67         return error;
68       }
69 
70       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
71         return error;
72       }
73 
74       if (auto error = ValidateMemorySemantics(_, inst, 2)) {
75         return error;
76       }
77       break;
78     }
79 
80     case SpvOpMemoryBarrier: {
81       const uint32_t memory_scope = inst->word(1);
82 
83       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
84         return error;
85       }
86 
87       if (auto error = ValidateMemorySemantics(_, inst, 1)) {
88         return error;
89       }
90       break;
91     }
92 
93     case SpvOpNamedBarrierInitialize: {
94       if (_.GetIdOpcode(result_type) != SpvOpTypeNamedBarrier) {
95         return _.diag(SPV_ERROR_INVALID_DATA, inst)
96                << spvOpcodeString(opcode)
97                << ": expected Result Type to be OpTypeNamedBarrier";
98       }
99 
100       const uint32_t subgroup_count_type = _.GetOperandTypeId(inst, 2);
101       if (!_.IsIntScalarType(subgroup_count_type) ||
102           _.GetBitWidth(subgroup_count_type) != 32) {
103         return _.diag(SPV_ERROR_INVALID_DATA, inst)
104                << spvOpcodeString(opcode)
105                << ": expected Subgroup Count to be a 32-bit int";
106       }
107       break;
108     }
109 
110     case SpvOpMemoryNamedBarrier: {
111       const uint32_t named_barrier_type = _.GetOperandTypeId(inst, 0);
112       if (_.GetIdOpcode(named_barrier_type) != SpvOpTypeNamedBarrier) {
113         return _.diag(SPV_ERROR_INVALID_DATA, inst)
114                << spvOpcodeString(opcode)
115                << ": expected Named Barrier to be of type OpTypeNamedBarrier";
116       }
117 
118       const uint32_t memory_scope = inst->word(2);
119 
120       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
121         return error;
122       }
123 
124       if (auto error = ValidateMemorySemantics(_, inst, 2)) {
125         return error;
126       }
127       break;
128     }
129 
130     default:
131       break;
132   }
133 
134   return SPV_SUCCESS;
135 }
136 
137 }  // namespace val
138 }  // namespace spvtools
139