From 2533576802f5dcbc80bace3fafee2c9e33d824cd Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Thu, 25 May 2023 20:37:42 +0200 Subject: [PATCH] EEVEE: Fix non-deterministic codegen preventing shader cache to work used_libraries was iterated on to generate shader code depending on pointers order, which was non-deterministic. It prevented shader caching by graphics drivers to survive across reboots, as reported in https://techgage.com/article/blender-3-5-performance-deep-dive-cycles-eevee-viewport/ Co-authored-by: Ray Molenkamp Pull Request: https://projects.blender.org/blender/blender/pulls/108289 --- source/blender/gpu/intern/gpu_codegen.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc index 77d06bb69d7..4ec3904a990 100644 --- a/source/blender/gpu/intern/gpu_codegen.cc +++ b/source/blender/gpu/intern/gpu_codegen.cc @@ -483,16 +483,26 @@ void GPUCodegen::generate_library() GPUCodegenCreateInfo &info = *create_info; void *value; - /* Iterate over libraries. We need to keep this struct intact in case - * it is required for the optimization pass. */ + blender::Vector source_files; + + /* Iterate over libraries. We need to keep this struct intact in case it is required for the + * optimization pass. The first pass just collects the keys from the GSET, given items in a GSET + * are unordered this can cause order differences between invocations, so we collect the keys + * first, and sort them before doing actual work, to guarantee stable behavior while still + * having cheap insertions into the GSET */ GHashIterator *ihash = BLI_ghashIterator_new((GHash *)graph.used_libraries); while (!BLI_ghashIterator_done(ihash)) { value = BLI_ghashIterator_getKey(ihash); - auto deps = gpu_shader_dependency_get_resolved_source((const char *)value); - info.dependencies_generated.extend_non_duplicates(deps); + source_files.append((const char *)value); BLI_ghashIterator_step(ihash); } BLI_ghashIterator_free(ihash); + + std::sort(source_files.begin(), source_files.end()); + for (auto &key : source_files) { + auto deps = gpu_shader_dependency_get_resolved_source(key.c_str()); + info.dependencies_generated.extend_non_duplicates(deps); + } } void GPUCodegen::node_serialize(std::stringstream &eval_ss, const GPUNode *node)