Coverage Report

Created: 2025-07-23 06:18

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