]> git.tdb.fi Git - libs/gl.git/commitdiff
Assign bindings to all uniform blocks and sampler uniforms
authorMikko Rasa <tdb@tdb.fi>
Sat, 3 Apr 2021 16:40:34 +0000 (19:40 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 3 Apr 2021 18:30:10 +0000 (21:30 +0300)
21 files changed:
source/glsl/compiler.cpp
source/glsl/features.cpp
source/glsl/features.h
source/glsl/finalize.cpp
source/glsl/finalize.h
tests/glsl/arithmetic_assignment.glsl
tests/glsl/chained_member_access.glsl
tests/glsl/conditional_multiple_emitvertex.glsl
tests/glsl/constant_last_argument.glsl
tests/glsl/constructors.glsl
tests/glsl/function_overloading.glsl
tests/glsl/geometry_interface_block.glsl
tests/glsl/geometry_passthrough.glsl
tests/glsl/ignore_array_in_geometry_passthrough.glsl
tests/glsl/keep_spec_constants_in_module.glsl
tests/glsl/multiple_emitvertex.glsl
tests/glsl/parentheses.glsl
tests/glsl/partially_unused_interface_block.glsl
tests/glsl/specialization_constants.glsl
tests/glsl/ternary_operator.glsl
tests/glsl/uniform_location_allocation.glsl

index 91a13f4398ed02af892f4f1db567b216fab5b5fa..0ad41dfac46c2de102c827e17fa550b421166f3e 100644 (file)
@@ -107,7 +107,7 @@ void Compiler::compile(Mode mode)
                        ++i;
        }
 
-       LocationAllocator().apply(*module);
+       LocationAllocator().apply(*module, features);
        for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
                finalize(*i, mode);
 
