From 6997ed1c07c382c0f66c57c080934ad53e1d3713 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 8 Nov 2021 18:17:51 +0200 Subject: [PATCH] Allow a push constant block to be specified, but flatten it for now It's needed for Vulkan, but OpenGL does not have push constants. --- source/glsl/finalize.cpp | 29 ++++++++++++++++++++++------- source/glsl/validate.cpp | 13 +++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index f005d87d..2fff7549 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -221,15 +221,25 @@ void LocationAllocator::visit(InterfaceBlock &iface) if(iface.interface=="uniform") { - int bind_point = (iface.layout ? get_layout_value(*iface.layout, "binding") : -1); + bool push_constant = false; + if(iface.layout) + { + auto i = find_member(iface.layout->qualifiers, string("push_constant"), &Layout::Qualifier::name); + push_constant = (i!=iface.layout->qualifiers.end()); + } - if(bind_point>=0) + if(!push_constant) { - used_bindings[0].insert(bind_point); - uniforms[iface.block_name].bind_point = bind_point; + 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); } - else - unbound_blocks.push_back(&iface); } } @@ -636,6 +646,7 @@ bool LegacyConverter::supports_interface_block_location() const void LegacyConverter::visit(InterfaceBlock &iface) { + bool push_constant = false; if(iface.layout) { for(auto i=iface.layout->qualifiers.begin(); i!=iface.layout->qualifiers.end(); ) @@ -648,14 +659,18 @@ void LegacyConverter::visit(InterfaceBlock &iface) i = iface.layout->qualifiers.erase(i); } else + { + if(i->name=="push_constant") + push_constant = true; ++i; + } } if(iface.layout->qualifiers.empty()) iface.layout = 0; } - if(!supports_interface_blocks(iface.interface) && iface.type_declaration) + if((!supports_interface_blocks(iface.interface) || push_constant) && iface.type_declaration) { if(!iface.instance_name.empty()) unsupported("ARB_uniform_buffer_object required for interface block instances"); diff --git a/source/glsl/validate.cpp b/source/glsl/validate.cpp index f12177db..2da8345d 100644 --- a/source/glsl/validate.cpp +++ b/source/glsl/validate.cpp @@ -49,6 +49,8 @@ const char *DeclarationValidator::describe_variable(ScopeType scope) void DeclarationValidator::visit(Layout &layout) { + bool push_constant = false; + bool binding = false; for(const Layout::Qualifier &q: layout.qualifiers) { bool allowed = false; @@ -58,6 +60,8 @@ void DeclarationValidator::visit(Layout &layout) allowed = (variable && scope==GLOBAL); else if(q.name=="binding" || q.name=="set") { + binding = true; + if(q.name=="set") { error(layout, "Layout qualifier 'set' not allowed when targeting OpenGL"); @@ -141,6 +145,12 @@ void DeclarationValidator::visit(Layout &layout) err_descr = "non-matrix variable"; } } + else if(q.name=="push_constant") + { + push_constant = true; + allowed = (iface_block && !variable && iface_block->interface=="uniform"); + value = false; + } if(!allowed) { @@ -162,6 +172,9 @@ void DeclarationValidator::visit(Layout &layout) else if(!value && q.has_value) error(layout, format("Layout qualifier '%s' does not allow a value", q.name)); } + + if(push_constant && binding) + error(layout, "Layout qualifier 'push_constant' not allowed together with 'binding' or 'set'"); } void DeclarationValidator::visit(InterfaceLayout &layout) -- 2.45.2