Fix deep call hierarchies in CombinedImageSamplerUsageHandler.

This commit is contained in:
Hans-Kristian Arntzen 2017-05-06 13:53:06 +02:00
parent 3eb8a34173
commit 07ee7d09cb
3 changed files with 22 additions and 38 deletions

View File

@ -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;
}

View File

@ -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);
};
};
}

View File

@ -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;
}