convert_to_sampled_image_pass.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Copyright (c) 2021 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 SOURCE_OPT_CONVERT_TO_SAMPLED_IMAGE_PASS_H_
  15. #define SOURCE_OPT_CONVERT_TO_SAMPLED_IMAGE_PASS_H_
  16. #include <memory>
  17. #include <unordered_set>
  18. #include <utility>
  19. #include "source/opt/pass.h"
  20. #include "source/opt/types.h"
  21. namespace spvtools {
  22. namespace opt {
  23. // A struct for a pair of descriptor set and binding.
  24. struct DescriptorSetAndBinding {
  25. uint32_t descriptor_set;
  26. uint32_t binding;
  27. bool operator==(const DescriptorSetAndBinding& descriptor_set_binding) const {
  28. return descriptor_set_binding.descriptor_set == descriptor_set &&
  29. descriptor_set_binding.binding == binding;
  30. }
  31. };
  32. // See optimizer.hpp for documentation.
  33. class ConvertToSampledImagePass : public Pass {
  34. public:
  35. // Hashing functor for the pair of descriptor set and binding.
  36. struct DescriptorSetAndBindingHash {
  37. size_t operator()(
  38. const DescriptorSetAndBinding& descriptor_set_binding) const {
  39. return std::hash<uint32_t>()(descriptor_set_binding.descriptor_set) ^
  40. std::hash<uint32_t>()(descriptor_set_binding.binding);
  41. }
  42. };
  43. using SetOfDescriptorSetAndBindingPairs =
  44. std::unordered_set<DescriptorSetAndBinding, DescriptorSetAndBindingHash>;
  45. using DescriptorSetBindingToInstruction =
  46. std::unordered_map<DescriptorSetAndBinding, Instruction*,
  47. DescriptorSetAndBindingHash>;
  48. explicit ConvertToSampledImagePass(
  49. const std::vector<DescriptorSetAndBinding>& descriptor_set_binding_pairs)
  50. : descriptor_set_binding_pairs_(descriptor_set_binding_pairs.begin(),
  51. descriptor_set_binding_pairs.end()) {}
  52. const char* name() const override { return "convert-to-sampled-image"; }
  53. Status Process() override;
  54. // Parses the given null-terminated C string to get a vector of descriptor set
  55. // and binding pairs. Returns a unique pointer to the vector of descriptor set
  56. // and binding pairs built from the given |str| on success. Returns a nullptr
  57. // if the given string is not valid for building the vector of pairs.
  58. // A valid string for building the vector of pairs should follow the rule
  59. // below:
  60. //
  61. // "<descriptor set>:<binding> <descriptor set>:<binding> ..."
  62. // Example:
  63. // "3:5 2:1 0:4"
  64. //
  65. // Entries are separated with blank spaces (i.e.:' ', '\n', '\r', '\t',
  66. // '\f', '\v'). Each entry corresponds to a descriptor set and binding pair.
  67. // Multiple spaces between, before or after entries are allowed. However,
  68. // spaces are not allowed within a descriptor set or binding.
  69. //
  70. // In each entry, the descriptor set and binding are separated by ':'.
  71. // Missing ':' in any entry is invalid. And it is invalid to have blank
  72. // spaces in between the descriptor set and ':' or ':' and the binding.
  73. //
  74. // <descriptor set>: the descriptor set.
  75. // The text must represent a valid uint32_t number.
  76. //
  77. // <binding>: the binding.
  78. // The text must represent a valid uint32_t number.
  79. static std::unique_ptr<std::vector<DescriptorSetAndBinding>>
  80. ParseDescriptorSetBindingPairsString(const char* str);
  81. private:
  82. // Collects resources to convert to sampled image and saves them in
  83. // |descriptor_set_binding_pair_to_sampler| if the resource is a sampler and
  84. // saves them in |descriptor_set_binding_pair_to_image| if the resource is an
  85. // image. Returns false if two samplers or two images have the same descriptor
  86. // set and binding. Otherwise, returns true.
  87. bool CollectResourcesToConvert(
  88. DescriptorSetBindingToInstruction* descriptor_set_binding_pair_to_sampler,
  89. DescriptorSetBindingToInstruction* descriptor_set_binding_pair_to_image)
  90. const;
  91. // Finds an OpDecorate with DescriptorSet decorating |inst| and another
  92. // OpDecorate with Binding decorating |inst|. Stores the descriptor set and
  93. // binding in |descriptor_set_binding|. Returns whether it successfully finds
  94. // the descriptor set and binding or not.
  95. bool GetDescriptorSetBinding(
  96. const Instruction& inst,
  97. DescriptorSetAndBinding* descriptor_set_binding) const;
  98. // Returns whether |descriptor_set_binding| is a pair of a descriptor set
  99. // and a binding that we have to convert resources with it to a sampled image
  100. // or not.
  101. bool ShouldResourceBeConverted(
  102. const DescriptorSetAndBinding& descriptor_set_binding) const;
  103. // Returns the pointee type of the type of variable |variable|. If |variable|
  104. // is not an OpVariable instruction, just returns nullptr.
  105. const analysis::Type* GetVariableType(const Instruction& variable) const;
  106. // Returns the storage class of |variable|.
  107. spv::StorageClass GetStorageClass(const Instruction& variable) const;
  108. // Finds |inst|'s users whose opcode is |user_opcode| or users of OpCopyObject
  109. // instructions of |inst| whose opcode is |user_opcode| and puts them in
  110. // |uses|.
  111. void FindUses(const Instruction* inst, std::vector<Instruction*>* uses,
  112. spv::Op user_opcode) const;
  113. // Finds OpImage* instructions using |image| or OpCopyObject instructions that
  114. // copy |image| and puts them in |uses|.
  115. void FindUsesOfImage(const Instruction* image,
  116. std::vector<Instruction*>* uses) const;
  117. // Creates an OpImage instruction that extracts the image from the sampled
  118. // image |sampled_image|.
  119. Instruction* CreateImageExtraction(Instruction* sampled_image);
  120. // Converts |image_variable| whose type is an image pointer to sampled image
  121. // type. Updates users of |image_variable| accordingly. If some instructions
  122. // e.g., OpImageRead use |image_variable| as an Image operand, creates an
  123. // image extracted from the sampled image using OpImage and replace the Image
  124. // operands of the users with the extracted image. If some OpSampledImage
  125. // instructions use |image_variable| and sampler whose descriptor set and
  126. // binding are the same with |image_variable|, just combines |image_variable|
  127. // and the sampler to a sampled image.
  128. Pass::Status UpdateImageVariableToSampledImage(
  129. Instruction* image_variable,
  130. const DescriptorSetAndBinding& descriptor_set_binding);
  131. // Returns the id of type sampled image type whose image type is the one of
  132. // |image_variable|.
  133. uint32_t GetSampledImageTypeForImage(Instruction* image_variable);
  134. // Moves |inst| next to the OpType* instruction with |type_id|.
  135. void MoveInstructionNextToType(Instruction* inst, uint32_t type_id);
  136. // Converts |image_variable| whose type is an image pointer to sampled image
  137. // with the type id |sampled_image_type_id|. Returns whether it successfully
  138. // converts the type of |image_variable| or not.
  139. bool ConvertImageVariableToSampledImage(Instruction* image_variable,
  140. uint32_t sampled_image_type_id);
  141. // Replaces |sampled_image_load| instruction used by OpImage* with the image
  142. // extracted from |sampled_image_load|. Returns the extracted image or nullptr
  143. // if it does not have uses.
  144. Instruction* UpdateImageUses(Instruction* sampled_image_load);
  145. // Returns true if the sampler of |sampled_image_inst| is decorated by a
  146. // descriptor set and a binding |descriptor_set_binding|.
  147. bool IsSamplerOfSampledImageDecoratedByDescriptorSetBinding(
  148. Instruction* sampled_image_inst,
  149. const DescriptorSetAndBinding& descriptor_set_binding);
  150. // Replaces OpSampledImage instructions using |image_load| with |image_load|
  151. // if the sampler of the OpSampledImage instruction has descriptor set and
  152. // binding |image_descriptor_set_binding|. Otherwise, replaces |image_load|
  153. // with |image_extraction|.
  154. void UpdateSampledImageUses(
  155. Instruction* image_load, Instruction* image_extraction,
  156. const DescriptorSetAndBinding& image_descriptor_set_binding);
  157. // Checks the uses of |sampler_variable|. When a sampler is used by
  158. // OpSampledImage instruction, the corresponding image must be
  159. // |image_to_be_combined_with| that should be already converted to a sampled
  160. // image by UpdateImageVariableToSampledImage() method.
  161. Pass::Status CheckUsesOfSamplerVariable(
  162. const Instruction* sampler_variable,
  163. Instruction* image_to_be_combined_with);
  164. // Returns true if Image operand of |sampled_image_inst| is the image of
  165. // |image_variable|.
  166. bool DoesSampledImageReferenceImage(Instruction* sampled_image_inst,
  167. Instruction* image_variable);
  168. // A set of pairs of descriptor set and binding. If an image and/or a sampler
  169. // have a pair of descriptor set and binding that is an element of
  170. // |descriptor_set_binding_pairs_|, they/it will be converted to a sampled
  171. // image by this pass.
  172. const SetOfDescriptorSetAndBindingPairs descriptor_set_binding_pairs_;
  173. };
  174. } // namespace opt
  175. } // namespace spvtools
  176. #endif // SOURCE_OPT_CONVERT_TO_SAMPLED_IMAGE_PASS_H_