Welcome to mirror list, hosted at ThFree Co, Russian Federation.

upgrade_memory_model.h « opt « source - github.com/KhronosGroup/SPIRV-Tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 489436b6df584b57fbacbb822166fd9359651c74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright (c) 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef LIBSPIRV_OPT_UPGRADE_MEMORY_MODEL_H_
#define LIBSPIRV_OPT_UPGRADE_MEMORY_MODEL_H_

#include <functional>
#include <tuple>

#include "pass.h"

namespace spvtools {
namespace opt {

// Hashing functor for the memoized result store.
struct CacheHash {
  size_t operator()(
      const std::pair<uint32_t, std::vector<uint32_t>>& item) const {
    std::u32string to_hash;
    to_hash.push_back(item.first);
    for (auto i : item.second) to_hash.push_back(i);
    return std::hash<std::u32string>()(to_hash);
  }
};

// Upgrades the memory model from Logical GLSL450 to Logical VulkanKHR.
//
// This pass remove deprecated decorations (Volatile and Coherent) and replaces
// them with new flags on individual instructions. It adds the Output storage
// class semantic to control barriers in tessellation control shaders that have
// an access to Output memory.
class UpgradeMemoryModel : public Pass {
 public:
  const char* name() const override { return "upgrade-memory-model"; }
  Status Process() override;

 private:
  // Used to indicate whether the operation performs an availability or
  // visibility operation.
  enum OperationType { kVisibility, kAvailability };

  // Used to indicate whether the instruction is a memory or image instruction.
  enum InstructionType { kMemory, kImage };

  // Modifies the OpMemoryModel to use VulkanKHR. Adds the Vulkan memory model
  // capability and extension.
  void UpgradeMemoryModelInstruction();

  // Upgrades memory, image and atomic instructions.
  // Memory and image instructions convert coherent and volatile decorations
  // into flags on the instruction.
  // Atomic memory semantics convert volatile decoration into flags on the
  // instruction.
  void UpgradeInstructions();

  // Upgrades memory and image operands for instructions that have them.
  void UpgradeMemoryAndImages();

  // Adds the volatile memory semantic if necessary.
  void UpgradeAtomics();

  // Returns whether |id| is coherent and/or volatile.
  std::tuple<bool, bool, spv::Scope> GetInstructionAttributes(uint32_t id);

  // Traces |inst| to determine if it is coherent and/or volatile.
  // |indices| tracks the access chain indices seen so far.
  std::pair<bool, bool> TraceInstruction(Instruction* inst,
                                         std::vector<uint32_t> indices,
                                         std::unordered_set<uint32_t>* visited);

  // Return true if |inst| is decorated with |decoration|.
  // If |inst| is decorated by member decorations then either |value| must
  // match the index or |value| must be a maximum allowable value. The max
  // value allows any element to match.
  bool HasDecoration(const Instruction* inst, uint32_t value,
                     spv::Decoration decoration);

  // Returns whether |type_id| indexed via |indices| is coherent and/or
  // volatile.
  std::pair<bool, bool> CheckType(uint32_t type_id,
                                  const std::vector<uint32_t>& indices);

  // Returns whether any type/element under |inst| is coherent and/or volatile.
  std::pair<bool, bool> CheckAllTypes(const Instruction* inst);

  // Modifies the flags of |inst| to include the new flags for the Vulkan
  // memory model. |operation_type| indicates whether flags should use
  // MakeVisible or MakeAvailable variants. |inst_type| indicates whether the
  // Pointer or Texel variants of flags should be used.
  void UpgradeFlags(Instruction* inst, uint32_t in_operand, bool is_coherent,
                    bool is_volatile, OperationType operation_type,
                    InstructionType inst_type);

  // Modifies the semantics at |in_operand| of |inst| to include the volatile
  // bit if |is_volatile| is true.
  void UpgradeSemantics(Instruction* inst, uint32_t in_operand,
                        bool is_volatile);

  // Returns the result id for a constant for |scope|.
  uint32_t GetScopeConstant(spv::Scope scope);

  // Returns the value of |index_inst|. |index_inst| must be an OpConstant of
  // integer type.g
  uint64_t GetIndexValue(Instruction* index_inst);

  // Removes coherent and volatile decorations.
  void CleanupDecorations();

  // For all tessellation control entry points, if there is an operation on
  // Output storage class, then all barriers are modified to include the
  // OutputMemoryKHR semantic.
  void UpgradeBarriers();

  // If the Vulkan memory model is specified, device scope actually means
  // device scope. The memory scope must be modified to be QueueFamilyKHR
  // scope.
  void UpgradeMemoryScope();

  // Returns true if |scope_id| is spv::Scope::Device.
  bool IsDeviceScope(uint32_t scope_id);

  // Upgrades GLSL.std.450 modf and frexp. Both instructions are replaced with
  // their struct versions. New extracts and a store are added in order to
  // facilitate adding memory model flags.
  void UpgradeExtInst(Instruction* modf);

  // Returns the number of words taken up by a memory access argument and its
  // implied operands.
  uint32_t MemoryAccessNumWords(uint32_t mask);

  // Caches the result of TraceInstruction. For a given result id and set of
  // indices, stores whether that combination is coherent and/or volatile.
  std::unordered_map<std::pair<uint32_t, std::vector<uint32_t>>,
                     std::pair<bool, bool>, CacheHash>
      cache_;
};
}  // namespace opt
}  // namespace spvtools
#endif  // LIBSPIRV_OPT_UPGRADE_MEMORY_MODEL_H_