#include <msp/core/raii.h>
#include <msp/strings/lexicalcast.h>
#include "compatibility.h"
+#include "glsl_error.h"
using namespace std;
void DefaultPrecisionGenerator::apply(Stage &s)
{
stage = &s;
- visit(s.content);
+ s.content.visit(*this);
}
void DefaultPrecisionGenerator::visit(Block &block)
void PrecisionRemover::apply(Stage &stage)
{
- visit(stage.content);
+ stage.content.visit(*this);
NodeRemover().apply(stage, nodes_to_remove);
}
{
stage = &s;
features = feat;
- visit(s.content);
+ if(supports_stage(s.type))
+ s.content.visit(*this);
+ else
+ unsupported(format("Stage %s is not supported", Stage::get_stage_name(s.type)));
+}
+
+void LegacyConverter::unsupported(const string &reason)
+{
+ Diagnostic diagnostic;
+ diagnostic.severity = Diagnostic::ERR;
+ diagnostic.source = GENERATED_SOURCE;
+ diagnostic.line = 0;
+ diagnostic.message = reason;
+ stage->diagnostics.push_back(diagnostic);
}
void LegacyConverter::visit(Block &block)
return true;
}
+bool LegacyConverter::supports_stage(Stage::Type st) const
+{
+ if(st==Stage::GEOMETRY)
+ {
+ if(features.gl_api==OPENGL_ES2)
+ return check_version(Version(3, 20));
+ else
+ return check_version(Version(1, 50));
+ }
+ else
+ return true;
+}
+
bool LegacyConverter::supports_unified_interface_syntax() const
{
if(features.gl_api==OPENGL_ES2)
{
var.name = "gl_FragColor";
var.declaration = 0;
- type = "vec4";
+ r_type = "vec4";
}
else if(var.declaration)
- type = var.declaration->type;
+ r_type = var.declaration->type;
else
- type = string();
+ r_type.clear();
}
void LegacyConverter::visit(Assignment &assign)
{
TraversingVisitor::visit(assign);
- if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
- assign.target_declaration = 0;
+ if(assign.target.declaration==frag_out && !supports_unified_interface_syntax())
+ assign.target.declaration = 0;
}
bool LegacyConverter::supports_unified_sampling_functions() const
if(call.name=="texture")
{
string sampler_type;
- type = string();
+ r_type.clear();
NodeArray<Expression>::iterator i = call.arguments.begin();
if(i!=call.arguments.end())
{
(*i)->visit(*this);
- sampler_type = type;
+ sampler_type = r_type;
for(; i!=call.arguments.end(); ++i)
(*i)->visit(*this);
if(var.layout && !supports_interface_layouts())
{
vector<Layout::Qualifier>::iterator i;
- for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
+ for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->name!="location"); ++i) ;
if(i!=var.layout->qualifiers.end())
{
- unsigned location = lexical_cast<unsigned>(i->value);
if(stage->type==Stage::VERTEX && var.interface=="in")
{
- stage->locations[var.name] = location;
+ stage->locations[var.name] = i->value;
var.layout->qualifiers.erase(i);
}
else if(stage->type==Stage::FRAGMENT && var.interface=="out")
{
- if(location!=0)
- check_extension(&Features::ext_gpu_shader4);
- stage->locations[var.name] = location;
- var.layout->qualifiers.erase(i);
+ if(check_extension(&Features::ext_gpu_shader4))
+ {
+ stage->locations[var.name] = i->value;
+ var.layout->qualifiers.erase(i);
+ }
+ else if(i->value!=0)
+ unsupported("EXT_gpu_shader4 required for multiple fragment shader outputs");
}
if(var.layout->qualifiers.empty())
void LegacyConverter::visit(InterfaceBlock &iface)
{
- if(!supports_interface_blocks(iface.interface))
+ if(!supports_interface_blocks(iface.interface) && iface.type_declaration)
{
- stage->content.body.splice(uniform_insert_point, iface.members.body);
- nodes_to_remove.insert(&iface);
+ if(!iface.instance_name.empty())
+ unsupported("ARB_uniform_buffer_object required for interface block instances");
+ else if(iface.struct_declaration)
+ {
+ stage->content.body.splice(uniform_insert_point, iface.struct_declaration->members.body);
+ nodes_to_remove.insert(&iface);
+ nodes_to_remove.insert(iface.struct_declaration);
+ }
+ else
+ /* If the interface block is an array, it should have an instance
+ name too, so this should never be reached */
+ throw logic_error("Unexpected interface block configuration");
}
}