diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 805b34ebfe0..d22881846aa 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -1906,6 +1906,20 @@ SpecializationBatchHandle GLShaderCompiler::precompile_specializations( return handle; } +GLShader::GLProgram *GLShaderCompiler::SpecializationWork::program_get() +{ + for (const SpecializationConstant &constant : constants) { + const ShaderInput *input = shader->interface->constant_get(constant.name.c_str()); + BLI_assert_msg(input != nullptr, "The specialization constant doesn't exists"); + shader->constants.values[input->location].u = constant.value.u; + } + shader->constants.is_dirty = true; + if (shader->program_cache_.contains(shader->constants.values)) { + return &shader->program_cache_.lookup(shader->constants.values); + } + return nullptr; +} + void GLShaderCompiler::prepare_next_specialization_batch() { BLI_assert(current_specialization_batch.is_ready && !specialization_queue.is_empty()); @@ -1920,24 +1934,20 @@ void GLShaderCompiler::prepare_next_specialization_batch() for (auto &specialization : next.specializations) { GLShader *sh = static_cast(unwrap(specialization.shader)); - for (const SpecializationConstant &constant : specialization.constants) { - const ShaderInput *input = sh->interface->constant_get(constant.name.c_str()); - BLI_assert_msg(input != nullptr, "The specialization constant doesn't exists"); - sh->constants.values[input->location].u = constant.value.u; - } - sh->constants.is_dirty = true; - if (sh->program_cache_.contains(sh->constants.values)) { - /* Already compiled. */ - continue; - } items.append({}); SpecializationWork &item = items.last(); item.shader = sh; + item.constants = specialization.constants; + + if (item.program_get()) { + /* Already compiled. */ + items.pop_last(); + continue; + } /** WORKAROUND: Set async_compilation to true, so only the sources are generated. */ sh->async_compilation_ = true; sh->program_get(); - item.program = sh->program_active_; sh->async_compilation_ = false; item.sources = sh->get_sources(); @@ -1971,8 +1981,9 @@ bool GLShaderCompiler::specialization_batch_is_ready(SpecializationBatchHandle & } if (!item.do_async_compilation) { - glDeleteProgram(item.program->program_id); - item.program->program_id = 0; + GLShader::GLProgram *program = item.program_get(); + glDeleteProgram(program->program_id); + program->program_id = 0; item.shader->constants.is_dirty = true; item.is_ready = true; continue; @@ -1984,7 +1995,7 @@ bool GLShaderCompiler::specialization_batch_is_ready(SpecializationBatchHandle & } else if (item.worker->is_ready()) { /* Retrieve the binary compiled by the worker. */ - if (item.worker->load_program_binary(item.program->program_id)) { + if (item.worker->load_program_binary(item.program_get()->program_id)) { item.is_ready = true; } else { diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh index 4407404669f..e121515d64c 100644 --- a/source/blender/gpu/opengl/gl_shader.hh +++ b/source/blender/gpu/opengl/gl_shader.hh @@ -299,9 +299,11 @@ class GLShaderCompiler : public ShaderCompiler { struct SpecializationWork { GLShader *shader = nullptr; - GLShader::GLProgram *program = nullptr; + Vector constants; GLSourcesBaked sources; + GLShader::GLProgram *program_get(); + GLCompilerWorker *worker = nullptr; bool do_async_compilation = false; bool is_ready = false;