diff --git a/spirv_cross.cpp b/spirv_cross.cpp index 6a0d9306..be0f8831 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -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 &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; } diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 72407225..19bc662e 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -621,6 +621,10 @@ protected: SPIRFunction &entry, const CFG &cfg, const std::unordered_map> &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 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 to_variable_map; - std::unordered_map param_to_global; + std::unordered_map> dependency_hierarchy; std::unordered_set comparison_samplers; - uint32_t map_to_global_variable(uint32_t id, bool map_parameter) const; + + void add_hierarchy_to_comparison_samplers(uint32_t sampler); }; }; } diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index d1932232..69194c78 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -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; }