From 52335491d6e3b568f2b19bd0ec15c8d7b5f011da Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 24 Apr 2021 19:19:35 +0300 Subject: [PATCH] Handle SPIR-V arrays with specialization constant for size --- source/core/module.cpp | 34 +++++++++++++++++++++++++++++----- source/core/module.h | 4 ++++ source/core/program.cpp | 26 +++++++++++++++++++++----- source/core/program.h | 1 + 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/source/core/module.cpp b/source/core/module.cpp index ce540505..2474feae 100644 --- a/source/core/module.cpp +++ b/source/core/module.cpp @@ -153,6 +153,14 @@ void SpirVModule::reflect() Reflection reflection; reflection.reflect_code(code); + map spec_indices; + for(map::const_iterator i=reflection.constants.begin(); i!=reflection.constants.end(); ++i) + if(i->second.constant_id>=0) + { + spec_indices[&i->second] = spec_constants.size(); + spec_constants.push_back(i->second); + } + map struct_indices; structs.reserve(reflection.structs.size()); for(map::const_iterator i=reflection.structs.begin(); i!=reflection.structs.end(); ++i) @@ -170,6 +178,11 @@ void SpirVModule::reflect() map::const_iterator k = struct_indices.find(j->struct_type); j->struct_type = (k!=struct_indices.end() ? &structs[k->second] : 0); } + if(j->array_size_spec) + { + map::const_iterator k = spec_indices.find(j->array_size_spec); + j->array_size_spec = (k!=spec_indices.end() ? &spec_constants[k->second] : 0); + } } const StructMember *last_member = &i->members.back(); @@ -179,6 +192,8 @@ void SpirVModule::reflect() const StructMember *lm = &last_member->struct_type->members.back(); if(last_member->array_size) last_offset += last_member->array_stride*(last_member->array_size-1); + else if(last_member->array_size_spec) + last_offset += last_member->array_stride*(last_member->array_size_spec->i_value-1); last_offset += lm->offset; last_member = lm; } @@ -206,11 +221,18 @@ void SpirVModule::reflect() } for(vector::iterator i=variables.begin(); i!=variables.end(); ++i) + { if(i->struct_type) { map::const_iterator j = struct_indices.find(i->struct_type); i->struct_type = (j!=struct_indices.end() ? &structs[j->second] : 0); } + if(i->array_size_spec) + { + map::const_iterator j = spec_indices.find(i->array_size_spec); + i->array_size_spec = (j!=spec_indices.end() ? &spec_constants[j->second] : 0); + } + } entry_points.reserve(reflection.entry_points.size()); for(map::const_iterator i=reflection.entry_points.begin(); i!=reflection.entry_points.end(); ++i) @@ -223,10 +245,6 @@ void SpirVModule::reflect() *j = (k!=var_indices.end() ? &variables[k->second] : 0); } } - - for(map::const_iterator i=reflection.constants.begin(); i!=reflection.constants.end(); ++i) - if(i->second->constant_id>=0) - spec_constants.push_back(i->second); } @@ -240,6 +258,7 @@ SpirVModule::StructMember::StructMember(): struct_type(0), offset(0), array_size(0), + array_size_spec(0), array_stride(0), matrix_stride(0) { } @@ -268,6 +287,7 @@ bool SpirVModule::Variable::operator==(const Variable &other) const SpirVModule::TypeInfo::TypeInfo(): type(VOID), struct_type(0), + array_size_spec(0), array_size(0), array_stride(0), storage(static_cast(-1)) @@ -443,7 +463,9 @@ void SpirVModule::Reflection::reflect_array_type(CodeIterator op) type.struct_type = elem.struct_type; const Constant &size = constants[*(op+3)]; - if(size.type==INT || size.type==UNSIGNED_INT) + if(size.constant_id>=0) + type.array_size_spec = &size; + else if(size.type==INT || size.type==UNSIGNED_INT) type.array_size = size.i_value; } @@ -464,6 +486,7 @@ void SpirVModule::Reflection::reflect_struct_type(CodeIterator op) mem->type = type.type; mem->struct_type = type.struct_type; mem->array_size = type.array_size; + mem->array_size_spec = type.array_size_spec; mem->array_stride = type.array_stride; } } @@ -501,6 +524,7 @@ void SpirVModule::Reflection::reflect_variable(CodeIterator op) var.type = type.type; var.struct_type = type.struct_type; var.array_size = type.array_size; + var.array_size_spec = type.array_size_spec; } void SpirVModule::Reflection::reflect_decorate(CodeIterator op) diff --git a/source/core/module.h b/source/core/module.h index 6ca522a5..2b632fab 100644 --- a/source/core/module.h +++ b/source/core/module.h @@ -78,6 +78,7 @@ public: OUTPUT = 3 }; + struct Constant; struct Structure; struct Variable; @@ -97,6 +98,7 @@ public: const Structure *struct_type; unsigned offset; unsigned array_size; + const Constant *array_size_spec; unsigned array_stride; unsigned matrix_stride; @@ -116,6 +118,7 @@ public: StorageClass storage; DataType type; const Structure *struct_type; + const Constant *array_size_spec; unsigned array_size; int location; int descriptor_set; @@ -143,6 +146,7 @@ private: { DataType type; const Structure *struct_type; + const Constant *array_size_spec; unsigned array_size; unsigned array_stride; StorageClass storage; diff --git a/source/core/program.cpp b/source/core/program.cpp index 81da5b96..038c0313 100644 --- a/source/core/program.cpp +++ b/source/core/program.cpp @@ -214,6 +214,9 @@ void Program::add_spirv_stages(const SpirVModule &mod, const map &s const vector &code = mod.get_code(); glShaderBinary(stage_ids.size(), &stage_ids[0], GL_SHADER_BINARY_FORMAT_SPIR_V, &code[0], code.size()*4); + if(!spec_values.empty() && !transient) + transient = new TransientData; + const vector &spec_consts = mod.get_spec_constants(); vector spec_id_array; vector spec_value_array; @@ -226,6 +229,7 @@ void Program::add_spirv_stages(const SpirVModule &mod, const map &s { spec_id_array.push_back(i->constant_id); spec_value_array.push_back(j->second); + transient->spec_values[i->constant_id] = j->second; } } @@ -333,9 +337,6 @@ void Program::link() glUniform1i(location, i->second); } } - - delete transient; - transient = 0; } } else if(module->get_format()==Module::SPIR_V) @@ -344,6 +345,9 @@ void Program::link() collect_attributes(); } + delete transient; + transient = 0; + for(vector::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i) require_type(i->type); for(vector::const_iterator i=attributes.begin(); i!=attributes.end(); ++i) @@ -570,9 +574,21 @@ void Program::collect_block_uniforms(const SpirVModule::Structure &strct, const unsigned offset = base_offset+i->offset; if(i->struct_type) { - if(i->array_size) + unsigned array_size = i->array_size; + if(i->array_size_spec) + { + array_size = i->array_size_spec->i_value; + if(transient) + { + map::const_iterator j = transient->spec_values.find(i->array_size_spec->constant_id); + if(j!=transient->spec_values.end()) + array_size = j->second; + } + } + + if(array_size) { - for(unsigned j=0; jarray_size; ++j, offset+=i->array_stride) + for(unsigned j=0; jarray_stride) collect_block_uniforms(*i->struct_type, format("%s%s[%d].", prefix, i->name, j), offset, uniform_names); } else diff --git a/source/core/program.h b/source/core/program.h index 6ed2f571..201d9270 100644 --- a/source/core/program.h +++ b/source/core/program.h @@ -105,6 +105,7 @@ private: { std::map textures; std::map blocks; + std::map spec_values; }; unsigned id; -- 2.45.2