From 67eb497002d1d9b09831c4d3bb2b510dd148d582 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Fri, 21 Jul 2017 13:36:33 -0600
Subject: [PATCH] SPV/OpenGL: Require locations on non-opaque uniform
 variables.

---
 Test/baseResults/glspv.frag.out            |  7 ++++---
 Test/glspv.frag                            |  7 ++++++-
 Test/spv.targetOpenGL.vert                 |  5 +++--
 glslang/MachineIndependent/ParseHelper.cpp | 18 ++++++++++++------
 glslang/MachineIndependent/ParseHelper.h   |  2 +-
 5 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/Test/baseResults/glspv.frag.out b/Test/baseResults/glspv.frag.out
index 0ff15a8d3..36afc8317 100755
--- a/Test/baseResults/glspv.frag.out
+++ b/Test/baseResults/glspv.frag.out
@@ -1,9 +1,10 @@
 glspv.frag
 ERROR: 0:4: '#error' : GL_SPIRV is set ( correct , not an error )  
 ERROR: 0:6: '#error' : GL_SPIR is 100  
-ERROR: 0:14: 'input_attachment_index' : only allowed when using GLSL for Vulkan 
-ERROR: 0:14: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
-ERROR: 4 compilation errors.  No code generated.
+ERROR: 0:14: 'f' : non-opaque uniform variables need a layout(location=L) 
+ERROR: 0:19: 'input_attachment_index' : only allowed when using GLSL for Vulkan 
+ERROR: 0:19: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
+ERROR: 5 compilation errors.  No code generated.
 
 
 SPIR-V is not generated for failed compile or link
diff --git a/Test/glspv.frag b/Test/glspv.frag
index cea8e135b..008d191a3 100644
--- a/Test/glspv.frag
+++ b/Test/glspv.frag
@@ -1,4 +1,4 @@
-#version 330
+#version 450
 
 #ifdef GL_SPIRV
 #error GL_SPIRV is set ( correct, not an error )
@@ -11,4 +11,9 @@ void main()
 {
 }
 
+uniform float f; // ERROR, no location
+layout(location = 2) uniform float g;
+uniform sampler2D s1;
+layout(location = 3) uniform sampler2D s2;
+
 layout(input_attachment_index = 1) uniform subpassInput sub; // ERROR, no inputs
diff --git a/Test/spv.targetOpenGL.vert b/Test/spv.targetOpenGL.vert
index 0920334fa..6d68a3391 100755
--- a/Test/spv.targetOpenGL.vert
+++ b/Test/spv.targetOpenGL.vert
@@ -1,8 +1,9 @@
 #version 450
 
 layout(constant_id = 3) const int a = 2;
-
-uniform float f;
+layout(location = 2) uniform float f;
+layout(location = 4) uniform sampler2D s1;
+uniform sampler2D s2;
 
 void main()
 {
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 1d56c1fa8..25d360e69 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -2472,16 +2472,22 @@ void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, co
         error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
 }
 
-void TParseContext::transparentCheck(const TSourceLoc& loc, const TType& type, const TString& /*identifier*/)
+void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
 {
     if (parsingBuiltins)
         return;
 
-    // Vulkan doesn't allow transparent uniforms outside of blocks
-    if (spvVersion.vulkan == 0 || type.getQualifier().storage != EvqUniform)
+    if (type.getQualifier().storage != EvqUniform)
         return;
-    if (type.containsNonOpaque())
-        vulkanRemoved(loc, "non-opaque uniforms outside a block");
+
+    if (type.containsNonOpaque()) {
+        // Vulkan doesn't allow transparent uniforms outside of blocks
+        if (spvVersion.vulkan > 0)
+            vulkanRemoved(loc, "non-opaque uniforms outside a block");
+        // OpenGL wants locations on these
+        if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation())
+            error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
+    }
 }
 
 //
@@ -5107,7 +5113,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
 
     samplerCheck(loc, type, identifier, initializer);
     atomicUintCheck(loc, type, identifier);
-    transparentCheck(loc, type, identifier);
+    transparentOpaqueCheck(loc, type, identifier);
 
     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 9e81a378a..73f2470ca 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -327,7 +327,7 @@ public:
     void boolCheck(const TSourceLoc&, const TPublicType&);
     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
-    void transparentCheck(const TSourceLoc&, const TType&, const TString& identifier);
+    void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
-- 
GitLab