if(features.target_api!=VULKAN)
allocate_locations("uniform");
- for(InterfaceBlock *b: unbound_blocks)
- bind_uniform(b->layout, b->block_name, features.uniform_binding_range);
+ for(VariableDeclaration *b: unbound_blocks)
+ bind_uniform(b->layout, b->block_declaration->block_name, features.uniform_binding_range);
for(VariableDeclaration *t: unbound_textures)
bind_uniform(t->layout, t->name, features.texture_binding_range);
}
if(!var.name.compare(0, 3, "gl_"))
return;
- if(!var.interface.empty())
+ if(!var.interface.empty() && !var.block_declaration)
{
int location = get_layout_value(var.layout.get(), "location");
if(var.interface=="uniform")
{
- const TypeDeclaration *base_type = get_ultimate_base_type(var.type_declaration);
- if(dynamic_cast<const ImageTypeDeclaration *>(base_type) && !visit_uniform(var.name, var.layout))
- unbound_textures.push_back(&var);
+ if(var.block_declaration)
+ {
+ bool push_constant = has_layout_qualifier(var.layout.get(), "push_constant");
+ if(!push_constant && !visit_uniform(var.block_declaration->block_name, var.layout))
+ unbound_blocks.push_back(&var);
+ }
+ else
+ {
+ const TypeDeclaration *base_type = get_ultimate_base_type(var.type_declaration);
+ if(dynamic_cast<const ImageTypeDeclaration *>(base_type) && !visit_uniform(var.name, var.layout))
+ unbound_textures.push_back(&var);
+ }
}
}
-void LocationAllocator::visit(InterfaceBlock &iface)
+
+void DepthRangeConverter::apply(Stage &stage, const Features &features)
{
- if(!iface.instance_name.compare(0, 3, "gl_"))
+ if(stage.type!=Stage::VERTEX || features.target_api==VULKAN)
return;
- if(iface.interface=="uniform")
+ stage.content.visit(*this);
+}
+
+void DepthRangeConverter::visit(FunctionDeclaration &func)
+{
+ if(func.definition==&func && func.name=="main")
{
- bool push_constant = has_layout_qualifier(iface.layout.get(), "push_constant");
- if(!push_constant && !visit_uniform(iface.block_name, iface.layout))
- unbound_blocks.push_back(&iface);
+ VariableReference *position = new VariableReference;
+ position->name = "gl_Position";
+
+ MemberAccess *z = new MemberAccess;
+ z->left = position;
+ z->member = "z";
+
+ Literal *scale = new Literal;
+ scale->token = "2.0";
+ scale->value = 2.0f;
+
+ BinaryExpression *multiply = new BinaryExpression;
+ multiply->oper = &Operator::get_operator("*", Operator::BINARY);
+ multiply->left = z;
+ multiply->right = scale;
+
+ MemberAccess *w = new MemberAccess;
+ w->left = position->clone();
+ w->member = "w";
+
+ BinaryExpression *subtract = new BinaryExpression;
+ subtract->oper = &Operator::get_operator("-", Operator::BINARY);
+ subtract->left = multiply;
+ subtract->right = w;
+
+ Assignment *assign = new Assignment;
+ assign->oper = &Operator::get_operator("=", Operator::BINARY);
+ assign->left = z->clone();
+ assign->right = subtract;
+
+ ExpressionStatement *statement = new ExpressionStatement;
+ statement->expression = assign;
+
+ func.body.body.push_back(statement);
}
}
var.name = "gl_FragColor";
var.declaration = 0;
}
-}
-void StructuralFeatureConverter::visit(InterfaceBlockReference &iface)
-{
- r_flattened_interface = nodes_to_remove.count(iface.declaration);
+ r_flattened_interface = nodes_to_remove.count(var.declaration);
}
void StructuralFeatureConverter::visit(MemberAccess &memacc)
TraversingVisitor::visit(call);
}
-void StructuralFeatureConverter::visit(VariableDeclaration &var)
-{
- if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
- if(stage->type==Stage::FRAGMENT && var.interface=="out")
- {
- frag_out = &var;
- nodes_to_remove.insert(&var);
- }
-
- TraversingVisitor::visit(var);
-}
-
bool StructuralFeatureConverter::supports_interface_blocks(const string &iface) const
{
if(features.target_api==VULKAN)
return false;
}
-void StructuralFeatureConverter::visit(InterfaceBlock &iface)
+void StructuralFeatureConverter::visit(VariableDeclaration &var)
{
- bool push_constant = has_layout_qualifier(iface.layout.get(), "push_constant");
- if((!supports_interface_blocks(iface.interface) || (push_constant && features.target_api!=VULKAN)) && iface.type_declaration)
+ if(var.block_declaration)
{
- if(!iface.instance_name.empty())
- unsupported("ARB_uniform_buffer_object required for interface block instances");
- else if(iface.struct_declaration)
+ bool push_constant = has_layout_qualifier(var.layout.get(), "push_constant");
+ if(!supports_interface_blocks(var.interface) || (push_constant && features.target_api!=VULKAN))
{
- for(const RefPtr<Statement> &s: iface.struct_declaration->members.body)
- if(VariableDeclaration *var = dynamic_cast<VariableDeclaration *>(s.get()))
- var->interface = iface.interface;
- stage->content.body.splice(uniform_insert_point, iface.struct_declaration->members.body);
- nodes_to_remove.insert(&iface);
- nodes_to_remove.insert(iface.struct_declaration);
+ if(var.name.find(' ')==string::npos)
+ unsupported("ARB_uniform_buffer_object required for interface block instances");
+ else
+ {
+ for(const RefPtr<Statement> &s: var.block_declaration->members.body)
+ if(VariableDeclaration *mem = dynamic_cast<VariableDeclaration *>(s.get()))
+ mem->interface = var.interface;
+ stage->content.body.splice(uniform_insert_point, var.block_declaration->members.body);
+ nodes_to_remove.insert(&var);
+ nodes_to_remove.insert(var.block_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");
}
+
+ if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
+ if(stage->type==Stage::FRAGMENT && var.interface=="out")
+ {
+ frag_out = &var;
+ nodes_to_remove.insert(&var);
+ }
+
+ TraversingVisitor::visit(var);
}
bool QualifierConverter::supports_uniform_location() const
{
if(features.target_api==VULKAN)
- return true;
+ return false;
else if(features.target_api==OPENGL_ES)
return check_version(Version(3, 10));
else if(check_version(Version(4, 30)))
return check_version(Version(4, 20));
}
+bool QualifierConverter::supports_interface_block_location() const
+{
+ if(features.target_api==VULKAN)
+ return true;
+ else if(features.target_api==OPENGL_ES)
+ return check_version(Version(3, 20));
+ else if(check_version(Version(4, 40)))
+ return true;
+ else
+ return check_extension(&Features::arb_enhanced_layouts);
+}
+
void QualifierConverter::visit(VariableDeclaration &var)
{
if(var.layout)
{
bool supported = true;
bool external = false;
- if(var.interface=="in")
+ if(var.block_declaration)
+ supported = supports_interface_block_location();
+ else if(var.interface=="in")
{
external = (stage->type==Stage::VERTEX);
supported = (external ? supports_interface_layouts() : supports_stage_interface_layouts());
}
else if(i->name=="binding" && !supports_binding())
{
- if(dynamic_cast<const ImageTypeDeclaration *>(get_ultimate_base_type(var.type_declaration)))
+ if(var.block_declaration)
+ stage->uniform_block_bindings[var.block_declaration->block_name] = i->value;
+ else if(dynamic_cast<const ImageTypeDeclaration *>(get_ultimate_base_type(var.type_declaration)))
stage->texture_bindings[var.name] = i->value;
i = var.layout->qualifiers.erase(i);
TraversingVisitor::visit(var);
}
-bool QualifierConverter::supports_interface_block_location() const
-{
- if(features.target_api==VULKAN)
- return true;
- else if(features.target_api==OPENGL_ES)
- return check_version(Version(3, 20));
- else if(check_version(Version(4, 40)))
- return true;
- else
- return check_extension(&Features::arb_enhanced_layouts);
-}
-
-void QualifierConverter::visit(InterfaceBlock &iface)
-{
- if(iface.layout)
- {
- for(auto i=iface.layout->qualifiers.begin(); i!=iface.layout->qualifiers.end(); )
- {
- if(i->name=="location" && !supports_interface_block_location())
- i = iface.layout->qualifiers.erase(i);
- else if(i->name=="binding" && !supports_binding())
- {
- stage->uniform_block_bindings[iface.block_name] = i->value;
- i = iface.layout->qualifiers.erase(i);
- }
- else
- ++i;
- }
-
- if(iface.layout->qualifiers.empty())
- iface.layout = 0;
- }
-}
-
} // namespace SL
} // namespace GL
} // namespace Msp