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