X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fcore%2Fprogram.cpp;h=8ac13bbd0ce21454cb5af1b269dacc0fc6770205;hp=57ef987950d9dbbaed82d3a75669b53a6b7fbc20;hb=HEAD;hpb=959efbf61663efd7879070ce0447e02c8a447ce0 diff --git a/source/core/program.cpp b/source/core/program.cpp index 57ef9879..91f21565 100644 --- a/source/core/program.cpp +++ b/source/core/program.cpp @@ -12,36 +12,60 @@ Program::Program(const Module &mod, const map &spec_values) add_stages(mod, spec_values); } +Program::Program(Program &&other): + ProgramBackend(move(other)), + reflect_data(move(other.reflect_data)), + specialized_spirv(other.specialized_spirv) +{ + other.specialized_spirv = 0; +} + +Program::~Program() +{ + delete specialized_spirv; +} + void Program::add_stages(const Module &mod, const map &spec_values) { if(has_stages()) throw invalid_operation("Program::add_stages"); reflect_data = ReflectData(); + const Module *final_module = &mod; - TransientData transient; switch(mod.get_format()) { case Module::GLSL: - add_glsl_stages(static_cast(mod), spec_values, transient); + add_glsl_stages(static_cast(mod), spec_values); break; case Module::SPIR_V: - add_spirv_stages(static_cast(mod), spec_values); + if(static_cast(mod).is_specializable()) + { + specialized_spirv = static_cast(mod).specialize(spec_values); + final_module = specialized_spirv; + } + add_spirv_stages(*static_cast(final_module), spec_values); break; default: throw invalid_argument("Program::add_stages"); } - finalize(mod, transient); - - if(mod.get_format()==Module::SPIR_V) + if(final_module->get_format()==Module::SPIR_V) { - collect_uniforms(static_cast(mod)); - collect_attributes(static_cast(mod)); + const SpirVModule &spirv_mod = *static_cast(final_module); + collect_uniforms(spirv_mod); + collect_attributes(spirv_mod); + collect_builtins(spirv_mod); + + for(const SpirVModule::EntryPoint &e: spirv_mod.get_entry_points()) + if(e.stage==SpirVModule::COMPUTE) + reflect_data.compute_wg_size = e.compute_local_size; } finalize_uniforms(); + reflect_data.update_used_bindings(); + for(const ReflectData::UniformInfo &u: reflect_data.uniforms) require_type(u.type); for(const ReflectData::AttributeInfo &a: reflect_data.attributes) @@ -51,34 +75,48 @@ void Program::add_stages(const Module &mod, const map &spec_values) void Program::collect_uniforms(const SpirVModule &mod) { // Prepare the default block - reflect_data.uniform_blocks.push_back(ReflectData::UniformBlockInfo()); + reflect_data.uniform_blocks.emplace_back(); vector > block_uniform_names(1); for(const SpirVModule::Variable &v: mod.get_variables()) { - if(v.storage==SpirVModule::UNIFORM && v.struct_type) + if((v.storage==SpirVModule::UNIFORM || v.storage==SpirVModule::PUSH_CONSTANT) && v.struct_type) { - reflect_data.uniform_blocks.push_back(ReflectData::UniformBlockInfo()); + reflect_data.uniform_blocks.emplace_back(); ReflectData::UniformBlockInfo &info = reflect_data.uniform_blocks.back(); info.name = v.struct_type->name; - info.bind_point = v.binding; info.data_size = v.struct_type->size; + if(v.storage==SpirVModule::PUSH_CONSTANT) + { + info.bind_point = ReflectData::PUSH_CONSTANT; + reflect_data.push_constants_size = info.data_size; + } + else + { + if(v.binding>=0) + info.bind_point = v.binding | (v.descriptor_set<<20); + else + info.bind_point = ReflectData::DEFAULT_BLOCK; + reflect_data.n_descriptor_sets = max(reflect_data.n_descriptor_sets, v.descriptor_set+1); + } string prefix; if(!v.name.empty()) prefix = v.struct_type->name+"."; - block_uniform_names.push_back(vector()); + block_uniform_names.emplace_back(); collect_block_uniforms(*v.struct_type, prefix, 0, block_uniform_names.back()); } - else if(v.storage==SpirVModule::UNIFORM_CONSTANT && v.location>=0) + else if(v.storage==SpirVModule::UNIFORM_CONSTANT && (v.location>=0 || v.binding>=0)) { block_uniform_names[0].push_back(v.name); - reflect_data.uniforms.push_back(ReflectData::UniformInfo()); + reflect_data.uniforms.emplace_back(); ReflectData::UniformInfo &info = reflect_data.uniforms.back(); info.name = v.name; info.tag = v.name; info.location = v.location; - info.binding = v.binding; + if(v.binding>=0) + info.binding = v.binding | (v.descriptor_set<<20); + reflect_data.n_descriptor_sets = max(reflect_data.n_descriptor_sets, v.descriptor_set+1); info.array_size = max(v.array_size, 1U); info.type = v.type; } @@ -86,6 +124,12 @@ void Program::collect_uniforms(const SpirVModule &mod) sort_member(reflect_data.uniforms, &ReflectData::UniformInfo::tag); + if(block_uniform_names.front().empty()) + { + reflect_data.uniform_blocks.erase(reflect_data.uniform_blocks.begin()); + block_uniform_names.erase(block_uniform_names.begin()); + } + for(unsigned i=0; istorage==SpirVModule::INPUT) { - reflect_data.attributes.push_back(ReflectData::AttributeInfo()); + reflect_data.attributes.emplace_back(); ReflectData::AttributeInfo &info = reflect_data.attributes.back(); info.name = v->name; info.location = v->location; @@ -151,6 +195,8 @@ void Program::collect_attributes(const SpirVModule &mod) info.type = v->type; } } + + sort_member(reflect_data.attributes, &ReflectData::AttributeInfo::name); } void Program::collect_builtins(const SpirVModule &mod) @@ -212,6 +258,12 @@ int Program::get_uniform_binding(Tag tag) const return i!=reflect_data.uniforms.end() && i->tag==tag ? i->binding : -1; } +bool Program::uses_binding(int binding) const +{ + auto i = lower_bound(reflect_data.used_bindings, binding); + return i!=reflect_data.used_bindings.end() && *i==binding; +} + const ReflectData::AttributeInfo &Program::get_attribute_info(const string &name) const { auto i = lower_bound_member(reflect_data.attributes, name, &ReflectData::AttributeInfo::name);