split_combined_image_sampler_pass.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright (c) 2025 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_SPLIT_COMBINED_IMAGE_SAMPLER_PASS_H_
  15. #define LIBSPIRV_OPT_SPLIT_COMBINED_IMAGE_SAMPLER_PASS_H_
  16. #include <unordered_map>
  17. #include <utility>
  18. #include <vector>
  19. #include "source/diagnostic.h"
  20. #include "source/opt/decoration_manager.h"
  21. #include "source/opt/def_use_manager.h"
  22. #include "source/opt/pass.h"
  23. #include "source/opt/type_manager.h"
  24. namespace spvtools {
  25. namespace opt {
  26. // Replaces each combined-image sampler variable with an image variable
  27. // and a sampler variable. Similar for function parameters.
  28. //
  29. // Copy the descriptor set and binding number. Vulkan allows this, surprisingly.
  30. class SplitCombinedImageSamplerPass : public Pass {
  31. public:
  32. virtual ~SplitCombinedImageSamplerPass() override = default;
  33. const char* name() const override { return "split-combined-image-sampler"; }
  34. IRContext::Analysis GetPreservedAnalyses() override;
  35. Status Process() override;
  36. private:
  37. // Records failure for the current module, and returns a stream
  38. // that can be used to provide user error information to the message
  39. // consumer.
  40. spvtools::DiagnosticStream Fail();
  41. // Find variables that contain combined texture-samplers, or arrays of them.
  42. // Also populate known_globals_.
  43. void FindCombinedTextureSamplers();
  44. // Returns the sampler type. If it does not yet exist, then it is created
  45. // and placed before the first sampled image type.
  46. Instruction* GetSamplerType();
  47. // Remaps function types and function declarations. Each
  48. // pointer-to-sampled-image-type operand is replaced with a pair of
  49. // pointer-to-image-type and pointer-to-sampler-type pair.
  50. // Updates the def-use manager and type manager.
  51. spv_result_t RemapFunctions();
  52. // Remap resource variables.
  53. // Updates the def-use manager.
  54. spv_result_t RemapVars();
  55. // Remap a single resource variable for combined var.
  56. // Updates the def-use manager and the decorations manager.
  57. spv_result_t RemapVar(Instruction* combined_var);
  58. // Transitively remaps uses of the combined object with uses of the
  59. // decomposed image and sampler parts. The combined object can be sampled
  60. // image value, a pointer to one, an array of one, or a pointer to an array
  61. // of one. The image and sampler parts have corresponding shapes.
  62. // Updates the def-use manager and the decorations manager.
  63. spv_result_t RemapUses(Instruction* combined, Instruction* image_part,
  64. Instruction* sampler_part);
  65. // Removes types that are no longer referenced.
  66. spv_result_t RemoveDeadTypes();
  67. // Returns the type instruction for a UniformConstant pointer to the given
  68. // pointee type. If it does not yet exist, the new type instruction is created
  69. // and placed immediately after the pointee type instruction. Updates def-use
  70. // and type managers, and the set of known globals.
  71. Instruction* MakeUniformConstantPointer(Instruction* pointee);
  72. // Returns the ID of the pointee type for a pointer value instruction.
  73. uint32_t PointeeTypeId(Instruction* ptr_value) {
  74. auto* ptr_ty = def_use_mgr_->GetDef(ptr_value->type_id());
  75. assert(ptr_ty->opcode() == spv::Op::OpTypePointer);
  76. return ptr_ty->GetSingleWordInOperand(1);
  77. }
  78. // Creates a new OpName instruction mapping the given name to the given
  79. // string, and adds it to the module at the end of the OpName and OpMemberName
  80. // section.
  81. void AddOpName(uint32_t id, const std::string& name);
  82. // Cached from the IRContext. Valid while Process() is running.
  83. analysis::DefUseManager* def_use_mgr_ = nullptr;
  84. // Cached from the IRContext. Valid while Process() is running.
  85. analysis::TypeManager* type_mgr_ = nullptr;
  86. // Did processing modify the module?
  87. bool modified_ = false;
  88. Pass::Status Ok() {
  89. return modified_ ? Pass::Status::SuccessWithChange
  90. : Pass::Status::SuccessWithoutChange;
  91. }
  92. // The first OpTypeSampledImage instruction in the module, if one exists.
  93. Instruction* first_sampled_image_type_ = nullptr;
  94. // An OpTypeSampler instruction, if one existed already, or if we created one.
  95. Instruction* sampler_type_ = nullptr;
  96. // The known types and module-scope values.
  97. // We use this to know when a new such value was created.
  98. std::unordered_set<uint32_t> known_globals_;
  99. bool IsKnownGlobal(uint32_t id) const {
  100. return known_globals_.find(id) != known_globals_.end();
  101. }
  102. void RegisterGlobal(uint32_t id) { known_globals_.insert(id); }
  103. void RegisterNewGlobal(uint32_t id) {
  104. modified_ = true;
  105. RegisterGlobal(id);
  106. }
  107. // Deletes an instruction and associated debug and decoration instructions.
  108. // Updates the def-use manager.
  109. void KillInst(Instruction* inst);
  110. // Combined types. The known combined sampled-image type,
  111. // and recursively pointers or arrays of them.
  112. std::unordered_set<uint32_t> combined_types_;
  113. // The pre-existing types this pass should remove: pointer to
  114. // combined type, array of combined type, pointer to array of combined type.
  115. std::vector<uint32_t> combined_types_to_remove_;
  116. // Is an OpTypeSampledImage used as a function parameter? Those should be
  117. // transformed.
  118. bool sampled_image_used_as_param_ = false;
  119. // Remaps a combined-kind type to corresponding sampler-kind and image-kind
  120. // of type.
  121. struct TypeRemapInfo {
  122. // The instruction for the combined type, pointer to combined type,
  123. // or point to array of combined type.
  124. Instruction* combined_kind_type;
  125. // The corresponding image type, with the same shape of indirection as the
  126. // combined_kind_type.
  127. Instruction* image_kind_type;
  128. // The corresponding sampler type, with the same shape of indirection as the
  129. // combined_kind_type.
  130. Instruction* sampler_kind_type;
  131. };
  132. // Maps the ID of a combined-image-sampler type kind to its corresponding
  133. // split parts.
  134. std::unordered_map<uint32_t, TypeRemapInfo> type_remap_;
  135. // Returns the image-like and sampler-like types of the same indirection shape
  136. // as the given combined-like type. If combined_kind_type is not a combined
  137. // type or a pointer to one, or an array of one or a pointer to an array of
  138. // one, then returns a pair of null pointer. Either both components are
  139. // non-null, or both components are null. Updates the def-use manager and the
  140. // type manager if new instructions are created.
  141. std::pair<Instruction*, Instruction*> SplitType(
  142. Instruction& combined_kind_type);
  143. // The combined-image-sampler variables to be replaced.
  144. std::vector<Instruction*> ordered_vars_;
  145. };
  146. } // namespace opt
  147. } // namespace spvtools
  148. #endif // LIBSPIRV_OPT_SPLIT_COMBINED_IMAGE_SAMPLER_PASS_H_