1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // AtomicCounter_test.cpp:
7 //   Tests for validating ESSL 3.10 section 4.4.6.
8 //
9 
10 #include "gtest/gtest.h"
11 
12 #include "GLSLANG/ShaderLang.h"
13 #include "angle_gl.h"
14 #include "gtest/gtest.h"
15 #include "tests/test_utils/ShaderCompileTreeTest.h"
16 
17 using namespace sh;
18 
19 class AtomicCounterTest : public ShaderCompileTreeTest
20 {
21   public:
AtomicCounterTest()22     AtomicCounterTest() {}
23 
24   protected:
getShaderType() const25     ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
getShaderSpec() const26     ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
initResources(ShBuiltInResources * resources)27     void initResources(ShBuiltInResources *resources) override
28     {
29         resources->MaxAtomicCounterBindings = 8;
30     }
31 };
32 
33 // Test that layout qualifiers described in ESSL 3.10 section 4.4.6 can be successfully compiled,
34 // and the values of offset are properly assigned to counter variables.
TEST_F(AtomicCounterTest,BasicAtomicCounterDeclaration)35 TEST_F(AtomicCounterTest, BasicAtomicCounterDeclaration)
36 {
37     mExtraCompileOptions |= SH_VARIABLES;
38     const std::string &source =
39         "#version 310 es\n"
40         "layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
41         "layout(binding = 2) uniform atomic_uint b;\n"
42         "layout(binding = 2, offset = 12) uniform atomic_uint c, d;\n"
43         "layout(binding = 1, offset = 4) uniform atomic_uint e;\n"
44         "void main()\n"
45         "{\n"
46         "}\n";
47     if (!compile(source))
48     {
49         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
50     }
51 
52     std::vector<sh::ShaderVariable> counters = getUniforms();
53 
54     EXPECT_EQ(std::string("a"), counters[0].name);
55     EXPECT_EQ(2, counters[0].binding);
56     EXPECT_EQ(4, counters[0].offset);
57 
58     EXPECT_EQ(std::string("b"), counters[1].name);
59     EXPECT_EQ(2, counters[1].binding);
60     EXPECT_EQ(8, counters[1].offset);
61 
62     EXPECT_EQ(std::string("c"), counters[2].name);
63     EXPECT_EQ(2, counters[2].binding);
64     EXPECT_EQ(12, counters[2].offset);
65 
66     EXPECT_EQ(std::string("d"), counters[3].name);
67     EXPECT_EQ(2, counters[3].binding);
68     EXPECT_EQ(16, counters[3].offset);
69 
70     EXPECT_EQ(std::string("e"), counters[4].name);
71     EXPECT_EQ(1, counters[4].binding);
72     EXPECT_EQ(4, counters[4].offset);
73 }
74 
75 // Test that ESSL 3.00 doesn't support atomic_uint.
TEST_F(AtomicCounterTest,InvalidShaderVersion)76 TEST_F(AtomicCounterTest, InvalidShaderVersion)
77 {
78     const std::string &source =
79         "#version 300 es\n"
80         "layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
81         "void main()\n"
82         "{\n"
83         "}\n";
84     if (compile(source))
85     {
86         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
87     }
88 }
89 
90 // Test that any qualifier other than uniform leads to compile-time error.
TEST_F(AtomicCounterTest,InvalidQualifier)91 TEST_F(AtomicCounterTest, InvalidQualifier)
92 {
93     const std::string &source =
94         "#version 310 es\n"
95         "layout(binding = 2, offset = 4) in atomic_uint a;\n"
96         "void main()\n"
97         "{\n"
98         "}\n";
99     if (compile(source))
100     {
101         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
102     }
103 }
104 
105 // Test that uniform must be specified for declaration.
TEST_F(AtomicCounterTest,UniformMustSpecifiedForDeclaration)106 TEST_F(AtomicCounterTest, UniformMustSpecifiedForDeclaration)
107 {
108     const std::string &source =
109         "#version 310 es\n"
110         "atomic_uint a;\n"
111         "void main()\n"
112         "{\n"
113         "}\n";
114     if (compile(source))
115     {
116         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
117     }
118 }
119 
120 // Test that offset overlapping leads to compile-time error(ESSL 3.10 section 4.4.6).
TEST_F(AtomicCounterTest,BindingOffsetOverlapping)121 TEST_F(AtomicCounterTest, BindingOffsetOverlapping)
122 {
123     const std::string &source =
124         "#version 310 es\n"
125         "layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
126         "layout(binding = 2, offset = 6) uniform atomic_uint b;\n"
127         "void main()\n"
128         "{\n"
129         "}\n";
130     if (compile(source))
131     {
132         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
133     }
134 }
135 
136 // Test offset inheritance for multiple variables in one same declaration.
TEST_F(AtomicCounterTest,MultipleVariablesDeclaration)137 TEST_F(AtomicCounterTest, MultipleVariablesDeclaration)
138 {
139     const std::string &source =
140         "#version 310 es\n"
141         "layout(binding = 2, offset = 4) uniform atomic_uint a, b;\n"
142         "layout(binding = 2, offset = 8) uniform atomic_uint c;\n"
143         "void main()\n"
144         "{\n"
145         "}\n";
146     if (compile(source))
147     {
148         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
149     }
150 }
151 
152 // Test that subsequent declarations inherit the globally specified offset.
TEST_F(AtomicCounterTest,GlobalBindingOffsetOverlapping)153 TEST_F(AtomicCounterTest, GlobalBindingOffsetOverlapping)
154 {
155     const std::string &source =
156         "#version 310 es\n"
157         "layout(binding = 2, offset = 4) uniform atomic_uint;\n"
158         "layout(binding = 2) uniform atomic_uint b;\n"
159         "layout(binding = 2, offset = 4) uniform atomic_uint c;\n"
160         "void main()\n"
161         "{\n"
162         "}\n";
163     if (compile(source))
164     {
165         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
166     }
167 }
168 
169 // The spec only demands offset unique and non-overlapping. So this should be allowed.
TEST_F(AtomicCounterTest,DeclarationSequenceWithDecrementalOffsetsSpecified)170 TEST_F(AtomicCounterTest, DeclarationSequenceWithDecrementalOffsetsSpecified)
171 {
172     const std::string &source =
173         "#version 310 es\n"
174         "layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
175         "layout(binding = 2, offset = 0) uniform atomic_uint b;\n"
176         "void main()\n"
177         "{\n"
178         "}\n";
179     if (!compile(source))
180     {
181         FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
182     }
183 }
184 
185 // Test that image format qualifiers are not allowed for atomic counters.
TEST_F(AtomicCounterTest,ImageFormatMustNotSpecified)186 TEST_F(AtomicCounterTest, ImageFormatMustNotSpecified)
187 {
188     const std::string &source =
189         "#version 310 es\n"
190         "layout(binding = 2, offset = 4, rgba32f) uniform atomic_uint a;\n"
191         "void main()\n"
192         "{\n"
193         "}\n";
194     if (compile(source))
195     {
196         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
197     }
198 }
199 
200 // Test that global layout qualifiers must not use 'offset'.
TEST_F(AtomicCounterTest,OffsetMustNotSpecifiedForGlobalLayoutQualifier)201 TEST_F(AtomicCounterTest, OffsetMustNotSpecifiedForGlobalLayoutQualifier)
202 {
203     const std::string &source =
204         "#version 310 es\n"
205         "layout(offset = 4) in;\n"
206         "void main()\n"
207         "{\n"
208         "}\n";
209     if (compile(source))
210     {
211         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
212     }
213 }
214 
215 // Test that offset overlapping leads to compile-time error (ESSL 3.10 section 4.4.6).
216 // Note that there is some vagueness in the spec when it comes to this test.
TEST_F(AtomicCounterTest,BindingOffsetOverlappingForArrays)217 TEST_F(AtomicCounterTest, BindingOffsetOverlappingForArrays)
218 {
219     const std::string &source =
220         "#version 310 es\n"
221         "layout(binding = 2, offset = 4) uniform atomic_uint[2] a;\n"
222         "layout(binding = 2, offset = 8) uniform atomic_uint b;\n"
223         "void main()\n"
224         "{\n"
225         "}\n";
226     if (compile(source))
227     {
228         FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
229     }
230 }
231