index d2030783403e8be9c790dc4c23ae13635b540179..73c95b0fd3cf9248c1499c4e9c129382eb4b9912 100644 (file)
@@ -6,6 +6,7 @@
 #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/gl/misc.h>
 #include "features.h"
 
 namespace Msp {
@@ -22,7 +23,9 @@ Features::Features():
        arb_uniform_buffer_object(false),
        ext_gpu_shader4(false),
        ext_texture_array(false),
-       constant_id_range(0x80000000U)
+       constant_id_range(0x80000000U),
+       uniform_binding_range(84),
+       texture_binding_range(96)
 { }
 
 Features Features::from_context()
@@ -38,6 +41,8 @@ Features Features::from_context()
        features.arb_uniform_buffer_object = ARB_uniform_buffer_object;
        features.ext_gpu_shader4 = EXT_gpu_shader4;
        features.ext_texture_array = EXT_texture_array;
+       features.uniform_binding_range = get_i(GL_MAX_UNIFORM_BUFFER_BINDINGS);
+       features.texture_binding_range = get_i(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
        return features;
 }
 
index 36220eb352fc0e097dfa1a2ddcae378a10e6073f..31825c028e47f7400cba36b7c1a9eb19690c9215 100644 (file)
@@ -20,6 +20,8 @@ struct Features
        bool ext_gpu_shader4;
        bool ext_texture_array;
        unsigned constant_id_range;
+       unsigned uniform_binding_range;
+       unsigned texture_binding_range;
 
        Features();
 
index 1b300e72a872cd55aa19727cf284efba5607b26f..2d1a46fb0862639457a1137a2de94036c6a1f7da 100644 (file)
@@ -1,4 +1,5 @@
 #include <msp/core/algorithm.h>
+#include <msp/core/hash.h>
 #include <msp/core/raii.h>
 #include <msp/strings/lexicalcast.h>
 #include "finalize.h"
@@ -11,11 +12,16 @@ namespace Msp {
 namespace GL {
 namespace SL {
 
-void LocationAllocator::apply(Module &module)
+void LocationAllocator::apply(Module &module, const Features &features)
 {
        for(list<Stage>::iterator i=module.stages.begin(); i!=module.stages.end(); ++i)
                apply(*i);
        allocate_locations("uniform");
+
+       for(vector<InterfaceBlock *>::const_iterator i=unbound_blocks.begin(); i!=unbound_blocks.end(); ++i)
+               bind_uniform((*i)->layout, (*i)->block_name, features.uniform_binding_range);
+       for(vector<VariableDeclaration *>::const_iterator i=unbound_textures.begin(); i!=unbound_textures.end(); ++i)
+               bind_uniform((*i)->layout, (*i)->name, features.texture_binding_range);
 }
 
 void LocationAllocator::apply(Stage &stage)
@@ -45,10 +51,10 @@ void LocationAllocator::allocate_locations(const string &iface)
 
                if((*i)->interface=="uniform")
                {
-                       map<string, unsigned>::const_iterator j = uniform_locations.find((*i)->name);
-                       if(j!=uniform_locations.end())
+                       map<string, Uniform>::const_iterator j = uniforms.find((*i)->name);
+                       if(j!=uniforms.end() && j->second.location>=0)
                        {
-                               add_location((*i)->layout, j->second);
+                               add_layout_value((*i)->layout, "location", j->second.location);
                                continue;
                        }
                }
@@ -67,9 +73,9 @@ void LocationAllocator::allocate_locations(const string &iface)
                        next = blocking+1;
                }
 
-               add_location((*i)->layout, next);
+               add_layout_value((*i)->layout, "location", next);
                if((*i)->interface=="uniform")
-                       uniform_locations[(*i)->name] = next;
+                       uniforms[(*i)->name].location = next;
 
                for(unsigned j=0; j<size; ++j)
                        used.insert(next+j);
@@ -79,21 +85,43 @@ void LocationAllocator::allocate_locations(const string &iface)
        unplaced_variables.erase(write, unplaced_variables.end());
 }
 
-void LocationAllocator::add_location(RefPtr<Layout> &layout, unsigned location)
+void LocationAllocator::bind_uniform(RefPtr<Layout> &layout, const string &name, unsigned range)
+{
+       map<string, Uniform>::const_iterator i = uniforms.find(name);
+       if(i!=uniforms.end() && i->second.bind_point>=0)
+               add_layout_value(layout, "binding", i->second.bind_point);
+       else
+       {
+               set<unsigned> &used = used_bindings[0];
+
+               unsigned bind_point = fold32(hash64(name))%range;
+               while(used.count(bind_point))
+                       bind_point = (bind_point+1)%range;
+
+               add_layout_value(layout, "binding", bind_point);
+               uniforms[name].bind_point = bind_point;
+               used.insert(bind_point);
+       }
+}
+
+void LocationAllocator::add_layout_value(RefPtr<Layout> &layout, const string &name, unsigned value)
 {
        if(!layout)
                layout = new Layout;
 
        Layout::Qualifier qual;
-       qual.name = "location";
+       qual.name = name;
        qual.has_value = true;
-       qual.value = location;
+       qual.value = value;
        layout->qualifiers.push_back(qual);
 }
 
 void LocationAllocator::visit(VariableDeclaration &var)
 {
-       if(!var.interface.empty() && var.name.compare(0, 3, "gl_"))
+       if(!var.name.compare(0, 3, "gl_"))
+               return;
+
+       if(!var.interface.empty())
        {
                int location = (var.layout ? get_layout_value(*var.layout, "location") : -1);
 
@@ -101,7 +129,7 @@ void LocationAllocator::visit(VariableDeclaration &var)
                {
                        location = get_layout_value(*var.linked_declaration->layout, "location");
                        if(location>=0)
-                               add_location(var.layout, location);
+                               add_layout_value(var.layout, "location", location);
                }
 
                if(location>=0)
@@ -110,11 +138,48 @@ void LocationAllocator::visit(VariableDeclaration &var)
                        for(unsigned i=0; i<size; ++i)
                                used_locations[var.interface].insert(location+i);
                        if(var.interface=="uniform")
-                               uniform_locations[var.name] = location;
+                               uniforms[var.name].location = location;
                }
                else
                        unplaced_variables.push_back(&var);
        }
+
+       if(var.interface=="uniform")
+       {
+               const TypeDeclaration *type = var.type_declaration;
+               while(const BasicTypeDeclaration *basic = dynamic_cast<const BasicTypeDeclaration *>(type))
+                       type = basic->base_type;
+               if(dynamic_cast<const ImageTypeDeclaration *>(type))
+               {
+                       int bind_point = (var.layout ? get_layout_value(*var.layout, "binding") : -1);
+                       if(bind_point>=0)
+                       {
+                               used_bindings[0].insert(bind_point);
+                               uniforms[var.name].bind_point = bind_point;
+                       }
+                       else
+                               unbound_textures.push_back(&var);
+               }
+       }
+}
+
+void LocationAllocator::visit(InterfaceBlock &iface)
+{
+       if(!iface.instance_name.compare(0, 3, "gl_"))
+               return;
+
+       if(iface.interface=="uniform")
+       {
+               int bind_point = (iface.layout ? get_layout_value(*iface.layout, "binding") : -1);
+
+               if(bind_point>=0)
+               {
+                       used_bindings[0].insert(bind_point);
+                       uniforms[iface.block_name].bind_point = bind_point;
+               }
+               else
+                       unbound_blocks.push_back(&iface);
+       }
 }
 
 
index 28145aebd9e2837abedcb2b5ec54ae3b8f745414..3db581be732cd3c5ea7e0b40fce67498db9e1e45 100644 (file)
@@ -11,20 +11,33 @@ namespace SL {
 class LocationAllocator: private TraversingVisitor
 {
 private:
+       struct Uniform
+       {
+               int location;
+               int desc_set;
+               int bind_point;
+
+               Uniform(): location(-1), desc_set(-1), bind_point(-1) { }
+       };
+
        std::map<std::string, std::set<unsigned> > used_locations;
-       std::map<std::string, unsigned> uniform_locations;
+       std::map<std::string, Uniform> uniforms;
+       std::map<unsigned, std::set<unsigned> > used_bindings;
        std::vector<VariableDeclaration *> unplaced_variables;
+       std::vector<VariableDeclaration *> unbound_textures;
+       std::vector<InterfaceBlock *> unbound_blocks;
 
 public:
-       void apply(Module &);
+       void apply(Module &, const Features &);
 private:
        void apply(Stage &);
 
        void allocate_locations(const std::string &);
-       void add_location(RefPtr<Layout> &, unsigned);
+       void bind_uniform(RefPtr<Layout> &, const std::string &, unsigned);
+       void add_layout_value(RefPtr<Layout> &, const std::string &, unsigned);
 
        virtual void visit(VariableDeclaration &);
-       virtual void visit(InterfaceBlock &) { }
+       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &) { }
 };
 
index 01e03b075a1580951d510b43a9e9653acdb6457f..c3bcdad070b5f6dc511cca9f73f78054ef69cf33 100644 (file)
@@ -41,7 +41,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=4) uniform sampler2D tex;
+layout(location=4, binding=71) uniform sampler2D tex;
 layout(location=5) uniform vec3 tint;
 layout(location=6) uniform vec3 ambient;
 layout(location=0) out vec4 frag_color;
