Coverage Report

Created: 2024-09-11 07:09

/src/spirv-tools/source/opt/upgrade_memory_model.h
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
#ifndef LIBSPIRV_OPT_UPGRADE_MEMORY_MODEL_H_
16
#define LIBSPIRV_OPT_UPGRADE_MEMORY_MODEL_H_
17
18
#include <functional>
19
#include <tuple>
20
21
#include "pass.h"
22
23
namespace spvtools {
24
namespace opt {
25
26
// Hashing functor for the memoized result store.
27
struct CacheHash {
28
  size_t operator()(
29
0
      const std::pair<uint32_t, std::vector<uint32_t>>& item) const {
30
0
    std::u32string to_hash;
31
0
    to_hash.push_back(item.first);
32
0
    for (auto i : item.second) to_hash.push_back(i);
33
0
    return std::hash<std::u32string>()(to_hash);
34
0
  }
35
};
36
37
// Upgrades the memory model from Logical GLSL450 to Logical VulkanKHR.
38
//
39
// This pass remove deprecated decorations (Volatile and Coherent) and replaces
40
// them with new flags on individual instructions. It adds the Output storage
41
// class semantic to control barriers in tessellation control shaders that have
42
// an access to Output memory.
43
class UpgradeMemoryModel : public Pass {
44
 public:
45
0
  const char* name() const override { return "upgrade-memory-model"; }
46
  Status Process() override;
47
48
 private:
49
  // Used to indicate whether the operation performs an availability or
50
  // visibility operation.
51
  enum OperationType { kVisibility, kAvailability };
52
53
  // Used to indicate whether the instruction is a memory or image instruction.
54
  enum InstructionType { kMemory, kImage };
55
56
  // Modifies the OpMemoryModel to use VulkanKHR. Adds the Vulkan memory model
57
  // capability and extension.
58
  void UpgradeMemoryModelInstruction();
59
60
  // Upgrades memory, image and atomic instructions.
61
  // Memory and image instructions convert coherent and volatile decorations
62
  // into flags on the instruction.
63
  // Atomic memory semantics convert volatile decoration into flags on the
64
  // instruction.
65
  void UpgradeInstructions();
66
67
  // Upgrades memory and image operands for instructions that have them.
68
  void UpgradeMemoryAndImages();
69
70
  // Adds the volatile memory semantic if necessary.
71
  void UpgradeAtomics();
72
73
  // Returns whether |id| is coherent and/or volatile.
74
  std::tuple<bool, bool, spv::Scope> GetInstructionAttributes(uint32_t id);
75
76
  // Traces |inst| to determine if it is coherent and/or volatile.
77
  // |indices| tracks the access chain indices seen so far.
78
  std::pair<bool, bool> TraceInstruction(Instruction* inst,
79
                                         std::vector<uint32_t> indices,
80
                                         std::unordered_set<uint32_t>* visited);
81
82
  // Return true if |inst| is decorated with |decoration|.
83
  // If |inst| is decorated by member decorations then either |value| must
84
  // match the index or |value| must be a maximum allowable value. The max
85
  // value allows any element to match.
86
  bool HasDecoration(const Instruction* inst, uint32_t value,
87
                     spv::Decoration decoration);
88
89
  // Returns whether |type_id| indexed via |indices| is coherent and/or
90
  // volatile.
91
  std::pair<bool, bool> CheckType(uint32_t type_id,
92
                                  const std::vector<uint32_t>& indices);
93
94
  // Returns whether any type/element under |inst| is coherent and/or volatile.
95
  std::pair<bool, bool> CheckAllTypes(const Instruction* inst);
96
97
  // Modifies the flags of |inst| to include the new flags for the Vulkan
98
  // memory model. |operation_type| indicates whether flags should use
99
  // MakeVisible or MakeAvailable variants. |inst_type| indicates whether the
100
  // Pointer or Texel variants of flags should be used.
101
  void UpgradeFlags(Instruction* inst, uint32_t in_operand, bool is_coherent,
102
                    bool is_volatile, OperationType operation_type,
103
                    InstructionType inst_type);
104
105
  // Modifies the semantics at |in_operand| of |inst| to include the volatile
106
  // bit if |is_volatile| is true.
107
  void UpgradeSemantics(Instruction* inst, uint32_t in_operand,
108
                        bool is_volatile);
109
110
  // Returns the result id for a constant for |scope|.
111
  uint32_t GetScopeConstant(spv::Scope scope);
112
113
  // Returns the value of |index_inst|. |index_inst| must be an OpConstant of
114
  // integer type.g
115
  uint64_t GetIndexValue(Instruction* index_inst);
116
117
  // Removes coherent and volatile decorations.
118
  void CleanupDecorations();
119
120
  // For all tessellation control entry points, if there is an operation on
121
  // Output storage class, then all barriers are modified to include the
122
  // OutputMemoryKHR semantic.
123
  void UpgradeBarriers();
124
125
  // If the Vulkan memory model is specified, device scope actually means
126
  // device scope. The memory scope must be modified to be QueueFamilyKHR
127
  // scope.
128
  void UpgradeMemoryScope();
129
130
  // Returns true if |scope_id| is spv::Scope::Device.
131
  bool IsDeviceScope(uint32_t scope_id);
132
133
  // Upgrades GLSL.std.450 modf and frexp. Both instructions are replaced with
134
  // their struct versions. New extracts and a store are added in order to
135
  // facilitate adding memory model flags.
136
  void UpgradeExtInst(Instruction* modf);
137
138
  // Returns the number of words taken up by a memory access argument and its
139
  // implied operands.
140
  uint32_t MemoryAccessNumWords(uint32_t mask);
141
142
  // Caches the result of TraceInstruction. For a given result id and set of
143
  // indices, stores whether that combination is coherent and/or volatile.
144
  std::unordered_map<std::pair<uint32_t, std::vector<uint32_t>>,
145
                     std::pair<bool, bool>, CacheHash>
146
      cache_;
147
};
148
}  // namespace opt
149
}  // namespace spvtools
150
#endif  // LIBSPIRV_OPT_UPGRADE_MEMORY_MODEL_H_