void Compiler::compile(Mode mode)
{
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
- generate(*i, mode);
+ generate(*i);
bool valid = true;
for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
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)
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)
InterfaceGenerator().apply(stage);
resolve(stage, RESOLVE_BLOCKS|RESOLVE_TYPES|RESOLVE_VARIABLES);
- ConstantSpecializer().apply(stage, (mode==PROGRAM && specialized ? &spec_values : 0));
+ ConstantIdAssigner().apply(stage);
}
template<typename T>
/** Generates any implicitly defines syntactic structures and resolves
variables. */
- void generate(Stage &, Mode);
+ void generate(Stage &);
template<typename T>
bool resolve(Stage &, unsigned &, unsigned);
namespace GL {
namespace SL {
-ConstantSpecializer::ConstantSpecializer():
- values(0)
-{ }
-
-void ConstantSpecializer::apply(Stage &stage, const map<string, int> *v)
+void ConstantIdAssigner::apply(Stage &stage)
{
- values = v;
stage.content.visit(*this);
}
-void ConstantSpecializer::visit(VariableDeclaration &var)
+void ConstantIdAssigner::visit(VariableDeclaration &var)
{
- bool specializable = false;
if(var.layout)
{
vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i)
- if(i->name=="constant_id")
+ if(i->name=="constant_id" && i->has_value)
{
- specializable = true;
- if(values)
- qualifiers.erase(i);
- else if(i->value==-1)
+ if(i->value==-1)
i->value = hash32(var.name)&0x7FFFFFFF;
break;
}
-
- if(qualifiers.empty())
- var.layout = 0;
- }
-
- if(specializable && values)
- {
- map<string, int>::const_iterator i = values->find(var.name);
- if(i!=values->end())
- {
- RefPtr<Literal> literal = new Literal;
- if(var.type=="bool")
- {
- literal->token = (i->second ? "true" : "false");
- literal->value = static_cast<bool>(i->second);
- }
- else if(var.type=="int")
- {
- literal->token = lexical_cast<string>(i->second);
- literal->value = i->second;
- }
- var.init_expression = literal;
- }
}
}
namespace GL {
namespace SL {
-/** Manipulates specialization constants. If values are specified, turns
-specialization constants into normal constants. Without values assigns
-automatic constant_ids to specialization constants. */
-class ConstantSpecializer: private TraversingVisitor
+/** Assigns IDs to specialization constants with an automatic ID. */
+class ConstantIdAssigner: private TraversingVisitor
{
-private:
- const std::map<std::string, int> *values;
-
public:
- ConstantSpecializer();
-
- void apply(Stage &, const std::map<std::string, int> *);
+ void apply(Stage &);
private:
virtual void visit(VariableDeclaration &);
namespace GL {
namespace SL {
+ConstantSpecializer::ConstantSpecializer():
+ values(0)
+{ }
+
+void ConstantSpecializer::apply(Stage &stage, const map<string, int> &v)
+{
+ values = &v;
+ stage.content.visit(*this);
+}
+
+void ConstantSpecializer::visit(VariableDeclaration &var)
+{
+ bool specializable = false;
+ if(var.layout)
+ {
+ vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
+ for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); (!specializable && i!=qualifiers.end()); ++i)
+ if(i->name=="constant_id")
+ {
+ specializable = true;
+ qualifiers.erase(i);
+ }
+
+ if(qualifiers.empty())
+ var.layout = 0;
+ }
+
+ if(specializable)
+ {
+ map<string, int>::const_iterator i = values->find(var.name);
+ if(i!=values->end())
+ {
+ RefPtr<Literal> literal = new Literal;
+ if(var.type=="bool")
+ {
+ literal->token = (i->second ? "true" : "false");
+ literal->value = static_cast<bool>(i->second);
+ }
+ else if(var.type=="int")
+ {
+ literal->token = lexical_cast<string>(i->second);
+ literal->value = i->second;
+ }
+ var.init_expression = literal;
+ }
+ }
+}
+
+
InlineableFunctionLocator::InlineableFunctionLocator():
current_function(0),
return_count(0)
namespace GL {
namespace SL {
+/** Assigns values to specialization constants, turning them into normal
+constants. */
+class ConstantSpecializer: private TraversingVisitor
+{
+private:
+ const std::map<std::string, int> *values;
+
+public:
+ ConstantSpecializer();
+
+ void apply(Stage &, const std::map<std::string, int> &);
+
+private:
+ virtual void visit(VariableDeclaration &);
+};
+
/** Finds functions which are candidates for inlining. Currently this means
functions which have no flow control statements, no more than one return
statement, and are only called once. */