Fix #124011: GPU: Broken specialization constants
Don't store pointers to `blender::Map` items since, unlike `std::map`, they're not guaranteed to stay valid. This resulted in shader binaries being loaded into the wrong specialization. Pull Request: https://projects.blender.org/blender/blender/pulls/124051
This commit is contained in:
parent
f8e78b8236
commit
b0fbd550e0
@ -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<GLShader *>(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 {
|
||||
|
@ -299,9 +299,11 @@ class GLShaderCompiler : public ShaderCompiler {
|
||||
|
||||
struct SpecializationWork {
|
||||
GLShader *shader = nullptr;
|
||||
GLShader::GLProgram *program = nullptr;
|
||||
Vector<shader::SpecializationConstant> constants;
|
||||
GLSourcesBaked sources;
|
||||
|
||||
GLShader::GLProgram *program_get();
|
||||
|
||||
GLCompilerWorker *worker = nullptr;
|
||||
bool do_async_compilation = false;
|
||||
bool is_ready = false;
|
||||
|
Loading…
Reference in New Issue
Block a user