Fix severe performance issue with invariant expression invalidation.

We were going down a tree of expressions multiple times and this caused
an exponential explosion in time, which was not caught until recently.

Fix this by blocking any traversal going through an ID more than one
time.

This fix overall improves performance by almost an order of magnitude on a
particular test shader rather than slowing it down by ~75x.
This commit is contained in:
Hans-Kristian Arntzen 2019-08-01 09:51:44 +02:00
parent ffca8735ff
commit b97e9b0499
3 changed files with 11 additions and 6 deletions

View File

@ -1063,7 +1063,8 @@ static int main_inner(int argc, char *argv[])
cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
cbs.add("--glsl-emit-push-constant-as-ubo", [&args](CLIParser &) { args.glsl_emit_push_constant_as_ubo = true; }); cbs.add("--glsl-emit-push-constant-as-ubo", [&args](CLIParser &) { args.glsl_emit_push_constant_as_ubo = true; });
cbs.add("--glsl-emit-ubo-as-plain-uniforms", [&args](CLIParser &) { args.glsl_emit_ubo_as_plain_uniforms = true; }); cbs.add("--glsl-emit-ubo-as-plain-uniforms", [&args](CLIParser &) { args.glsl_emit_ubo_as_plain_uniforms = true; });
cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions", [&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; }); cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions",
[&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; });
cbs.add("--msl", [&args](CLIParser &) { args.msl = true; }); cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; }); cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; }); cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });

View File

@ -816,6 +816,7 @@ protected:
std::unordered_set<uint32_t> forwarded_temporaries; std::unordered_set<uint32_t> forwarded_temporaries;
std::unordered_set<uint32_t> suppressed_usage_tracking; std::unordered_set<uint32_t> suppressed_usage_tracking;
std::unordered_set<uint32_t> hoisted_temporaries; std::unordered_set<uint32_t> hoisted_temporaries;
std::unordered_set<uint32_t> forced_invariant_temporaries;
Bitset active_input_builtins; Bitset active_input_builtins;
Bitset active_output_builtins; Bitset active_output_builtins;

View File

@ -4981,7 +4981,8 @@ std::string CompilerGLSL::convert_separate_image_to_expression(uint32_t id)
// Don't need to consider Shadow state since the dummy sampler is always non-shadow. // Don't need to consider Shadow state since the dummy sampler is always non-shadow.
auto sampled_type = type; auto sampled_type = type;
sampled_type.basetype = SPIRType::SampledImage; sampled_type.basetype = SPIRType::SampledImage;
return join(type_to_glsl(sampled_type), "(", to_expression(id), ", ", to_expression(dummy_sampler_id), ")"); return join(type_to_glsl(sampled_type), "(", to_expression(id), ", ",
to_expression(dummy_sampler_id), ")");
} }
else else
{ {
@ -7550,14 +7551,16 @@ void CompilerGLSL::disallow_forwarding_in_expression_chain(const SPIRExpression
// Allow trivially forwarded expressions like OpLoad or trivial shuffles, // Allow trivially forwarded expressions like OpLoad or trivial shuffles,
// these will be marked as having suppressed usage tracking. // these will be marked as having suppressed usage tracking.
// Our only concern is to make sure arithmetic operations are done in similar ways. // Our only concern is to make sure arithmetic operations are done in similar ways.
if (expression_is_forwarded(expr.self) && !expression_suppresses_usage_tracking(expr.self)) if (expression_is_forwarded(expr.self) && !expression_suppresses_usage_tracking(expr.self) &&
forced_invariant_temporaries.count(expr.self) == 0)
{ {
forced_temporaries.insert(expr.self); forced_temporaries.insert(expr.self);
forced_invariant_temporaries.insert(expr.self);
force_recompile(); force_recompile();
}
for (auto &dependent : expr.expression_dependencies) for (auto &dependent : expr.expression_dependencies)
disallow_forwarding_in_expression_chain(get<SPIRExpression>(dependent)); disallow_forwarding_in_expression_chain(get<SPIRExpression>(dependent));
}
} }
void CompilerGLSL::handle_store_to_invariant_variable(uint32_t store_id, uint32_t value_id) void CompilerGLSL::handle_store_to_invariant_variable(uint32_t store_id, uint32_t value_id)