+ LocationAllocator().apply(*module, features);
+ for(Stage &s: module->stages)
+ finalize(s, mode);
+
+ compiled = true;
+}
+
+string Compiler::get_combined_glsl() const
+{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_combined_glsl");
+
+ string glsl;
+
+ unsigned source_count = module->source_map.get_count();
+ for(unsigned i=1; i<source_count; ++i)
+ glsl += format("#pragma MSP source(%d, \"%s\")\n", i, module->source_map.get_name(i));
+ for(Stage &s: module->stages)
+ {
+ glsl += format("#pragma MSP stage(%s)\n", Stage::get_stage_name(s.type));
+ glsl += Formatter().apply(s);
+ glsl += '\n';
+ }
+
+ return glsl;
+}
+
+vector<Stage::Type> Compiler::get_stages() const
+{
+ vector<Stage::Type> stage_types;
+ stage_types.reserve(module->stages.size());
+ for(const Stage &s: module->stages)
+ stage_types.push_back(s.type);
+ return stage_types;
+}
+
+string Compiler::get_stage_glsl(Stage::Type stage_type) const
+{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_stage_glsl");
+ auto i = find_member(module->stages, stage_type, &Stage::type);
+ if(i!=module->stages.end())
+ return Formatter().apply(*i);
+ throw key_error(Stage::get_stage_name(stage_type));
+}
+
+vector<uint32_t> Compiler::get_combined_spirv() const
+{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_combined_spirv");
+ SpirVGenerator gen;
+ gen.apply(*module, features);
+ return gen.get_code();
+}
+
+const map<string, unsigned> &Compiler::get_vertex_attributes() const
+{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_vertex_attributes");
+ auto i = find_member(module->stages, Stage::VERTEX, &Stage::type);
+ if(i!=module->stages.end())
+ return i->locations;
+ throw invalid_operation("Compiler::get_vertex_attributes");
+}
+
+const map<string, unsigned> &Compiler::get_fragment_outputs() const
+{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_fragment_outputs");
+ auto i = find_member(module->stages, Stage::FRAGMENT, &Stage::type);
+ if(i!=module->stages.end())
+ return i->locations;
+ throw invalid_operation("Compiler::get_fragment_outputs");
+}
+
+const map<string, unsigned> &Compiler::get_texture_bindings() const
+{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_texture_bindings");
+ return module->shared.texture_bindings;
+}
+
+const map<string, unsigned> &Compiler::get_uniform_block_bindings() const
+{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_uniform_block_bindings");
+ return module->shared.uniform_block_bindings;