From 8f2713a3f1501e90016bb8069ecd08dde2f90e56 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 3 Apr 2021 19:40:34 +0300 Subject: [PATCH] Assign bindings to all uniform blocks and sampler uniforms --- source/glsl/compiler.cpp | 2 +- source/glsl/features.cpp | 7 +- source/glsl/features.h | 2 + source/glsl/finalize.cpp | 89 ++++++++++++++++--- source/glsl/finalize.h | 21 ++++- tests/glsl/arithmetic_assignment.glsl | 2 +- tests/glsl/chained_member_access.glsl | 2 +- .../glsl/conditional_multiple_emitvertex.glsl | 2 +- tests/glsl/constant_last_argument.glsl | 2 +- tests/glsl/constructors.glsl | 2 +- tests/glsl/function_overloading.glsl | 2 +- tests/glsl/geometry_interface_block.glsl | 2 +- tests/glsl/geometry_passthrough.glsl | 2 +- .../ignore_array_in_geometry_passthrough.glsl | 2 +- tests/glsl/keep_spec_constants_in_module.glsl | 2 +- tests/glsl/multiple_emitvertex.glsl | 2 +- tests/glsl/parentheses.glsl | 2 +- .../partially_unused_interface_block.glsl | 4 +- tests/glsl/specialization_constants.glsl | 2 +- tests/glsl/ternary_operator.glsl | 6 +- tests/glsl/uniform_location_allocation.glsl | 4 +- 21 files changed, 123 insertions(+), 38 deletions(-) diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index 91a13f43..0ad41dfa 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -107,7 +107,7 @@ void Compiler::compile(Mode mode) ++i; } - LocationAllocator().apply(*module); + LocationAllocator().apply(*module, features); for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) finalize(*i, mode); diff --git a/source/glsl/features.cpp b/source/glsl/features.cpp index d2030783..73c95b0f 100644 --- a/source/glsl/features.cpp +++ b/source/glsl/features.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #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; } diff --git a/source/glsl/features.h b/source/glsl/features.h index 36220eb3..31825c02 100644 --- a/source/glsl/features.h +++ b/source/glsl/features.h @@ -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(); diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 1b300e72..2d1a46fb 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #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::iterator i=module.stages.begin(); i!=module.stages.end(); ++i) apply(*i); allocate_locations("uniform"); + + for(vector::const_iterator i=unbound_blocks.begin(); i!=unbound_blocks.end(); ++i) + bind_uniform((*i)->layout, (*i)->block_name, features.uniform_binding_range); + for(vector::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::const_iterator j = uniform_locations.find((*i)->name); - if(j!=uniform_locations.end()) + map::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 &layout, unsigned location) +void LocationAllocator::bind_uniform(RefPtr &layout, const string &name, unsigned range) +{ + map::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 &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, 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(type)) + type = basic->base_type; + if(dynamic_cast(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); + } } diff --git a/source/glsl/finalize.h b/source/glsl/finalize.h index 28145aeb..3db581be 100644 --- a/source/glsl/finalize.h +++ b/source/glsl/finalize.h @@ -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 > used_locations; - std::map uniform_locations; + std::map uniforms; + std::map > used_bindings; std::vector unplaced_variables; + std::vector unbound_textures; + std::vector 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 &, unsigned); + void bind_uniform(RefPtr &, const std::string &, unsigned); + void add_layout_value(RefPtr &, const std::string &, unsigned); virtual void visit(VariableDeclaration &); - virtual void visit(InterfaceBlock &) { } + virtual void visit(InterfaceBlock &); virtual void visit(FunctionDeclaration &) { } }; diff --git a/tests/glsl/arithmetic_assignment.glsl b/tests/glsl/arithmetic_assignment.glsl index 01e03b07..c3bcdad0 100644 --- a/tests/glsl/arithmetic_assignment.glsl +++ b/tests/glsl/arithmetic_assignment.glsl @@ -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; diff --git a/tests/glsl/chained_member_access.glsl b/tests/glsl/chained_member_access.glsl index c34cf7d5..2b9c719a 100644 --- a/tests/glsl/chained_member_access.glsl +++ b/tests/glsl/chained_member_access.glsl @@ -29,7 +29,7 @@ struct Transform { TransformComponents components; }; -uniform ModelData +layout(binding=26) uniform ModelData { Transform transform; } model; diff --git a/tests/glsl/conditional_multiple_emitvertex.glsl b/tests/glsl/conditional_multiple_emitvertex.glsl index 7a80a72b..2e4f32b1 100644 --- a/tests/glsl/conditional_multiple_emitvertex.glsl +++ b/tests/glsl/conditional_multiple_emitvertex.glsl @@ -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() diff --git a/tests/glsl/constant_last_argument.glsl b/tests/glsl/constant_last_argument.glsl index 4285b5f0..003de2d5 100644 --- a/tests/glsl/constant_last_argument.glsl +++ b/tests/glsl/constant_last_argument.glsl @@ -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() diff --git a/tests/glsl/constructors.glsl b/tests/glsl/constructors.glsl index d10dacf5..ddb1dcea 100644 --- a/tests/glsl/constructors.glsl +++ b/tests/glsl/constructors.glsl @@ -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; diff --git a/tests/glsl/function_overloading.glsl b/tests/glsl/function_overloading.glsl index 02576cad..a44c00d4 100644 --- a/tests/glsl/function_overloading.glsl +++ b/tests/glsl/function_overloading.glsl @@ -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() diff --git a/tests/glsl/geometry_interface_block.glsl b/tests/glsl/geometry_interface_block.glsl index fb9a2aa0..ea0d377a 100644 --- a/tests/glsl/geometry_interface_block.glsl +++ b/tests/glsl/geometry_interface_block.glsl @@ -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 { diff --git a/tests/glsl/geometry_passthrough.glsl b/tests/glsl/geometry_passthrough.glsl index 95e5ecbd..59352842 100644 --- a/tests/glsl/geometry_passthrough.glsl +++ b/tests/glsl/geometry_passthrough.glsl @@ -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() diff --git a/tests/glsl/ignore_array_in_geometry_passthrough.glsl b/tests/glsl/ignore_array_in_geometry_passthrough.glsl index 598a177c..56fe0dfa 100644 --- a/tests/glsl/ignore_array_in_geometry_passthrough.glsl +++ b/tests/glsl/ignore_array_in_geometry_passthrough.glsl @@ -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() diff --git a/tests/glsl/keep_spec_constants_in_module.glsl b/tests/glsl/keep_spec_constants_in_module.glsl index 674e55ec..c60c0a89 100644 --- a/tests/glsl/keep_spec_constants_in_module.glsl +++ b/tests/glsl/keep_spec_constants_in_module.glsl @@ -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; diff --git a/tests/glsl/multiple_emitvertex.glsl b/tests/glsl/multiple_emitvertex.glsl index 8d769e8b..227f1e09 100644 --- a/tests/glsl/multiple_emitvertex.glsl +++ b/tests/glsl/multiple_emitvertex.glsl @@ -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() diff --git a/tests/glsl/parentheses.glsl b/tests/glsl/parentheses.glsl index 24635017..a1cd9b88 100644 --- a/tests/glsl/parentheses.glsl +++ b/tests/glsl/parentheses.glsl @@ -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; diff --git a/tests/glsl/partially_unused_interface_block.glsl b/tests/glsl/partially_unused_interface_block.glsl index 240ddcfa..7ccdc0d7 100644 --- a/tests/glsl/partially_unused_interface_block.glsl +++ b/tests/glsl/partially_unused_interface_block.glsl @@ -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; diff --git a/tests/glsl/specialization_constants.glsl b/tests/glsl/specialization_constants.glsl index 2b9eaad8..eacc9bde 100644 --- a/tests/glsl/specialization_constants.glsl +++ b/tests/glsl/specialization_constants.glsl @@ -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() diff --git a/tests/glsl/ternary_operator.glsl b/tests/glsl/ternary_operator.glsl index d3844af8..a04d8102 100644 --- a/tests/glsl/ternary_operator.glsl +++ b/tests/glsl/ternary_operator.glsl @@ -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() diff --git a/tests/glsl/uniform_location_allocation.glsl b/tests/glsl/uniform_location_allocation.glsl index f82a9b8c..f0ab8476 100644 --- a/tests/glsl/uniform_location_allocation.glsl +++ b/tests/glsl/uniform_location_allocation.glsl @@ -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; -- 2.43.0