upgrade_memory_model.h 5.9 KB

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