+ bool allowed = false;
+ string err_descr;
+ bool value = true;
+ if(i->name=="location")
+ allowed = (variable && scope==GLOBAL);
+ else if(i->name=="binding" || i->name=="set")
+ {
+ if(variable)
+ {
+ TypeDeclaration *type = variable->type_declaration;
+ while(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(type))
+ type = basic->base_type;
+ allowed = (scope==GLOBAL && dynamic_cast<ImageTypeDeclaration *>(type));
+ err_descr = "variable of non-opaque type";
+ }
+ else if(iface_block)
+ allowed = true;
+ }
+ else if(i->name=="constant_id")
+ {
+ allowed = (variable && scope==GLOBAL);
+ if(allowed)
+ {
+ if(!variable->constant)
+ {
+ allowed = false;
+ err_descr = "non-constant variable";
+ }
+ else
+ {
+ BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(variable->type_declaration);
+ if(!basic || basic->kind<BasicTypeDeclaration::BOOL || basic->kind>BasicTypeDeclaration::INT)
+ {
+ allowed = false;
+ err_descr = format("variable of type '%s'",
+ (variable->type_declaration ? variable->type_declaration->name : variable->type));
+ }
+ }
+ }
+ }
+ else if(i->name=="offset")
+ allowed = (variable && scope==INTERFACE_BLOCK);
+ else if(i->name=="points")
+ {
+ allowed = (stage->type==Stage::GEOMETRY && iface_layout && (iface_layout->interface=="in" || iface_layout->interface=="out"));
+ value = false;
+ }
+ else if(i->name=="lines" || i->name=="lines_adjacency" || i->name=="triangles" || i->name=="triangles_adjacency")
+ {
+ allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="in");
+ value = false;
+ }
+ else if(i->name=="line_strip" || i->name=="triangle_strip")
+ {
+ allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="out");
+ value = false;
+ }
+ else if(i->name=="invocations")
+ allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="in");
+ else if(i->name=="max_vertices")
+ allowed = (stage->type==Stage::GEOMETRY && iface_layout && iface_layout->interface=="out");
+ else if(i->name=="std140" || i->name=="std430")
+ {
+ allowed = (iface_block && !variable && iface_block->interface=="uniform");
+ value = false;
+ }
+
+ if(!allowed)
+ {
+ if(err_descr.empty())
+ {
+ if(variable)
+ err_descr = describe_variable(scope);
+ else if(iface_block)
+ err_descr = "interface block";
+ else if(iface_layout)
+ err_descr = format("interface '%s'", iface_layout->interface);
+ else
+ err_descr = "unknown declaration";
+ }
+ error(layout, format("Layout qualifier '%s' not allowed on %s", i->name, err_descr));
+ }
+ else if(value && !i->has_value)
+ error(layout, format("Layout qualifier '%s' requires a value", i->name));
+ else if(!value && i->has_value)
+ error(layout, format("Layout qualifier '%s' does not allow a value", i->name));