X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcore%2Fprogram.cpp;h=881872212bebc224209f020d24aae0b4cc64c485;hb=89347a620294a1136ee111edeadec68390654f78;hp=16b2fa79c7509a5ee38a6f912c5a2da0ebbf83ec;hpb=5871764de7aa23d2c40cac03ad9d07088fb57e06;p=libs%2Fgl.git diff --git a/source/core/program.cpp b/source/core/program.cpp index 16b2fa79..88187221 100644 --- a/source/core/program.cpp +++ b/source/core/program.cpp @@ -12,118 +12,71 @@ 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(!spec_values.empty()) + { + 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) { - const SpirVModule &spirv_mod = static_cast(mod); - vector used_variables = collect_used_variables(spirv_mod, spec_values); - collect_uniforms(spirv_mod, used_variables); - collect_attributes(spirv_mod, used_variables); + const SpirVModule &spirv_mod = *static_cast(final_module); + collect_uniforms(spirv_mod); + collect_attributes(spirv_mod); collect_builtins(spirv_mod); } 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) require_type(a.type); } -vector Program::collect_used_variables(const SpirVModule &mod, const map &spec_values) -{ - std::map spec_values_by_id; - for(const SpirVModule::Constant &c: mod.get_spec_constants()) - { - auto i = spec_values.find(c.name); - if(i!=spec_values.end()) - spec_values_by_id[c.constant_id] = i->second; - } - - const vector &blocks = mod.get_blocks(); - vector visited(blocks.size(), 4); - for(unsigned i=0; ii_value; - auto j = spec_values_by_id.find(b.condition->constant_id); - if(j!=spec_values_by_id.end()) - cond = j->second; - if(b.negate_condition) - cond = !cond; - } - - visited[i] |= cond*2; - for(const SpirVModule::InstructionBlock *s: b.successors) - visited[s-blocks.data()] &= 3; - } - - for(unsigned i=0; i &variables = mod.get_variables(); - vector used(variables.size()); - for(unsigned i=0; i &blocks, unsigned i, vector &visited) -{ - visited[i] |= 1; - for(const SpirVModule::InstructionBlock *s: blocks[i].successors) - { - unsigned j = s-blocks.data(); - if((visited[j]&3)==2) - collect_visited_blocks(blocks, j, visited); - } -} - -void Program::collect_uniforms(const SpirVModule &mod, const vector &used_variables) +void Program::collect_uniforms(const SpirVModule &mod) { // Prepare the default block reflect_data.uniform_blocks.emplace_back(); vector > block_uniform_names(1); - const vector &variables = mod.get_variables(); unsigned n_descriptor_sets = 0; - for(unsigned i=0; i &used_variables) +void Program::collect_attributes(const SpirVModule &mod) { - const vector &variables = mod.get_variables(); for(const SpirVModule::EntryPoint &e: mod.get_entry_points()) if(e.stage==SpirVModule::VERTEX && e.name=="main") { for(const SpirVModule::Variable *v: e.globals) - if(v->storage==SpirVModule::INPUT && used_variables[v-variables.data()]) + if(v->storage==SpirVModule::INPUT) { reflect_data.attributes.emplace_back(); ReflectData::AttributeInfo &info = reflect_data.attributes.back(); @@ -299,6 +251,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);