1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Negative Atomic Counter Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fNegativeAtomicCounterTests.hpp"
25
26 #include "deUniquePtr.hpp"
27
28 #include "glwEnums.hpp"
29 #include "gluShaderProgram.hpp"
30
31 #include "tcuTestLog.hpp"
32
33 namespace deqp
34 {
35 namespace gles31
36 {
37 namespace Functional
38 {
39 namespace NegativeTestShared
40 {
41 namespace
42 {
43
44 enum TestCase
45 {
46 TESTCASE_LAYOUT_LARGE_BINDING = 0,
47 TESTCASE_LAYOUT_MEDIUMP_PRECISION,
48 TESTCASE_LAYOUT_LOWP_PRECISION,
49 TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP,
50 TESTCASE_LAYOUT_BINDING_OMITTED,
51 TESTCASE_STRUCT,
52 TESTCASE_BODY_WRITE,
53 TESTCASE_BODY_DECLARE,
54
55 TESTCASE_LAST
56 };
57
58 static const glu::ShaderType s_shaders[] =
59 {
60 glu::SHADERTYPE_VERTEX,
61 glu::SHADERTYPE_FRAGMENT,
62 glu::SHADERTYPE_GEOMETRY,
63 glu::SHADERTYPE_TESSELLATION_CONTROL,
64 glu::SHADERTYPE_TESSELLATION_EVALUATION,
65 glu::SHADERTYPE_COMPUTE
66 };
67
genShaderSource(NegativeTestContext & ctx,TestCase test,glu::ShaderType type)68 std::string genShaderSource (NegativeTestContext& ctx, TestCase test, glu::ShaderType type)
69 {
70 DE_ASSERT(test < TESTCASE_LAST && type < glu::SHADERTYPE_LAST);
71
72 glw::GLint maxBuffers = -1;
73 std::ostringstream shader;
74
75 ctx.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxBuffers);
76
77 shader << getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n";
78
79 switch (type)
80 {
81 case glu::SHADERTYPE_GEOMETRY:
82 shader << "#extension GL_EXT_geometry_shader : enable\n";
83 shader << "layout(max_vertices = 3) out;\n";
84 break;
85
86 case glu::SHADERTYPE_TESSELLATION_CONTROL:
87 case glu::SHADERTYPE_TESSELLATION_EVALUATION:
88 shader << "#extension GL_EXT_tessellation_shader : enable\n";
89 break;
90
91 default:
92 break;
93 }
94
95 switch (test)
96 {
97 case TESTCASE_LAYOUT_LARGE_BINDING:
98 shader << "layout (binding = " << maxBuffers << ", offset = 0) uniform atomic_uint counter0;\n";
99 break;
100
101 case TESTCASE_LAYOUT_MEDIUMP_PRECISION:
102 shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_MEDIUMP) << " uniform atomic_uint counter0;\n";
103 break;
104
105 case TESTCASE_LAYOUT_LOWP_PRECISION:
106 shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_LOWP) << " uniform atomic_uint counter0;\n";
107 break;
108
109 case TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP:
110 shader << "layout (binding = 1, offset = 0) uniform atomic_uint counter0;\n"
111 << "layout (binding = 1, offset = 2) uniform atomic_uint counter1;\n";
112 break;
113
114 case TESTCASE_LAYOUT_BINDING_OMITTED:
115 shader << "layout (offset = 0) uniform atomic_uint counter0;\n";
116 break;
117
118 case TESTCASE_STRUCT:
119 shader << "struct\n"
120 << "{\n"
121 << " int a;\n"
122 << " atomic_uint counter;\n"
123 << "} S;\n";
124 break;
125
126 case TESTCASE_BODY_WRITE:
127 shader << "layout (binding = 1) uniform atomic_uint counter;\n";
128 break;
129
130 default:
131 break;
132 }
133
134 shader << "void main (void)\n"
135 << "{\n";
136
137 switch (test)
138 {
139 case TESTCASE_BODY_WRITE:
140 shader << "counter = 1;\n";
141 break;
142
143 case TESTCASE_BODY_DECLARE:
144 shader << "atomic_uint counter;\n";
145 break;
146
147 default:
148 break;
149 }
150
151 shader << "}\n";
152
153 return shader.str();
154 }
155
iterateShaders(NegativeTestContext & ctx,TestCase testCase)156 void iterateShaders (NegativeTestContext& ctx, TestCase testCase)
157 {
158 tcu::TestLog& log = ctx.getLog();
159 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_shaders); ndx++)
160 {
161 if (ctx.isShaderSupported(s_shaders[ndx]))
162 {
163 ctx.beginSection(std::string("Verify shader: ") + glu::getShaderTypeName(s_shaders[ndx]));
164 const glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << glu::ShaderSource(s_shaders[ndx], genShaderSource(ctx, testCase, s_shaders[ndx])));
165 if (program.getShaderInfo(s_shaders[ndx]).compileOk)
166 {
167 log << program;
168 log << tcu::TestLog::Message << "Expected program to fail, but compilation passed." << tcu::TestLog::EndMessage;
169 ctx.fail("Shader was not expected to compile.");
170 }
171 ctx.endSection();
172 }
173 }
174 }
175
atomic_max_counter_bindings(NegativeTestContext & ctx)176 void atomic_max_counter_bindings (NegativeTestContext& ctx)
177 {
178 ctx.beginSection("It is a compile-time error to bind an atomic counter with a binding value greater than or equal to gl_MaxAtomicCounterBindings.");
179 iterateShaders(ctx, TESTCASE_LAYOUT_LARGE_BINDING);
180 ctx.endSection();
181 }
182
atomic_precision(NegativeTestContext & ctx)183 void atomic_precision (NegativeTestContext& ctx)
184 {
185 ctx.beginSection("It is an error to declare an atomic type with a lowp or mediump precision.");
186 iterateShaders(ctx, TESTCASE_LAYOUT_MEDIUMP_PRECISION);
187 iterateShaders(ctx, TESTCASE_LAYOUT_LOWP_PRECISION);
188 ctx.endSection();
189 }
190
atomic_binding_offset_overlap(NegativeTestContext & ctx)191 void atomic_binding_offset_overlap (NegativeTestContext& ctx)
192 {
193 ctx.beginSection("Atomic counters may not have overlapping offsets in the same binding.");
194 iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP);
195 ctx.endSection();
196 }
197
atomic_binding_omitted(NegativeTestContext & ctx)198 void atomic_binding_omitted (NegativeTestContext& ctx)
199 {
200 ctx.beginSection("Atomic counters must specify a binding point");
201 iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OMITTED);
202 ctx.endSection();
203 }
204
atomic_struct(NegativeTestContext & ctx)205 void atomic_struct (NegativeTestContext& ctx)
206 {
207 ctx.beginSection("Structures may not have an atomic_uint variable.");
208 iterateShaders(ctx, TESTCASE_STRUCT);
209 ctx.endSection();
210 }
211
atomic_body_write(NegativeTestContext & ctx)212 void atomic_body_write (NegativeTestContext& ctx)
213 {
214 ctx.beginSection("An atomic_uint variable cannot be directly written to.");
215 iterateShaders(ctx, TESTCASE_BODY_WRITE);
216 ctx.endSection();
217 }
218
atomic_body_declare(NegativeTestContext & ctx)219 void atomic_body_declare (NegativeTestContext& ctx)
220 {
221 ctx.beginSection("An atomic_uint variable cannot be declared in local scope");
222 iterateShaders(ctx, TESTCASE_BODY_DECLARE);
223 ctx.endSection();
224 }
225
226 } // anonymous
227
getNegativeAtomicCounterTestFunctions()228 std::vector<FunctionContainer> getNegativeAtomicCounterTestFunctions ()
229 {
230 const FunctionContainer funcs[] =
231 {
232 {atomic_max_counter_bindings, "atomic_max_counter_bindings", "Invalid atomic counter buffer binding." },
233 {atomic_precision, "atomic_precision", "Invalid precision qualifier." },
234 {atomic_binding_offset_overlap, "atomic_binding_offset_overlap", "Invalid offset." },
235 {atomic_binding_omitted, "atomic_binding_omitted", "Binding not specified." },
236 {atomic_struct, "atomic_struct", "Invalid atomic_uint usage in struct." },
237 {atomic_body_write, "atomic_body_write", "Invalid write access to atomic_uint." },
238 {atomic_body_declare, "atomic_body_declare", "Invalid precision qualifier." },
239 };
240
241 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
242 }
243
244 } // NegativeTestShared
245 } // Functional
246 } // gles31
247 } // deqp
248