xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fNegativeAtomicCounterTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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[] = {glu::SHADERTYPE_VERTEX,
59                                             glu::SHADERTYPE_FRAGMENT,
60                                             glu::SHADERTYPE_GEOMETRY,
61                                             glu::SHADERTYPE_TESSELLATION_CONTROL,
62                                             glu::SHADERTYPE_TESSELLATION_EVALUATION,
63                                             glu::SHADERTYPE_COMPUTE};
64 
genShaderSource(NegativeTestContext & ctx,TestCase test,glu::ShaderType type)65 std::string genShaderSource(NegativeTestContext &ctx, TestCase test, glu::ShaderType type)
66 {
67     DE_ASSERT(test < TESTCASE_LAST && type < glu::SHADERTYPE_LAST);
68 
69     glw::GLint maxBuffers = -1;
70     std::ostringstream shader;
71 
72     ctx.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxBuffers);
73 
74     shader << getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n";
75 
76     switch (type)
77     {
78     case glu::SHADERTYPE_GEOMETRY:
79         shader << "#extension GL_EXT_geometry_shader : enable\n";
80         shader << "layout(max_vertices = 3) out;\n";
81         break;
82 
83     case glu::SHADERTYPE_TESSELLATION_CONTROL:
84     case glu::SHADERTYPE_TESSELLATION_EVALUATION:
85         shader << "#extension GL_EXT_tessellation_shader : enable\n";
86         break;
87 
88     default:
89         break;
90     }
91 
92     switch (test)
93     {
94     case TESTCASE_LAYOUT_LARGE_BINDING:
95         shader << "layout (binding = " << maxBuffers << ", offset = 0) uniform atomic_uint counter0;\n";
96         break;
97 
98     case TESTCASE_LAYOUT_MEDIUMP_PRECISION:
99         shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_MEDIUMP)
100                << " uniform atomic_uint counter0;\n";
101         break;
102 
103     case TESTCASE_LAYOUT_LOWP_PRECISION:
104         shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_LOWP)
105                << " uniform atomic_uint counter0;\n";
106         break;
107 
108     case TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP:
109         shader << "layout (binding = 1, offset = 0) uniform atomic_uint counter0;\n"
110                << "layout (binding = 1, offset = 2) uniform atomic_uint counter1;\n";
111         break;
112 
113     case TESTCASE_LAYOUT_BINDING_OMITTED:
114         shader << "layout (offset = 0) uniform atomic_uint counter0;\n";
115         break;
116 
117     case TESTCASE_STRUCT:
118         shader << "struct\n"
119                << "{\n"
120                << "  int a;\n"
121                << "  atomic_uint counter;\n"
122                << "} S;\n";
123         break;
124 
125     case TESTCASE_BODY_WRITE:
126         shader << "layout (binding = 1) uniform atomic_uint counter;\n";
127         break;
128 
129     default:
130         break;
131     }
132 
133     shader << "void main (void)\n"
134            << "{\n";
135 
136     switch (test)
137     {
138     case TESTCASE_BODY_WRITE:
139         shader << "counter = 1;\n";
140         break;
141 
142     case TESTCASE_BODY_DECLARE:
143         shader << "atomic_uint counter;\n";
144         break;
145 
146     default:
147         break;
148     }
149 
150     shader << "}\n";
151 
152     return shader.str();
153 }
154 
iterateShaders(NegativeTestContext & ctx,TestCase testCase)155 void iterateShaders(NegativeTestContext &ctx, TestCase testCase)
156 {
157     tcu::TestLog &log = ctx.getLog();
158     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_shaders); ndx++)
159     {
160         if (ctx.isShaderSupported(s_shaders[ndx]))
161         {
162             ctx.beginSection(std::string("Verify shader: ") + glu::getShaderTypeName(s_shaders[ndx]));
163             const glu::ShaderProgram program(ctx.getRenderContext(),
164                                              glu::ProgramSources() << glu::ShaderSource(
165                                                  s_shaders[ndx], genShaderSource(ctx, testCase, s_shaders[ndx])));
166             if (program.getShaderInfo(s_shaders[ndx]).compileOk)
167             {
168                 log << program;
169                 log << tcu::TestLog::Message << "Expected program to fail, but compilation passed."
170                     << tcu::TestLog::EndMessage;
171                 ctx.fail("Shader was not expected to compile.");
172             }
173             ctx.endSection();
174         }
175     }
176 }
177 
atomic_max_counter_bindings(NegativeTestContext & ctx)178 void atomic_max_counter_bindings(NegativeTestContext &ctx)
179 {
180     ctx.beginSection("It is a compile-time error to bind an atomic counter with a binding value greater than or equal "
181                      "to gl_MaxAtomicCounterBindings.");
182     iterateShaders(ctx, TESTCASE_LAYOUT_LARGE_BINDING);
183     ctx.endSection();
184 }
185 
atomic_precision(NegativeTestContext & ctx)186 void atomic_precision(NegativeTestContext &ctx)
187 {
188     ctx.beginSection("It is an error to declare an atomic type with a lowp or mediump precision.");
189     iterateShaders(ctx, TESTCASE_LAYOUT_MEDIUMP_PRECISION);
190     iterateShaders(ctx, TESTCASE_LAYOUT_LOWP_PRECISION);
191     ctx.endSection();
192 }
193 
atomic_binding_offset_overlap(NegativeTestContext & ctx)194 void atomic_binding_offset_overlap(NegativeTestContext &ctx)
195 {
196     ctx.beginSection("Atomic counters may not have overlapping offsets in the same binding.");
197     iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP);
198     ctx.endSection();
199 }
200 
atomic_binding_omitted(NegativeTestContext & ctx)201 void atomic_binding_omitted(NegativeTestContext &ctx)
202 {
203     ctx.beginSection("Atomic counters must specify a binding point");
204     iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OMITTED);
205     ctx.endSection();
206 }
207 
atomic_struct(NegativeTestContext & ctx)208 void atomic_struct(NegativeTestContext &ctx)
209 {
210     ctx.beginSection("Structures may not have an atomic_uint variable.");
211     iterateShaders(ctx, TESTCASE_STRUCT);
212     ctx.endSection();
213 }
214 
atomic_body_write(NegativeTestContext & ctx)215 void atomic_body_write(NegativeTestContext &ctx)
216 {
217     ctx.beginSection("An atomic_uint variable cannot be directly written to.");
218     iterateShaders(ctx, TESTCASE_BODY_WRITE);
219     ctx.endSection();
220 }
221 
atomic_body_declare(NegativeTestContext & ctx)222 void atomic_body_declare(NegativeTestContext &ctx)
223 {
224     ctx.beginSection("An atomic_uint variable cannot be declared in local scope");
225     iterateShaders(ctx, TESTCASE_BODY_DECLARE);
226     ctx.endSection();
227 }
228 
229 } // namespace
230 
getNegativeAtomicCounterTestFunctions()231 std::vector<FunctionContainer> getNegativeAtomicCounterTestFunctions()
232 {
233     const FunctionContainer funcs[] = {
234         {atomic_max_counter_bindings, "atomic_max_counter_bindings", "Invalid atomic counter buffer binding."},
235         {atomic_precision, "atomic_precision", "Invalid precision qualifier."},
236         {atomic_binding_offset_overlap, "atomic_binding_offset_overlap", "Invalid offset."},
237         {atomic_binding_omitted, "atomic_binding_omitted", "Binding not specified."},
238         {atomic_struct, "atomic_struct", "Invalid atomic_uint usage in struct."},
239         {atomic_body_write, "atomic_body_write", "Invalid write access to atomic_uint."},
240         {atomic_body_declare, "atomic_body_declare", "Invalid precision qualifier."},
241     };
242 
243     return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
244 }
245 
246 } // namespace NegativeTestShared
247 } // namespace Functional
248 } // namespace gles31
249 } // namespace deqp
250