mirror of
https://github.com/KhronosGroup/SPIRV-Cross.git
synced 2024-11-12 23:20:09 +00:00
Fix deep call hierarchies in CombinedImageSamplerUsageHandler.
This commit is contained in:
parent
3eb8a34173
commit
07ee7d09cb
@ -3361,26 +3361,6 @@ void Compiler::analyze_sampler_comparison_states()
|
||||
comparison_samplers = move(handler.comparison_samplers);
|
||||
}
|
||||
|
||||
uint32_t Compiler::CombinedImageSamplerUsageHandler::map_to_global_variable(uint32_t id, bool map_parameter) const
|
||||
{
|
||||
const auto remap = [](const unordered_map<uint32_t, uint32_t> &map, uint32_t variable_id) -> uint32_t {
|
||||
auto itr = map.find(variable_id);
|
||||
if (itr != end(map))
|
||||
return itr->second;
|
||||
else
|
||||
return variable_id;
|
||||
};
|
||||
|
||||
// Attempt to remap an ID to a variable if it was loaded by OpLoad.
|
||||
id = remap(to_variable_map, id);
|
||||
if (map_parameter)
|
||||
{
|
||||
// Attempt to remap a variable ID to a global ID if the variable ID is a function parameter.
|
||||
id = remap(param_to_global, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint32_t *args, uint32_t length)
|
||||
{
|
||||
if (length < 3)
|
||||
@ -3390,32 +3370,37 @@ bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint
|
||||
const auto *arg = &args[3];
|
||||
length -= 3;
|
||||
|
||||
// Do not need a stack for param_to_global since we cannot recurse, and parameter IDs for different functions
|
||||
// must be different.
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
auto &argument = func.arguments[i];
|
||||
param_to_global[argument.id] = map_to_global_variable(arg[i], true);
|
||||
dependency_hierarchy[argument.id].insert(arg[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_samplers(uint32_t sampler)
|
||||
{
|
||||
// Traverse the variable dependency hierarchy and tag everything in its path with comparison samplers.
|
||||
comparison_samplers.insert(sampler);
|
||||
for (auto &samp : dependency_hierarchy[sampler])
|
||||
add_hierarchy_to_comparison_samplers(samp);
|
||||
}
|
||||
|
||||
bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case OpAccessChain:
|
||||
case OpInBoundsAccessChain:
|
||||
case OpLoad:
|
||||
{
|
||||
if (length < 3)
|
||||
return false;
|
||||
// Needed so we are able to map the loaded OpSampler to its original variable.
|
||||
to_variable_map[args[1]] = args[2];
|
||||
dependency_hierarchy[args[1]].insert(args[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Deal with arrays of images and samplers?
|
||||
|
||||
case OpSampledImage:
|
||||
{
|
||||
if (length < 4)
|
||||
@ -3427,12 +3412,7 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
|
||||
{
|
||||
// This sampler must be a SamplerComparisionState, and not a regular SamplerState.
|
||||
uint32_t sampler = args[3];
|
||||
|
||||
// Make sure we tag both parameters and global variables here.
|
||||
uint32_t sampler_variable = map_to_global_variable(sampler, false);
|
||||
comparison_samplers.insert(sampler_variable);
|
||||
sampler_variable = map_to_global_variable(sampler, true);
|
||||
comparison_samplers.insert(sampler_variable);
|
||||
add_hierarchy_to_comparison_samplers(sampler);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -621,6 +621,10 @@ protected:
|
||||
SPIRFunction &entry, const CFG &cfg,
|
||||
const std::unordered_map<uint32_t, std::unordered_set<uint32_t>> &variable_to_blocks);
|
||||
|
||||
// If a variable ID or parameter ID is found in this set, a sampler is actually a shadow/comparison sampler.
|
||||
// SPIR-V does not support this distinction, so we must keep track of this information outside the type system.
|
||||
// There might be unrelated IDs found in this set which do not correspond to actual variables.
|
||||
// This set should only be queried for the existence of samplers which are already known to be variables or parameter IDs.
|
||||
std::unordered_set<uint32_t> comparison_samplers;
|
||||
void analyze_sampler_comparison_states();
|
||||
struct CombinedImageSamplerUsageHandler : OpcodeHandler
|
||||
@ -634,10 +638,10 @@ protected:
|
||||
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
|
||||
Compiler &compiler;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> to_variable_map;
|
||||
std::unordered_map<uint32_t, uint32_t> param_to_global;
|
||||
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> dependency_hierarchy;
|
||||
std::unordered_set<uint32_t> comparison_samplers;
|
||||
uint32_t map_to_global_variable(uint32_t id, bool map_parameter) const;
|
||||
|
||||
void add_hierarchy_to_comparison_samplers(uint32_t sampler);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -5830,7 +5830,7 @@ string CompilerGLSL::argument_decl(const SPIRFunction::Parameter &arg)
|
||||
if (type.basetype == SPIRType::Sampler)
|
||||
{
|
||||
tmp_type = &fake_type;
|
||||
fake_type.basetype = SPIRType::Sampler;
|
||||
fake_type = type;
|
||||
fake_type.image.depth = comparison_samplers.count(arg.id) != 0;
|
||||
}
|
||||
|
||||
@ -5849,7 +5849,7 @@ string CompilerGLSL::variable_decl(const SPIRVariable &variable)
|
||||
if (type.basetype == SPIRType::Sampler)
|
||||
{
|
||||
tmp_type = &fake_type;
|
||||
fake_type.basetype = SPIRType::Sampler;
|
||||
fake_type = type;
|
||||
fake_type.image.depth = comparison_samplers.count(variable.self) != 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user