#include <msp/strings/format.h>
#include <msp/strings/utils.h>
#include "builtin.h"
-#include "compatibility.h"
#include "compiler.h"
#include "debug.h"
#include "error.h"
+#include "finalize.h"
#include "generate.h"
#include "glsl_error.h"
#include "optimize.h"
#include "output.h"
+#include "resolve.h"
#include "resources.h"
#include "validate.h"
Compiler::Compiler():
features(Features::from_context()),
module(0),
+ compiled(false),
specialized(false)
{ }
Compiler::Compiler(const Features &f):
features(f),
module(0),
+ compiled(false),
specialized(false)
{ }
void Compiler::compile(Mode mode)
{
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
- generate(*i, mode);
+ generate(*i);
+ ConstantIdAssigner().apply(*module, features);
+
+ for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+ validate(*i);
+ GlobalInterfaceValidator().apply(*module);
bool valid = true;
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
- if(!validate(*i))
+ if(!check_errors(*i))
valid = false;
if(!valid)
throw invalid_shader_source(get_diagnostics());
- unsigned n = 0;
- for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++n)
+ if(mode==PROGRAM && specialized)
+ {
+ for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+ ConstantSpecializer().apply(*i, spec_values);
+ }
+ for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); )
{
OptimizeResult result = optimize(*i);
if(result==REDO_PREVIOUS)
else if(result!=REDO_STAGE)
++i;
}
+
+ LocationAllocator().apply(*module, features);
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
finalize(*i, 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();
string Compiler::get_stage_glsl(Stage::Type stage_type) const
{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_stage_glsl");
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
if(i->type==stage_type)
return Formatter().apply(*i);
const map<string, unsigned> &Compiler::get_vertex_attributes() const
{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_vertex_attributes");
for(list<Stage>::const_iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
if(i->type==Stage::VERTEX)
return i->locations;
const map<string, unsigned> &Compiler::get_fragment_outputs() const
{
+ if(!compiled)
+ throw invalid_operation("Compiler::get_fragment_outputs");
for(list<Stage>::const_iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
if(i->type==Stage::FRAGMENT)
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;
+}
+
const SourceMap &Compiler::get_source_map() const
{
return module->source_map;
target->required_features.glsl_version = stage.required_features.glsl_version;
for(NodeList<Statement>::iterator i=stage.content.body.begin(); i!=stage.content.body.end(); ++i)
target->content.body.push_back(*i);
- DeclarationCombiner().apply(*target);
}
void Compiler::import(DataFile::Collection *resources, const string &name)
append_module(import_parser.parse(*io, fn, module->source_map.get_count()), resources);
}
-void Compiler::generate(Stage &stage, Mode mode)
+void Compiler::generate(Stage &stage)
{
stage.required_features.gl_api = features.gl_api;
if(module->shared.required_features.glsl_version>stage.required_features.glsl_version)
variables through interfaces. */
InterfaceGenerator().apply(stage);
resolve(stage, RESOLVE_BLOCKS|RESOLVE_TYPES|RESOLVE_VARIABLES);
-
- ConstantSpecializer().apply(stage, (mode==PROGRAM && specialized ? &spec_values : 0));
- if(mode==PROGRAM)
- {
- LegacyConverter().apply(stage, features);
- resolve(stage, RESOLVE_VARIABLES|RESOLVE_FUNCTIONS);
- }
}
template<typename T>
}
}
-bool Compiler::validate(Stage &stage)
+void Compiler::validate(Stage &stage)
{
- TypeValidator().apply(stage);
DeclarationValidator().apply(stage);
+ IdentifierValidator().apply(stage);
ReferenceValidator().apply(stage);
ExpressionValidator().apply(stage);
+ StageInterfaceValidator().apply(stage);
+}
+bool Compiler::check_errors(Stage &stage)
+{
stable_sort(stage.diagnostics, &diagnostic_line_order);
for(vector<Diagnostic>::const_iterator i=stage.diagnostics.begin(); i!=stage.diagnostics.end(); ++i)
Compiler::OptimizeResult Compiler::optimize(Stage &stage)
{
+ if(ConstantFolder().apply(stage))
+ resolve(stage, RESOLVE_EXPRESSIONS);
ConstantConditionEliminator().apply(stage);
bool any_inlined = false;
void Compiler::finalize(Stage &stage, Mode mode)
{
- if(get_gl_api()==OPENGL_ES2 && mode==PROGRAM)
- DefaultPrecisionGenerator().apply(stage);
- else if(mode==MODULE)
- PrecisionRemover().apply(stage);
+ if(mode==PROGRAM)
+ {
+ LegacyConverter().apply(stage, features);
+ resolve(stage, RESOLVE_VARIABLES|RESOLVE_FUNCTIONS);
+ PrecisionConverter().apply(stage);
+ }
+
+ // Collect bindings from all stages into the shared stage's maps
+ module->shared.texture_bindings.insert(stage.texture_bindings.begin(), stage.texture_bindings.end());
+ module->shared.uniform_block_bindings.insert(stage.uniform_block_bindings.begin(), stage.uniform_block_bindings.end());
}
void Compiler::inject_block(Block &target, const Block &source)