From d751f5bbfb148db746ae1ea79c56c9bb96758155 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:07:25 +0300 Subject: [PATCH] Allow shader containers to be loaded in parallel. --- core/io/compression.cpp | 51 +++++++++++++-------- servers/rendering/renderer_rd/shader_rd.cpp | 40 ++++++++-------- servers/rendering/renderer_rd/shader_rd.h | 2 + servers/rendering/rendering_device.cpp | 4 +- 4 files changed, 54 insertions(+), 43 deletions(-) diff --git a/core/io/compression.cpp b/core/io/compression.cpp index 76663d9c2c..fd45b75a96 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -40,11 +40,34 @@ #include #endif -// Caches for zstd. -static BinaryMutex mutex; -static ZSTD_DCtx *current_zstd_d_ctx = nullptr; -static bool current_zstd_long_distance_matching; -static int current_zstd_window_log_size; +namespace { +struct ZstdDecompressorContext { + ZSTD_DCtx *zstd_d_ctx = nullptr; + bool zstd_long_distance_matching = false; + int zstd_window_log_size = 0; + + ~ZstdDecompressorContext() { + if (zstd_d_ctx) { + ZSTD_freeDCtx(zstd_d_ctx); + } + } + + void invalidate(bool p_zstd_long_distance_matching, int p_zstd_window_log_size) { + if (!zstd_d_ctx || zstd_long_distance_matching != p_zstd_long_distance_matching || zstd_window_log_size != p_zstd_window_log_size) { + if (zstd_d_ctx) { + ZSTD_freeDCtx(zstd_d_ctx); + } + + zstd_d_ctx = ZSTD_createDCtx(); + if (p_zstd_long_distance_matching) { + ZSTD_DCtx_setParameter(zstd_d_ctx, ZSTD_d_windowLogMax, p_zstd_window_log_size); + } + zstd_long_distance_matching = p_zstd_long_distance_matching; + zstd_window_log_size = p_zstd_window_log_size; + } + } +}; +} //namespace int64_t Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int64_t p_src_size, Mode p_mode) { switch (p_mode) { @@ -197,22 +220,10 @@ int64_t Compression::decompress(uint8_t *p_dst, int64_t p_dst_max_size, const ui return total; } break; case MODE_ZSTD: { - MutexLock lock(mutex); + thread_local ZstdDecompressorContext decompressor_ctx; + decompressor_ctx.invalidate(zstd_long_distance_matching, zstd_window_log_size); - if (!current_zstd_d_ctx || current_zstd_long_distance_matching != zstd_long_distance_matching || current_zstd_window_log_size != zstd_window_log_size) { - if (current_zstd_d_ctx) { - ZSTD_freeDCtx(current_zstd_d_ctx); - } - - current_zstd_d_ctx = ZSTD_createDCtx(); - if (zstd_long_distance_matching) { - ZSTD_DCtx_setParameter(current_zstd_d_ctx, ZSTD_d_windowLogMax, zstd_window_log_size); - } - current_zstd_long_distance_matching = zstd_long_distance_matching; - current_zstd_window_log_size = zstd_window_log_size; - } - - size_t ret = ZSTD_decompressDCtx(current_zstd_d_ctx, p_dst, p_dst_max_size, p_src, p_src_size); + size_t ret = ZSTD_decompressDCtx(decompressor_ctx.zstd_d_ctx, p_dst, p_dst_max_size, p_src, p_src_size); return (int64_t)ret; } break; } diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index d264f260e1..6b32e4481f 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -258,6 +258,7 @@ void ShaderRD::_initialize_version(Version *p_version) { p_version->variants.resize_initialized(variant_defines.size()); p_version->variant_data.resize(variant_defines.size()); p_version->group_compilation_tasks.resize_initialized(group_enabled.size()); + p_version->group_loaded_from_cache.resize_initialized(group_enabled.size()); } void ShaderRD::_clear_version(Version *p_version) { @@ -611,6 +612,16 @@ String ShaderRD::_get_cache_file_path(Version *p_version, int p_group, const Str return shader_cache_dir.path_join(relative_path); } +void ShaderRD::_load_variant_from_cache(uint32_t p_variant, CompileData p_data) { + uint32_t variant = group_to_variant_map[p_data.group][p_variant]; + if (!variants_enabled[variant]) { + p_data.version->variants.write[variant] = RID(); + return; // Variant is disabled, return. + } + + p_data.version->variants.write[variant] = RD::get_singleton()->shader_create_from_bytecode_with_samplers(p_data.version->variant_data[variant], p_data.version->variants[variant], immutable_samplers); +} + bool ShaderRD::_load_from_cache(Version *p_version, int p_group) { String api_safe_name = String(RD::get_singleton()->get_device_api_name()).validate_filename().to_lower(); Ref f; @@ -662,28 +673,14 @@ bool ShaderRD::_load_from_cache(Version *p_version, int p_group) { p_version->variant_data.write[variant_id] = variant_bytes; } - for (uint32_t i = 0; i < variant_count; i++) { - int variant_id = group_to_variant_map[p_group][i]; - if (!variants_enabled[variant_id]) { - p_version->variants.write[variant_id] = RID(); - continue; - } - print_verbose(vformat("Loading cache for shader %s, variant %d", name, i)); - { - RID shader = RD::get_singleton()->shader_create_from_bytecode_with_samplers(p_version->variant_data[variant_id], p_version->variants[variant_id], immutable_samplers); - if (shader.is_null()) { - for (uint32_t j = 0; j < i; j++) { - int variant_free_id = group_to_variant_map[p_group][j]; - RD::get_singleton()->free_rid(p_version->variants[variant_free_id]); - } - ERR_FAIL_COND_V(shader.is_null(), false); - } + CompileData compile_data; + compile_data.version = p_version; + compile_data.group = p_group; - p_version->variants.write[variant_id] = shader; - } - } + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_load_variant_from_cache, compile_data, variant_count, -1, true, "LoadVariantFromCache"); + p_version->group_compilation_tasks.write[p_group] = group_task; + p_version->group_loaded_from_cache.write[p_group] = true; - p_version->valid = true; return true; } @@ -733,6 +730,7 @@ void ShaderRD::_compile_version_start(Version *p_version, int p_group) { WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, compile_data, group_to_variant_map[p_group].size(), -1, true, SNAME("ShaderCompilation")); p_version->group_compilation_tasks.write[p_group] = group_task; + p_version->group_loaded_from_cache.write[p_group] = false; } void ShaderRD::_compile_version_end(Version *p_version, int p_group) { @@ -772,7 +770,7 @@ void ShaderRD::_compile_version_end(Version *p_version, int p_group) { return; } #if ENABLE_SHADER_CACHE - else if (shader_cache_user_dir_valid) { + else if (shader_cache_user_dir_valid && !p_version->group_loaded_from_cache[p_group]) { _save_to_cache(p_version, p_group); } #endif diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 9ec4cbd0c8..1a2dde3fa8 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -82,6 +82,7 @@ private: HashMap code_sections; Vector custom_defines; Vector group_compilation_tasks; + Vector group_loaded_from_cache; Vector> variant_data; Vector variants; @@ -178,6 +179,7 @@ private: String _version_get_sha1(Version *p_version) const; String _get_cache_file_relative_path(Version *p_version, int p_group, const String &p_api_name); String _get_cache_file_path(Version *p_version, int p_group, const String &p_api_name, bool p_user_dir); + void _load_variant_from_cache(uint32_t p_variant, CompileData p_data); bool _load_from_cache(Version *p_version, int p_group); void _save_to_cache(Version *p_version, int p_group); void _initialize_cache(); diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 5643d82933..69be1e433b 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -4170,8 +4170,6 @@ RID RenderingDevice::shader_create_from_bytecode(const Vector &p_shader } RID RenderingDevice::shader_create_from_bytecode_with_samplers(const Vector &p_shader_binary, RID p_placeholder, const Vector &p_immutable_samplers) { - _THREAD_SAFE_METHOD_ - Ref shader_container = driver->get_shader_container_format().create_container(); ERR_FAIL_COND_V(shader_container.is_null(), RID()); @@ -4195,6 +4193,8 @@ RID RenderingDevice::shader_create_from_bytecode_with_samplers(const Vectorshader_create_from_container(shader_container, driver_immutable_samplers); ERR_FAIL_COND_V(!shader_id, RID()); + _THREAD_SAFE_METHOD_ + // All good, let's create modules. RID id;