index c34cf7d53d8984912a066529c5452e668476b604..2b9c719a0f68fa56b828ed9b840b330e55806f1c 100644 (file)
@@ -29,7 +29,7 @@ struct Transform
 {
        TransformComponents components;
 };
-uniform ModelData
+layout(binding=26) uniform ModelData
 {
        Transform transform;
 } model;
index 7a80a72b2fe7c76faa32f9dffcd507cc198449d2..2e4f32b1ab601593104a6f76efb62e5b86c940c7 100644 (file)
@@ -66,7 +66,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=1) uniform sampler2D tex;
+layout(location=1, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _gs_out_texcoord;
 void main()
index 4285b5f06889c11723cfdf48593841d3e539e4c5..003de2d50eee97ad5d315af72b20d8ae2024192e 100644 (file)
@@ -30,7 +30,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=4) uniform sampler2D tex;
+layout(location=4, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _vs_out_texcoord;
 void main()
index d10dacf51dce9a6a6f04be0f779a8eb9c82262ea..ddb1dceae6f1c811bf8fde17cf3a0a9e1db8f314 100644 (file)
@@ -47,7 +47,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=9) uniform sampler2D normalmap;
+layout(location=9, binding=25) uniform sampler2D normalmap;
 layout(location=0) out vec4 frag_color;
 layout(location=1) in vec2 _vs_out_texcoord;
 layout(location=0) in vec3 tbn_light_dir;
