mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-09-06 18:38:26 +00:00
170 lines
7.0 KiB
C++
170 lines
7.0 KiB
C++
// 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_
|