| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // Copyright (c) 2025 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_SPLIT_COMBINED_IMAGE_SAMPLER_PASS_H_
- #define LIBSPIRV_OPT_SPLIT_COMBINED_IMAGE_SAMPLER_PASS_H_
- #include <unordered_map>
- #include <utility>
- #include <vector>
- #include "source/diagnostic.h"
- #include "source/opt/decoration_manager.h"
- #include "source/opt/def_use_manager.h"
- #include "source/opt/pass.h"
- #include "source/opt/type_manager.h"
- namespace spvtools {
- namespace opt {
- // Replaces each combined-image sampler variable with an image variable
- // and a sampler variable. Similar for function parameters.
- //
- // Copy the descriptor set and binding number. Vulkan allows this, surprisingly.
- class SplitCombinedImageSamplerPass : public Pass {
- public:
- virtual ~SplitCombinedImageSamplerPass() override = default;
- const char* name() const override { return "split-combined-image-sampler"; }
- IRContext::Analysis GetPreservedAnalyses() override;
- Status Process() override;
- private:
- // Records failure for the current module, and returns a stream
- // that can be used to provide user error information to the message
- // consumer.
- spvtools::DiagnosticStream Fail();
- // Find variables that contain combined texture-samplers, or arrays of them.
- // Also populate known_globals_.
- void FindCombinedTextureSamplers();
- // Returns the sampler type. If it does not yet exist, then it is created
- // and placed before the first sampled image type.
- Instruction* GetSamplerType();
- // Remaps function types and function declarations. Each
- // pointer-to-sampled-image-type operand is replaced with a pair of
- // pointer-to-image-type and pointer-to-sampler-type pair.
- // Updates the def-use manager and type manager.
- spv_result_t RemapFunctions();
- // Remap resource variables.
- // Updates the def-use manager.
- spv_result_t RemapVars();
- // Remap a single resource variable for combined var.
- // Updates the def-use manager and the decorations manager.
- spv_result_t RemapVar(Instruction* combined_var);
- // Transitively remaps uses of the combined object with uses of the
- // decomposed image and sampler parts. The combined object can be sampled
- // image value, a pointer to one, an array of one, or a pointer to an array
- // of one. The image and sampler parts have corresponding shapes.
- // Updates the def-use manager and the decorations manager.
- spv_result_t RemapUses(Instruction* combined, Instruction* image_part,
- Instruction* sampler_part);
- // Removes types that are no longer referenced.
- spv_result_t RemoveDeadTypes();
- // Returns the type instruction for a UniformConstant pointer to the given
- // pointee type. If it does not yet exist, the new type instruction is created
- // and placed immediately after the pointee type instruction. Updates def-use
- // and type managers, and the set of known globals.
- Instruction* MakeUniformConstantPointer(Instruction* pointee);
- // Returns the ID of the pointee type for a pointer value instruction.
- uint32_t PointeeTypeId(Instruction* ptr_value) {
- auto* ptr_ty = def_use_mgr_->GetDef(ptr_value->type_id());
- assert(ptr_ty->opcode() == spv::Op::OpTypePointer);
- return ptr_ty->GetSingleWordInOperand(1);
- }
- // Creates a new OpName instruction mapping the given name to the given
- // string, and adds it to the module at the end of the OpName and OpMemberName
- // section.
- void AddOpName(uint32_t id, const std::string& name);
- // Cached from the IRContext. Valid while Process() is running.
- analysis::DefUseManager* def_use_mgr_ = nullptr;
- // Cached from the IRContext. Valid while Process() is running.
- analysis::TypeManager* type_mgr_ = nullptr;
- // Did processing modify the module?
- bool modified_ = false;
- Pass::Status Ok() {
- return modified_ ? Pass::Status::SuccessWithChange
- : Pass::Status::SuccessWithoutChange;
- }
- // The first OpTypeSampledImage instruction in the module, if one exists.
- Instruction* first_sampled_image_type_ = nullptr;
- // An OpTypeSampler instruction, if one existed already, or if we created one.
- Instruction* sampler_type_ = nullptr;
- // The known types and module-scope values.
- // We use this to know when a new such value was created.
- std::unordered_set<uint32_t> known_globals_;
- bool IsKnownGlobal(uint32_t id) const {
- return known_globals_.find(id) != known_globals_.end();
- }
- void RegisterGlobal(uint32_t id) { known_globals_.insert(id); }
- void RegisterNewGlobal(uint32_t id) {
- modified_ = true;
- RegisterGlobal(id);
- }
- // Deletes an instruction and associated debug and decoration instructions.
- // Updates the def-use manager.
- void KillInst(Instruction* inst);
- // Combined types. The known combined sampled-image type,
- // and recursively pointers or arrays of them.
- std::unordered_set<uint32_t> combined_types_;
- // The pre-existing types this pass should remove: pointer to
- // combined type, array of combined type, pointer to array of combined type.
- std::vector<uint32_t> combined_types_to_remove_;
- // Is an OpTypeSampledImage used as a function parameter? Those should be
- // transformed.
- bool sampled_image_used_as_param_ = false;
- // Remaps a combined-kind type to corresponding sampler-kind and image-kind
- // of type.
- struct TypeRemapInfo {
- // The instruction for the combined type, pointer to combined type,
- // or point to array of combined type.
- Instruction* combined_kind_type;
- // The corresponding image type, with the same shape of indirection as the
- // combined_kind_type.
- Instruction* image_kind_type;
- // The corresponding sampler type, with the same shape of indirection as the
- // combined_kind_type.
- Instruction* sampler_kind_type;
- };
- // Maps the ID of a combined-image-sampler type kind to its corresponding
- // split parts.
- std::unordered_map<uint32_t, TypeRemapInfo> type_remap_;
- // Returns the image-like and sampler-like types of the same indirection shape
- // as the given combined-like type. If combined_kind_type is not a combined
- // type or a pointer to one, or an array of one or a pointer to an array of
- // one, then returns a pair of null pointer. Either both components are
- // non-null, or both components are null. Updates the def-use manager and the
- // type manager if new instructions are created.
- std::pair<Instruction*, Instruction*> SplitType(
- Instruction& combined_kind_type);
- // The combined-image-sampler variables to be replaced.
- std::vector<Instruction*> ordered_vars_;
- };
- } // namespace opt
- } // namespace spvtools
- #endif // LIBSPIRV_OPT_SPLIT_COMBINED_IMAGE_SAMPLER_PASS_H_
|