index 02576cadcc5096473034123ad49b3fcef0d7c91f..a44c00d4459fe1bce58e4fb680b46bed03315507 100644 (file)
@@ -42,7 +42,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=4) uniform sampler2D tex;
+layout(location=4, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _vs_out_texcoord;
 void main()
index fb9a2aa00ad53cebd6ba61028a26dbf62d2b2b62..ea0d377a913631529cf30927798ec9e08446e22c 100644 (file)
@@ -72,7 +72,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=0) uniform sampler2D tex;
+layout(location=0, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 in GeometryOut
 {
index 95e5ecbdb8289a1bea57235f4faa4ec4e483757b..5935284264b1d01c1dd74d1a3b779b9fc2b724d3 100644 (file)
@@ -54,7 +54,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=0) uniform sampler2D tex;
+layout(location=0, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _gs_out_texcoord;
 void main()
index 598a177c28cf066b9a537af5dc80821d97934a02..56fe0dfab4dbe8d5a179f5516beac14e7d3f6369 100644 (file)
@@ -61,7 +61,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=4) uniform sampler2D tex;
+layout(location=4, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _gs_out_texcoord;
 void main()
index 674e55eced68ae333a47dcf96175cf1ba5ba4ac1..c60c0a89fe00890b94ce781c8f3d6d376b35d90f 100644 (file)
@@ -44,7 +44,7 @@ void main()
 /* Expected output: fragment
 layout(constant_id=0) const bool use_texture = false;
 layout(constant_id=1) const bool use_vertex_color = false;
-layout(location=4) uniform sampler2D tex;
+layout(location=4, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=1) in vec2 _vs_out_texcoord;
 layout(location=0) in vec4 _vs_out_color;
index 8d769e8b75e16a175743edbccadec493ba1b1a4c..227f1e093359a4492faadef39e0b0d7108d19a49 100644 (file)
@@ -58,7 +58,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=0) uniform sampler2D tex;
+layout(location=0, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _gs_out_texcoord;
 void main()
index 24635017a43093d35e645fbed90a49fa69784aec..a1cd9b88f9339762127650c84ca0ee3ef00ffbd1 100644 (file)
@@ -58,7 +58,7 @@ struct LightParams
 };
 layout(location=5) uniform LightParams light;
 layout(location=9) uniform vec3 material_color;
-layout(location=10) uniform sampler2D occlusion_map;
+layout(location=10, binding=83) uniform sampler2D occlusion_map;
 layout(location=0) out vec4 frag_color;
 layout(location=1) in vec2 _vs_out_texcoord;
 layout(location=0) in vec3 _vs_out_normal;
index 240ddcfa056567d2f570dabe995ec8645add79c5..7ccdc0d766c032befdd301a5b4f0176c03644ca3 100644 (file)
@@ -28,7 +28,7 @@ void main()
 }
 
 /* Expected output: vertex
-uniform GlobalValues
+layout(binding=72) uniform GlobalValues
 {
        vec4 tint;
        vec2 scale;
@@ -49,7 +49,7 @@ void main()
 */
 
 /* Expected output: fragment
-uniform GlobalValues
+layout(binding=72) uniform GlobalValues
 {
        vec4 tint;
        vec2 scale;
index 2b9eaad843fdd31874f4bc40538d1896bce5e421..eacc9bde48837386ef3b91707d898858c289ed02 100644 (file)
@@ -39,7 +39,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=4) uniform sampler2D tex;
+layout(location=4, binding=71) uniform sampler2D tex;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _vs_out_texcoord;
 void main()
index d3844af853626cd2b0ffb700e15923237fe3c4b1..a04d810213cf7f5942e2b8c4ff9560ef0f05100f 100644 (file)
@@ -26,7 +26,7 @@ void main()
 }
 
 /* Expected output: vertex
-uniform Transform
+layout(binding=48) uniform Transform
 {
   mat4 mvp;
 } transform;
@@ -41,12 +41,12 @@ void main()
 */
 
 /* Expected output: fragment
-uniform Colors
+layout(binding=23) uniform Colors
 {
   vec4 color1;
   vec4 color2;
 };
-layout(location=0) uniform sampler2D mask;
+layout(location=0, binding=75) uniform sampler2D mask;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _vs_out_texcoord;
 void main()
index f82a9b8c43a64a4a3b9121b5cd7e693630ef8c31..f0ab84762bed751a968744b34ca5f250dac47e95 100644 (file)
@@ -20,7 +20,7 @@ void main()
 
 /* Expected output: vertex
 layout(location=1) uniform mat4 mvp;
-layout(location=0) uniform sampler2D heightmap;
+layout(location=0, binding=16) uniform sampler2D heightmap;
 layout(location=0) in vec2 position;
 layout(location=1) in vec2 texcoord;
 layout(location=0) out vec2 _vs_out_texcoord;
@@ -32,7 +32,7 @@ void main()
 */
 
 /* Expected output: fragment
-layout(location=0) uniform sampler2D heightmap;
+layout(location=0, binding=16) uniform sampler2D heightmap;
 layout(location=5) uniform vec4 color;
 layout(location=0) out vec4 frag_color;
 layout(location=0) in vec2 _vs_out_texcoord;