]> git.tdb.fi Git - libs/gl.git/commitdiff
Handle SPIR-V arrays with specialization constant for size
authorMikko Rasa <tdb@tdb.fi>
Sat, 24 Apr 2021 16:19:35 +0000 (19:19 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 24 Apr 2021 16:19:35 +0000 (19:19 +0300)
source/core/module.cpp
source/core/module.h
source/core/program.cpp
source/core/program.h

index ce540505fdf32d75a71c8430cb564b0537a3ca61..2474feaeb4cfffc8907caf4c1de730d40e5718cd 100644 (file)
@@ -153,6 +153,14 @@ void SpirVModule::reflect()
        Reflection reflection;
        reflection.reflect_code(code);
 
+       map<const Constant *, unsigned> spec_indices;
+       for(map<unsigned, Constant>::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<const Structure *, unsigned> struct_indices;
        structs.reserve(reflection.structs.size());
        for(map<unsigned, Structure>::const_iterator i=reflection.structs.begin(); i!=reflection.structs.end(); ++i)
@@ -170,6 +178,11 @@ void SpirVModule::reflect()
                                map<const Structure *, unsigned>::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 Constant *, unsigned>::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<Variable>::iterator i=variables.begin(); i!=variables.end(); ++i)
+       {
                if(i->struct_type)
                {
                        map<const Structure *, unsigned>::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 Constant *, unsigned>::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<unsigned, EntryPoint>::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<unsigned, Constant>::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<StorageClass>(-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)
index 6ca522a5563d8a79348563f4c6170cc8ba2efcb6..2b632fab485e27fde131d83251ad6ff8519caa07 100644 (file)
@@ -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;
index 81da5b96e7b50fd858e6a82d4017412711b9bb97..038c031393ae33a5fcaeee27a1c00910f5da0c3c 100644 (file)
@@ -214,6 +214,9 @@ void Program::add_spirv_stages(const SpirVModule &mod, const map<string, int> &s
        const vector<UInt32> &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<SpirVModule::Constant> &spec_consts = mod.get_spec_constants();
        vector<unsigned> spec_id_array;
        vector<unsigned> spec_value_array;
@@ -226,6 +229,7 @@ void Program::add_spirv_stages(const SpirVModule &mod, const map<string, int> &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<UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
                require_type(i->type);
        for(vector<AttributeInfo>::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<unsigned, int>::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; j<i->array_size; ++j, offset+=i->array_stride)
+                               for(unsigned j=0; j<array_size; ++j, offset+=i->array_stride)
                                        collect_block_uniforms(*i->struct_type, format("%s%s[%d].", prefix, i->name, j), offset, uniform_names);
                        }
                        else
index 6ed2f5716e7e50e0e20371204bb1eb32035a2aa5..201d927037c57edf0d1464ca1af4002fb28a6d1a 100644 (file)
@@ -105,6 +105,7 @@ private:
        {
                std::map<std::string, unsigned> textures;
                std::map<std::string, unsigned> blocks;
+               std::map<unsigned, int> spec_values;
        };
 
        unsigned id;