#include <msp/core/algorithm.h>
#include <msp/core/raii.h>
-#include <msp/gl/extensions/arb_explicit_attrib_location.h>
-#include <msp/gl/extensions/arb_gpu_shader5.h>
-#include <msp/gl/extensions/arb_uniform_buffer_object.h>
-#include <msp/gl/extensions/ext_gpu_shader4.h>
-#include <msp/gl/extensions/ext_texture_array.h>
+#include <msp/strings/lexicalcast.h>
#include "compatibility.h"
using namespace std;
namespace SL {
DefaultPrecisionGenerator::DefaultPrecisionGenerator():
- stage_type(Stage::SHARED),
- toplevel(true)
+ stage(0)
{ }
-void DefaultPrecisionGenerator::apply(Stage &stage)
+void DefaultPrecisionGenerator::apply(Stage &s)
{
- SetForScope<Stage::Type> set_stage(stage_type, stage.type);
- visit(stage.content);
+ stage = &s;
+ visit(s.content);
}
void DefaultPrecisionGenerator::visit(Block &block)
{
- if(toplevel)
+ for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
{
- SetForScope<bool> set(toplevel, false);
- BlockModifier::visit(block);
+ if(&block==&stage->content)
+ insert_point = i;
+ (*i)->visit(*this);
}
- else
- TraversingVisitor::visit(block);
}
void DefaultPrecisionGenerator::visit(Precision &prec)
Precision *prec = new Precision;
if(!type.compare(0, 7, "sampler"))
prec->precision = "lowp";
- else if(stage_type==Stage::FRAGMENT)
+ else if(stage->type==Stage::FRAGMENT)
prec->precision = "mediump";
else
prec->precision = "highp";
prec->type = type;
- insert_nodes.push_back(prec);
+ stage->content.body.insert(insert_point, prec);
have_default.insert(type);
}
}
-void PrecisionRemover::visit(Precision &)
+void PrecisionRemover::apply(Stage &stage)
+{
+ visit(stage.content);
+ NodeRemover().apply(stage, nodes_to_remove);
+}
+
+void PrecisionRemover::visit(Precision &prec)
{
- remove_node = true;
+ nodes_to_remove.insert(&prec);
}
void PrecisionRemover::visit(VariableDeclaration &var)
LegacyConverter::LegacyConverter():
- target_api(get_gl_api()),
- target_version(get_glsl_version()),
frag_out(0)
{ }
-LegacyConverter::LegacyConverter(const Version &v):
- target_api(get_gl_api()),
- target_version(v),
- frag_out(0)
-{ }
+void LegacyConverter::apply(Stage &s, const Features &feat)
+{
+ stage = &s;
+ features = feat;
+ visit(s.content);
+}
+
+void LegacyConverter::visit(Block &block)
+{
+ for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
+ {
+ if(&block==&stage->content)
+ uniform_insert_point = i;
+ (*i)->visit(*this);
+ }
+}
bool LegacyConverter::check_version(const Version &feature_version) const
{
- if(target_version<feature_version)
+ if(features.glsl_version<feature_version)
return false;
- else if(stage->required_version<feature_version)
- stage->required_version = feature_version;
+ else if(stage->required_features.glsl_version<feature_version)
+ stage->required_features.glsl_version = feature_version;
return true;
}
-bool LegacyConverter::check_extension(const Extension &extension) const
+bool LegacyConverter::check_extension(bool Features::*extension) const
{
- if(!extension)
+ if(!(features.*extension))
return false;
- vector<const Extension *>::iterator i = find(stage->required_extensions, &extension);
- if(i==stage->required_extensions.end())
- stage->required_extensions.push_back(&extension);
+ stage->required_features.*extension = true;
return true;
}
-void LegacyConverter::apply(Stage &s)
-{
- SetForScope<Stage *> set_stage(stage, &s);
- visit(s.content);
-}
-
bool LegacyConverter::supports_unified_interface_syntax() const
{
- if(target_api==OPENGL_ES2)
+ if(features.gl_api==OPENGL_ES2)
return check_version(Version(3, 0));
else
return check_version(Version(1, 30));
bool LegacyConverter::supports_unified_sampling_functions() const
{
- if(target_api==OPENGL_ES2)
+ if(features.gl_api==OPENGL_ES2)
return check_version(Version(3, 0));
else
return check_version(Version(1, 30));
call.name = "shadow2D";
else if(sampler_type=="sampler1DArray")
{
- check_extension(EXT_texture_array);
+ check_extension(&Features::ext_texture_array);
call.name = "texture1DArray";
}
else if(sampler_type=="sampler2DArray")
{
- check_extension(EXT_texture_array);
+ check_extension(&Features::ext_texture_array);
call.name = "texture2DArray";
}
else if(sampler_type=="sampler1DArrayShadow")
{
- check_extension(EXT_texture_array);
+ check_extension(&Features::ext_texture_array);
call.name = "shadow1DArray";
}
else if(sampler_type=="sampler2DArrayShadow")
{
- check_extension(EXT_texture_array);
+ check_extension(&Features::ext_texture_array);
call.name = "shadow2DArray";
}
}
bool LegacyConverter::supports_interface_layouts() const
{
- if(target_api==OPENGL_ES2)
+ if(features.gl_api==OPENGL_ES2)
return check_version(Version(3, 0));
else if(check_version(Version(3, 30)))
return true;
else
- return check_extension(ARB_explicit_attrib_location);
+ return check_extension(&Features::arb_explicit_attrib_location);
}
bool LegacyConverter::supports_centroid_sampling() const
{
- if(target_api==OPENGL_ES2)
+ if(features.gl_api==OPENGL_ES2)
return check_version(Version(3, 0));
else if(check_version(Version(1, 20)))
return true;
else
- return check_extension(EXT_gpu_shader4);
+ return check_extension(&Features::ext_gpu_shader4);
}
bool LegacyConverter::supports_sample_sampling() const
{
- if(target_api==OPENGL_ES2)
+ if(features.gl_api==OPENGL_ES2)
return check_version(Version(3, 20));
else if(check_version(Version(4, 0)))
return true;
else
- return check_extension(ARB_gpu_shader5);
+ return check_extension(&Features::arb_gpu_shader5);
}
void LegacyConverter::visit(VariableDeclaration &var)
else if(stage->type==Stage::FRAGMENT && var.interface=="out")
{
if(location!=0)
- static Require _req(EXT_gpu_shader4);
+ check_extension(&Features::ext_gpu_shader4);
stage->locations[var.name] = location;
var.layout->qualifiers.erase(i);
}
if(stage->type==Stage::FRAGMENT && var.interface=="out")
{
frag_out = &var;
- remove_node = true;
+ nodes_to_remove.insert(&var);
}
}
bool LegacyConverter::supports_interface_blocks(const string &iface) const
{
- if(target_api==OPENGL_ES2)
+ if(features.gl_api==OPENGL_ES2)
{
if(iface=="uniform")
return check_version(Version(3, 0));
else if(check_version(Version(1, 50)))
return true;
else if(iface=="uniform")
- return check_extension(ARB_uniform_buffer_object);
+ return check_extension(&Features::arb_uniform_buffer_object);
else
return false;
}
void LegacyConverter::visit(InterfaceBlock &iface)
{
if(!supports_interface_blocks(iface.interface))
- flatten_block(iface.members);
+ {
+ stage->content.body.splice(uniform_insert_point, iface.members.body);
+ nodes_to_remove.insert(&iface);
+ }
}
} // namespace SL