| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // Copyright (c) 2021 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 SOURCE_OPT_CONVERT_TO_SAMPLED_IMAGE_PASS_H_
- #define SOURCE_OPT_CONVERT_TO_SAMPLED_IMAGE_PASS_H_
- #include <memory>
- #include <unordered_set>
- #include <utility>
- #include "source/opt/pass.h"
- #include "source/opt/types.h"
- namespace spvtools {
- namespace opt {
- // A struct for a pair of descriptor set and binding.
- struct DescriptorSetAndBinding {
- uint32_t descriptor_set;
- uint32_t binding;
- bool operator==(const DescriptorSetAndBinding& descriptor_set_binding) const {
- return descriptor_set_binding.descriptor_set == descriptor_set &&
- descriptor_set_binding.binding == binding;
- }
- };
- // See optimizer.hpp for documentation.
- class ConvertToSampledImagePass : public Pass {
- public:
- // Hashing functor for the pair of descriptor set and binding.
- struct DescriptorSetAndBindingHash {
- size_t operator()(
- const DescriptorSetAndBinding& descriptor_set_binding) const {
- return std::hash<uint32_t>()(descriptor_set_binding.descriptor_set) ^
- std::hash<uint32_t>()(descriptor_set_binding.binding);
- }
- };
- using SetOfDescriptorSetAndBindingPairs =
- std::unordered_set<DescriptorSetAndBinding, DescriptorSetAndBindingHash>;
- using DescriptorSetBindingToInstruction =
- std::unordered_map<DescriptorSetAndBinding, Instruction*,
- DescriptorSetAndBindingHash>;
- explicit ConvertToSampledImagePass(
- const std::vector<DescriptorSetAndBinding>& descriptor_set_binding_pairs)
- : descriptor_set_binding_pairs_(descriptor_set_binding_pairs.begin(),
- descriptor_set_binding_pairs.end()) {}
- const char* name() const override { return "convert-to-sampled-image"; }
- Status Process() override;
- // Parses the given null-terminated C string to get a vector of descriptor set
- // and binding pairs. Returns a unique pointer to the vector of descriptor set
- // and binding pairs built from the given |str| on success. Returns a nullptr
- // if the given string is not valid for building the vector of pairs.
- // A valid string for building the vector of pairs should follow the rule
- // below:
- //
- // "<descriptor set>:<binding> <descriptor set>:<binding> ..."
- // Example:
- // "3:5 2:1 0:4"
- //
- // Entries are separated with blank spaces (i.e.:' ', '\n', '\r', '\t',
- // '\f', '\v'). Each entry corresponds to a descriptor set and binding pair.
- // Multiple spaces between, before or after entries are allowed. However,
- // spaces are not allowed within a descriptor set or binding.
- //
- // In each entry, the descriptor set and binding are separated by ':'.
- // Missing ':' in any entry is invalid. And it is invalid to have blank
- // spaces in between the descriptor set and ':' or ':' and the binding.
- //
- // <descriptor set>: the descriptor set.
- // The text must represent a valid uint32_t number.
- //
- // <binding>: the binding.
- // The text must represent a valid uint32_t number.
- static std::unique_ptr<std::vector<DescriptorSetAndBinding>>
- ParseDescriptorSetBindingPairsString(const char* str);
- private:
- // Collects resources to convert to sampled image and saves them in
- // |descriptor_set_binding_pair_to_sampler| if the resource is a sampler and
- // saves them in |descriptor_set_binding_pair_to_image| if the resource is an
- // image. Returns false if two samplers or two images have the same descriptor
- // set and binding. Otherwise, returns true.
- bool CollectResourcesToConvert(
- DescriptorSetBindingToInstruction* descriptor_set_binding_pair_to_sampler,
- DescriptorSetBindingToInstruction* descriptor_set_binding_pair_to_image)
- const;
- // Finds an OpDecorate with DescriptorSet decorating |inst| and another
- // OpDecorate with Binding decorating |inst|. Stores the descriptor set and
- // binding in |descriptor_set_binding|. Returns whether it successfully finds
- // the descriptor set and binding or not.
- bool GetDescriptorSetBinding(
- const Instruction& inst,
- DescriptorSetAndBinding* descriptor_set_binding) const;
- // Returns whether |descriptor_set_binding| is a pair of a descriptor set
- // and a binding that we have to convert resources with it to a sampled image
- // or not.
- bool ShouldResourceBeConverted(
- const DescriptorSetAndBinding& descriptor_set_binding) const;
- // Returns the pointee type of the type of variable |variable|. If |variable|
- // is not an OpVariable instruction, just returns nullptr.
- const analysis::Type* GetVariableType(const Instruction& variable) const;
- // Returns the storage class of |variable|.
- spv::StorageClass GetStorageClass(const Instruction& variable) const;
- // Finds |inst|'s users whose opcode is |user_opcode| or users of OpCopyObject
- // instructions of |inst| whose opcode is |user_opcode| and puts them in
- // |uses|.
- void FindUses(const Instruction* inst, std::vector<Instruction*>* uses,
- spv::Op user_opcode) const;
- // Finds OpImage* instructions using |image| or OpCopyObject instructions that
- // copy |image| and puts them in |uses|.
- void FindUsesOfImage(const Instruction* image,
- std::vector<Instruction*>* uses) const;
- // Creates an OpImage instruction that extracts the image from the sampled
- // image |sampled_image|.
- Instruction* CreateImageExtraction(Instruction* sampled_image);
- // Converts |image_variable| whose type is an image pointer to sampled image
- // type. Updates users of |image_variable| accordingly. If some instructions
- // e.g., OpImageRead use |image_variable| as an Image operand, creates an
- // image extracted from the sampled image using OpImage and replace the Image
- // operands of the users with the extracted image. If some OpSampledImage
- // instructions use |image_variable| and sampler whose descriptor set and
- // binding are the same with |image_variable|, just combines |image_variable|
- // and the sampler to a sampled image.
- Pass::Status UpdateImageVariableToSampledImage(
- Instruction* image_variable,
- const DescriptorSetAndBinding& descriptor_set_binding);
- // Returns the id of type sampled image type whose image type is the one of
- // |image_variable|.
- uint32_t GetSampledImageTypeForImage(Instruction* image_variable);
- // Moves |inst| next to the OpType* instruction with |type_id|.
- void MoveInstructionNextToType(Instruction* inst, uint32_t type_id);
- // Converts |image_variable| whose type is an image pointer to sampled image
- // with the type id |sampled_image_type_id|. Returns whether it successfully
- // converts the type of |image_variable| or not.
- bool ConvertImageVariableToSampledImage(Instruction* image_variable,
- uint32_t sampled_image_type_id);
- // Replaces |sampled_image_load| instruction used by OpImage* with the image
- // extracted from |sampled_image_load|. Returns the extracted image or nullptr
- // if it does not have uses.
- Instruction* UpdateImageUses(Instruction* sampled_image_load);
- // Returns true if the sampler of |sampled_image_inst| is decorated by a
- // descriptor set and a binding |descriptor_set_binding|.
- bool IsSamplerOfSampledImageDecoratedByDescriptorSetBinding(
- Instruction* sampled_image_inst,
- const DescriptorSetAndBinding& descriptor_set_binding);
- // Replaces OpSampledImage instructions using |image_load| with |image_load|
- // if the sampler of the OpSampledImage instruction has descriptor set and
- // binding |image_descriptor_set_binding|. Otherwise, replaces |image_load|
- // with |image_extraction|.
- void UpdateSampledImageUses(
- Instruction* image_load, Instruction* image_extraction,
- const DescriptorSetAndBinding& image_descriptor_set_binding);
- // Checks the uses of |sampler_variable|. When a sampler is used by
- // OpSampledImage instruction, the corresponding image must be
- // |image_to_be_combined_with| that should be already converted to a sampled
- // image by UpdateImageVariableToSampledImage() method.
- Pass::Status CheckUsesOfSamplerVariable(
- const Instruction* sampler_variable,
- Instruction* image_to_be_combined_with);
- // Returns true if Image operand of |sampled_image_inst| is the image of
- // |image_variable|.
- bool DoesSampledImageReferenceImage(Instruction* sampled_image_inst,
- Instruction* image_variable);
- // A set of pairs of descriptor set and binding. If an image and/or a sampler
- // have a pair of descriptor set and binding that is an element of
- // |descriptor_set_binding_pairs_|, they/it will be converted to a sampled
- // image by this pass.
- const SetOfDescriptorSetAndBindingPairs descriptor_set_binding_pairs_;
- };
- } // namespace opt
- } // namespace spvtools
- #endif // SOURCE_OPT_CONVERT_TO_SAMPLED_IMAGE_PASS_H_
|