+vector<uint8_t> Program::collect_used_variables(const SpirVModule &mod, const map<string, int> &spec_values)
+{
+ std::map<unsigned, int> 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<SpirVModule::InstructionBlock> &blocks = mod.get_blocks();
+ vector<uint8_t> visited(blocks.size(), 4);
+ for(unsigned i=0; i<blocks.size(); ++i)
+ {
+ const SpirVModule::InstructionBlock &b = blocks[i];
+
+ bool cond = true;
+ if(b.condition)
+ {
+ cond = b.condition->i_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<blocks.size(); ++i)
+ if(visited[i]&4)
+ collect_visited_blocks(blocks, i, visited);
+
+ const vector<SpirVModule::Variable> &variables = mod.get_variables();
+ vector<uint8_t> used(variables.size());
+ for(unsigned i=0; i<blocks.size(); ++i)
+ if(visited[i]&1)
+ {
+ for(const SpirVModule::Variable *v: blocks[i].accessed_variables)
+ used[v-variables.data()] = 1;
+ }
+
+ return used;
+}
+
+void Program::collect_visited_blocks(const vector<SpirVModule::InstructionBlock> &blocks, unsigned i, vector<uint8_t> &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<uint8_t> &used_variables)