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 <string>
18
19 #include "source/diagnostic.h"
20 #include "source/opcode.h"
21 #include "source/spirv_constant.h"
22 #include "source/spirv_target_env.h"
23 #include "source/util/bitutils.h"
24 #include "source/val/instruction.h"
25 #include "source/val/validate.h"
26 #include "source/val/validate_memory_semantics.h"
27 #include "source/val/validate_scopes.h"
28 #include "source/val/validation_state.h"
29
30 namespace spvtools {
31 namespace val {
32
33 // Validates correctness of barrier instructions.
BarriersPass(ValidationState_t & _,const Instruction * inst)34 spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
35 const SpvOp opcode = inst->opcode();
36 const uint32_t result_type = inst->type_id();
37
38 switch (opcode) {
39 case SpvOpControlBarrier: {
40 if (_.version() < SPV_SPIRV_VERSION_WORD(1, 3)) {
41 _.function(inst->function()->id())
42 ->RegisterExecutionModelLimitation(
43 [](SpvExecutionModel model, std::string* message) {
44 if (model != SpvExecutionModelTessellationControl &&
45 model != SpvExecutionModelGLCompute &&
46 model != SpvExecutionModelKernel &&
47 model != SpvExecutionModelTaskNV &&
48 model != SpvExecutionModelMeshNV) {
49 if (message) {
50 *message =
51 "OpControlBarrier requires one of the following "
52 "Execution "
53 "Models: TessellationControl, GLCompute, Kernel, "
54 "MeshNV or TaskNV";
55 }
56 return false;
57 }
58 return true;
59 });
60 }
61
62 const uint32_t execution_scope = inst->word(1);
63 const uint32_t memory_scope = inst->word(2);
64
65 if (auto error = ValidateExecutionScope(_, inst, execution_scope)) {
66 return error;
67 }
68
69 if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
70 return error;
71 }
72
73 if (auto error = ValidateMemorySemantics(_, inst, 2, memory_scope)) {
74 return error;
75 }
76 break;
77 }
78
79 case SpvOpMemoryBarrier: {
80 const uint32_t memory_scope = inst->word(1);
81
82 if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
83 return error;
84 }
85
86 if (auto error = ValidateMemorySemantics(_, inst, 1, memory_scope)) {
87 return error;
88 }
89 break;
90 }
91
92 case SpvOpNamedBarrierInitialize: {
93 if (_.GetIdOpcode(result_type) != SpvOpTypeNamedBarrier) {
94 return _.diag(SPV_ERROR_INVALID_DATA, inst)
95 << spvOpcodeString(opcode)
96 << ": expected Result Type to be OpTypeNamedBarrier";
97 }
98
99 const uint32_t subgroup_count_type = _.GetOperandTypeId(inst, 2);
100 if (!_.IsIntScalarType(subgroup_count_type) ||
101 _.GetBitWidth(subgroup_count_type) != 32) {
102 return _.diag(SPV_ERROR_INVALID_DATA, inst)
103 << spvOpcodeString(opcode)
104 << ": expected Subgroup Count to be a 32-bit int";
105 }
106 break;
107 }
108
109 case SpvOpMemoryNamedBarrier: {
110 const uint32_t named_barrier_type = _.GetOperandTypeId(inst, 0);
111 if (_.GetIdOpcode(named_barrier_type) != SpvOpTypeNamedBarrier) {
112 return _.diag(SPV_ERROR_INVALID_DATA, inst)
113 << spvOpcodeString(opcode)
114 << ": expected Named Barrier to be of type OpTypeNamedBarrier";
115 }
116
117 const uint32_t memory_scope = inst->word(2);
118
119 if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
120 return error;
121 }
122
123 if (auto error = ValidateMemorySemantics(_, inst, 2, memory_scope)) {
124 return error;
125 }
126 break;
127 }
128
129 default:
130 break;
131 }
132
133 return SPV_SUCCESS;
134 }
135
136 } // namespace val
137 } // namespace spvtools
138