]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/resolve.cpp
Add support for storage images in shaders
[libs/gl.git] / source / glsl / resolve.cpp
index 7c58bc6b0fe309b3137e2e10b239601cf5797e8e..aeccd1bf05ad18debdc3717264b4e58bfdf25493 100644 (file)
@@ -1,5 +1,6 @@
 #include <msp/core/algorithm.h>
 #include <msp/core/raii.h>
+#include <msp/strings/regex.h>
 #include <msp/strings/utils.h>
 #include "reflect.h"
 #include "resolve.h"
@@ -46,7 +47,27 @@ TypeDeclaration *TypeResolver::get_or_create_array_type(TypeDeclaration &type)
        return array;
 }
 
-void TypeResolver::resolve_type(TypeDeclaration *&type, const string &name, bool array)
+TypeDeclaration *TypeResolver::get_or_create_image_type(ImageTypeDeclaration &type, const std::string &texel_format)
+{
+       if(texel_format.empty())
+               return &type;
+
+       auto key = make_pair(&type, texel_format);
+       auto i = image_types.find(key);
+       if(i!=image_types.end())
+               return i->second;
+
+       ImageTypeDeclaration *image = new ImageTypeDeclaration(type);
+       image->source = INTERNAL_SOURCE;
+       image->name = format("%s_%s", type.name, texel_format);
+       image->format = texel_format;
+       image->base_image = &type;
+       stage->content.body.insert(type_insert_point, image);
+       image_types[key] = image;
+       return image;
+}
+
+void TypeResolver::resolve_type(TypeDeclaration *&type, const string &name, bool array, const Layout *layout)
 {
        TypeDeclaration *resolved = 0;
        auto i = stage->types.find(name);
@@ -56,8 +77,23 @@ void TypeResolver::resolve_type(TypeDeclaration *&type, const string &name, bool
                resolved = (j!=alias_map.end() ? j->second : i->second);
        }
 
-       if(resolved && array)
-               resolved = get_or_create_array_type(*resolved);
+       if(resolved)
+       {
+               if(ImageTypeDeclaration *image = dynamic_cast<ImageTypeDeclaration *>(resolved))
+                       if(layout)
+                       {
+                               static const Regex r_format("^(r|rg|rgba)(8|16|8_snorm|16_snorm|16f|32f)$");
+                               for(const Layout::Qualifier &q: layout->qualifiers)
+                                       if(r_format.match(q.name))
+                                       {
+                                               resolved = get_or_create_image_type(*image, q.name);
+                                               break;
+                                       }
+                       }
+
+               if(array)
+                       resolved = get_or_create_array_type(*resolved);
+       }
 
        r_any_resolved |= (resolved!=type);
        type=resolved;
@@ -99,6 +135,10 @@ void TypeResolver::visit(BasicTypeDeclaration &type)
 void TypeResolver::visit(ImageTypeDeclaration &type)
 {
        resolve_type(type.base_type, type.base, false);
+
+       if(!type.format.empty() && type.base_image)
+               image_types[make_pair(type.base_image, type.format)] = &type;
+
        stage->types.insert(make_pair(type.name, &type));
 }
 
@@ -116,7 +156,7 @@ void TypeResolver::visit(StructDeclaration &strct)
 
 void TypeResolver::visit(VariableDeclaration &var)
 {
-       resolve_type(var.type_declaration, var.type, var.array);
+       resolve_type(var.type_declaration, var.type, var.array, var.layout.get());
 
        var.block_declaration = 0;
        if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(get_ultimate_base_type(var.type_declaration)))
@@ -1104,6 +1144,13 @@ void ExpressionResolver::visit(FunctionCall &call)
                                else if(compat!=SAME_TYPE)
                                        return;
                        }
+                       else
+                       {
+                               ImageTypeDeclaration *arg_image = dynamic_cast<ImageTypeDeclaration *>(arg_type);
+                               ImageTypeDeclaration *param_image = dynamic_cast<ImageTypeDeclaration *>(param_type);
+                               if(!arg_image || !param_image || arg_image->base_image!=param_image)
+                                       return;
+                       }
                }
                resolve(call, call.declaration->return_type_declaration, false);
        }
@@ -1198,8 +1245,13 @@ void FunctionResolver::visit(FunctionCall &call)
                bool has_signature = true;
                for(auto i=call.arguments.begin(); (has_signature && i!=call.arguments.end()); ++i)
                {
-                       if((*i)->type)
-                               append(arg_types, ",", (*i)->type->name);
+                       if(const TypeDeclaration *type = (*i)->type)
+                       {
+                               if(const ImageTypeDeclaration *image = dynamic_cast<const ImageTypeDeclaration *>(type))
+                                       if(image->base_image)
+                                               type = image->base_image;
+                               append(arg_types, ",", type->name);
+                       }
                        else
                                has_signature = false;
                }