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 Program State Query tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fProgramStateQueryTests.hpp"
25 #include "es31fInfoLogQueryShared.hpp"
26 #include "glsStateQueryUtil.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluCallLogWrapper.hpp"
29 #include "gluContextInfo.hpp"
30 #include "gluObjectWrapper.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "glwFunctions.hpp"
33 #include "glwEnums.hpp"
34 #include "tcuStringTemplate.hpp"
35
36 namespace deqp
37 {
38
39 using std::string;
40 using std::map;
41
42 namespace gles31
43 {
44 namespace Functional
45 {
46 namespace
47 {
48
49 using namespace gls::StateQueryUtil;
50
getVerifierSuffix(QueryType type)51 static const char* getVerifierSuffix (QueryType type)
52 {
53 switch (type)
54 {
55 case QUERY_PROGRAM_INTEGER_VEC3:
56 case QUERY_PROGRAM_INTEGER:
57 return "get_programiv";
58
59 default:
60 DE_ASSERT(DE_FALSE);
61 return DE_NULL;
62 }
63 }
64
checkSupport(Context & ctx)65 static bool checkSupport(Context& ctx)
66 {
67 auto ctxType = ctx.getRenderContext().getType();
68 return contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
69 contextSupports(ctxType, glu::ApiType::core(4, 5));
70 }
71
specializeShader(Context & context,const char * code)72 static std::string specializeShader(Context& context, const char* code)
73 {
74 auto ctxType = context.getRenderContext().getType();
75 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(ctxType);
76 const bool isES32orGL45 = checkSupport(context);
77 const bool isES = isContextTypeES(ctxType);
78
79 std::map<std::string, std::string> specializationMap =
80 {
81 { "GLSL_VERSION_DECL", glu::getGLSLVersionDeclaration(glslVersion) },
82 { "GEOMETRY_SHADER_REQUIRE", (isES32orGL45 ? "" : "#extension GL_EXT_geometry_shader : require") },
83 { "TESSELLATION_SHADER_REQUIRE", (isES32orGL45 ? "" : "#extension GL_EXT_tessellation_shader : require") },
84 { "GL_POSITION_REDECL", (isES ? "" : "out gl_PerVertex { vec4 gl_Position;};")}
85 };
86
87 return tcu::StringTemplate(code).specialize(specializationMap);
88 }
89
90
91 class GeometryShaderCase : public TestCase
92 {
93 public:
94 GeometryShaderCase (Context& context, QueryType verifier, const char* name, const char* desc);
95 IterateResult iterate (void);
96
97 private:
98 const QueryType m_verifier;
99 };
100
GeometryShaderCase(Context & context,QueryType verifier,const char * name,const char * desc)101 GeometryShaderCase::GeometryShaderCase (Context& context, QueryType verifier, const char* name, const char* desc)
102 : TestCase (context, name, desc)
103 , m_verifier (verifier)
104 {
105 }
106
iterate(void)107 GeometryShaderCase::IterateResult GeometryShaderCase::iterate (void)
108 {
109 const bool isES32orGL45 = checkSupport(m_context);
110
111 if (!isES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
112 TCU_THROW(NotSupportedError, "Geometry shader tests require GL_EXT_geometry_shader extension or an OpenGL ES 3.2 or higher context.");
113
114
115 static const char* const s_vtxFragTemplate = "${GLSL_VERSION_DECL}\n"
116 "void main()\n"
117 "{\n"
118 "}\n";
119
120 static const char* const s_geometryTemplate1 = "${GLSL_VERSION_DECL}\n"
121 "${GEOMETRY_SHADER_REQUIRE}\n"
122 "layout(triangles) in;"
123 "layout(triangle_strip, max_vertices = 3) out;\n"
124 "void main()\n"
125 "{\n"
126 " EndPrimitive();\n"
127 "}\n";
128
129 static const char* const s_geometryTemplate2 = "${GLSL_VERSION_DECL}\n"
130 "${GEOMETRY_SHADER_REQUIRE}\n"
131 "layout(points) in;"
132 "layout(line_strip, max_vertices = 5) out;\n"
133 "void main()\n"
134 "{\n"
135 " EndPrimitive();\n"
136 "}\n";
137
138 static const char* const s_geometryTemplate3 = "${GLSL_VERSION_DECL}\n"
139 "${GEOMETRY_SHADER_REQUIRE}\n"
140 "layout(points) in;"
141 "layout(points, max_vertices = 50) out;\n"
142 "void main()\n"
143 "{\n"
144 " EndPrimitive();\n"
145 "}\n";
146
147 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
148 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
149
150 gl.enableLogging(true);
151
152 {
153 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Layout", "triangles in, triangle strip out, 3 vertices");
154 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
155 << glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
156 << glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
157 << glu::GeometrySource(specializeShader(m_context, s_geometryTemplate1)));
158
159 TCU_CHECK_MSG(program.isOk(), "Compile failed");
160
161 m_testCtx.getLog() << program;
162
163 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 3, m_verifier);
164 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_TRIANGLES, m_verifier);
165 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_TRIANGLE_STRIP, m_verifier);
166 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_SHADER_INVOCATIONS, 1, m_verifier);
167 }
168
169 {
170 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Layout", "points in, line strip out, 5 vertices");
171 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
172 << glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
173 << glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
174 << glu::GeometrySource(specializeShader(m_context, s_geometryTemplate2)));
175
176 TCU_CHECK_MSG(program.isOk(), "Compile failed");
177
178 m_testCtx.getLog() << program;
179
180 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 5, m_verifier);
181 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_POINTS, m_verifier);
182 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_LINE_STRIP, m_verifier);
183 }
184
185 {
186 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Layout", "points in, points out, 50 vertices");
187 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
188 << glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
189 << glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
190 << glu::GeometrySource(specializeShader(m_context, s_geometryTemplate3)));
191
192 TCU_CHECK_MSG(program.isOk(), "Compile failed");
193
194 m_testCtx.getLog() << program;
195
196 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 50, m_verifier);
197 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_POINTS, m_verifier);
198 verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_POINTS, m_verifier);
199 }
200
201 result.setTestContextResult(m_testCtx);
202 return STOP;
203 }
204
205 class TessellationShaderCase : public TestCase
206 {
207 public:
208 TessellationShaderCase (Context& context, QueryType verifier, const char* name, const char* desc);
209 IterateResult iterate (void);
210
211 private:
212 const QueryType m_verifier;
213 };
214
TessellationShaderCase(Context & context,QueryType verifier,const char * name,const char * desc)215 TessellationShaderCase::TessellationShaderCase (Context& context, QueryType verifier, const char* name, const char* desc)
216 : TestCase (context, name, desc)
217 , m_verifier (verifier)
218 {
219 }
220
iterate(void)221 TessellationShaderCase::IterateResult TessellationShaderCase::iterate (void)
222 {
223 const bool isES32orGL45 = checkSupport(m_context);
224
225 if (!isES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
226 TCU_THROW(NotSupportedError, "Tessellation shader tests require GL_EXT_tessellation_shader extension or an OpenGL ES 3.2 or higher context.");
227
228
229 static const char* const s_vtxFragTemplate = "${GLSL_VERSION_DECL}\n"
230 "void main()\n"
231 "{\n"
232 "}\n";
233
234 static const char* const s_tessCtrlTemplate1 = "${GLSL_VERSION_DECL}\n"
235 "${TESSELLATION_SHADER_REQUIRE}\n"
236 "layout(vertices = 3) out;\n"
237 "void main()\n"
238 "{\n"
239 "}\n";
240
241 static const char* const s_tessEvalTemplate1 = "${GLSL_VERSION_DECL}\n"
242 "${TESSELLATION_SHADER_REQUIRE}\n"
243 "layout(triangles, equal_spacing, cw) in;\n"
244 "void main()\n"
245 "{\n"
246 "}\n";
247
248 static const char* const s_tessCtrlTemplate2 = "${GLSL_VERSION_DECL}\n"
249 "${TESSELLATION_SHADER_REQUIRE}\n"
250 "layout(vertices = 5) out;\n"
251 "void main()\n"
252 "{\n"
253 "}\n";
254
255 static const char* const s_tessEvalTemplate2 = "${GLSL_VERSION_DECL}\n"
256 "${TESSELLATION_SHADER_REQUIRE}\n"
257 "layout(quads, fractional_even_spacing, ccw) in;\n"
258 "void main()\n"
259 "{\n"
260 "}\n";
261
262 static const char* const s_tessEvalTemplate3 = "${GLSL_VERSION_DECL}\n"
263 "${TESSELLATION_SHADER_REQUIRE}\n"
264 "layout(isolines, fractional_odd_spacing, ccw, point_mode) in;\n"
265 "void main()\n"
266 "{\n"
267 "}\n";
268
269 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
270 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
271
272 gl.enableLogging(true);
273
274 {
275 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query State", "3 vertices, triangles, equal_spacing, cw");
276 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
277 << glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
278 << glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
279 << glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate1))
280 << glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate1)));
281
282 TCU_CHECK_MSG(program.isOk(), "Compile failed");
283
284 m_testCtx.getLog() << program;
285
286 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 3, m_verifier);
287 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_TRIANGLES, m_verifier);
288 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_EQUAL, m_verifier);
289 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CW, m_verifier);
290 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_FALSE, m_verifier);
291 }
292
293 {
294 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query State", "5 vertices, quads, fractional_even_spacing, ccw");
295 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
296 << glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
297 << glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
298 << glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate2))
299 << glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate2)));
300
301 TCU_CHECK_MSG(program.isOk(), "Compile failed");
302
303 m_testCtx.getLog() << program;
304
305 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 5, m_verifier);
306 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_QUADS, m_verifier);
307 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_FRACTIONAL_EVEN, m_verifier);
308 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CCW, m_verifier);
309 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_FALSE, m_verifier);
310 }
311
312 {
313 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query State", "5 vertices, isolines, fractional_odd_spacing, ccw, point_mode");
314 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources()
315 << glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
316 << glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
317 << glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate2))
318 << glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate3)));
319
320 TCU_CHECK_MSG(program.isOk(), "Compile failed");
321
322 m_testCtx.getLog() << program;
323
324 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 5, m_verifier);
325 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_ISOLINES, m_verifier);
326 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_FRACTIONAL_ODD, m_verifier);
327 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CCW, m_verifier);
328 verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_TRUE, m_verifier);
329 }
330
331 result.setTestContextResult(m_testCtx);
332 return STOP;
333 }
334
335 class ProgramSeparableCase : public TestCase
336 {
337 public:
338 ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc);
339 IterateResult iterate (void);
340
341 private:
342 const QueryType m_verifier;
343 };
344
ProgramSeparableCase(Context & context,QueryType verifier,const char * name,const char * desc)345 ProgramSeparableCase::ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc)
346 : TestCase (context, name, desc)
347 , m_verifier (verifier)
348 {
349 }
350
iterate(void)351 ProgramSeparableCase::IterateResult ProgramSeparableCase::iterate (void)
352 {
353 const string vtxTemplate = "${GLSL_VERSION_DECL}\n"
354 "out highp vec4 v_color;\n"
355 // NOTE that core profile requires the gl_PerVertex block to be redeclared
356 // in case a separable program is enabled.
357 "${GL_POSITION_REDECL}\n"
358 "void main()\n"
359 "{\n"
360 " gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n"
361 " v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n"
362 "}\n";
363 const string fragTemplate = "${GLSL_VERSION_DECL}\n"
364 "in highp vec4 v_color;\n"
365 "layout(location=0) out highp vec4 o_color;\n"
366 "void main()\n"
367 "{\n"
368 " o_color = v_color;\n"
369 "}\n";
370
371 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
372 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
373 glu::Shader vtxShader (m_context.getRenderContext(), glu::SHADERTYPE_VERTEX);
374 glu::Shader frgShader (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
375
376 const std::string vStr = specializeShader(m_context, vtxTemplate.c_str());
377 const std::string fStr = specializeShader(m_context, fragTemplate.c_str());
378 const char* const vtxSourcePtr = vStr.c_str();
379 const char* const fragSourcePtr = fStr.c_str();
380
381 vtxShader.setSources(1, &vtxSourcePtr, DE_NULL);
382 frgShader.setSources(1, &fragSourcePtr, DE_NULL);
383
384 vtxShader.compile();
385 frgShader.compile();
386
387 {
388 const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxShader", "Vertex shader");
389 m_testCtx.getLog() << vtxShader;
390 }
391
392 {
393 const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgShader", "Fragment shader");
394 m_testCtx.getLog() << frgShader;
395 }
396
397 TCU_CHECK_MSG(vtxShader.getCompileStatus() && frgShader.getCompileStatus(), "failed to build shaders");
398
399 gl.enableLogging(true);
400
401 {
402 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial");
403 glu::Program program (m_context.getRenderContext());
404
405 verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
406 }
407
408 {
409 const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetFalse", "SetFalse");
410 glu::Program program (m_context.getRenderContext());
411 int linkStatus = 0;
412
413 gl.glAttachShader(program.getProgram(), vtxShader.getShader());
414 gl.glAttachShader(program.getProgram(), frgShader.getShader());
415 gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
416 gl.glLinkProgram(program.getProgram());
417 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
418
419 gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
420 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
421
422 gl.glDetachShader(program.getProgram(), vtxShader.getShader());
423 gl.glDetachShader(program.getProgram(), frgShader.getShader());
424
425 TCU_CHECK_MSG(linkStatus == GL_TRUE, "failed to link program");
426
427 verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
428 }
429
430 {
431 const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetTrue", "SetTrue");
432 glu::Program program (m_context.getRenderContext());
433 int linkStatus = 0;
434
435 gl.glAttachShader(program.getProgram(), vtxShader.getShader());
436 gl.glAttachShader(program.getProgram(), frgShader.getShader());
437 gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
438 gl.glLinkProgram(program.getProgram());
439 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
440
441 gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
442 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
443
444 gl.glDetachShader(program.getProgram(), vtxShader.getShader());
445 gl.glDetachShader(program.getProgram(), frgShader.getShader());
446
447 TCU_CHECK_MSG(linkStatus == GL_TRUE, "failed to link program");
448
449 verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE, m_verifier);
450 }
451
452 result.setTestContextResult(m_testCtx);
453 return STOP;
454 }
455
456 class ComputeWorkGroupSizeCase : public TestCase
457 {
458 public:
459 ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc);
460 IterateResult iterate (void);
461
462 private:
463 const QueryType m_verifier;
464 };
465
ComputeWorkGroupSizeCase(Context & context,QueryType verifier,const char * name,const char * desc)466 ComputeWorkGroupSizeCase::ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc)
467 : TestCase (context, name, desc)
468 , m_verifier (verifier)
469 {
470 }
471
iterate(void)472 ComputeWorkGroupSizeCase::IterateResult ComputeWorkGroupSizeCase::iterate (void)
473 {
474 static const char* const s_computeTemplate1D = "${GLSL_VERSION_DECL}\n"
475 "layout (local_size_x = 3) in;\n"
476 "layout(binding = 0) buffer Output\n"
477 "{\n"
478 " highp float val;\n"
479 "} sb_out;\n"
480 "\n"
481 "void main (void)\n"
482 "{\n"
483 " sb_out.val = 1.0;\n"
484 "}\n";
485 static const char* const s_computeTemplate2D = "${GLSL_VERSION_DECL}\n"
486 "layout (local_size_x = 3, local_size_y = 2) in;\n"
487 "layout(binding = 0) buffer Output\n"
488 "{\n"
489 " highp float val;\n"
490 "} sb_out;\n"
491 "\n"
492 "void main (void)\n"
493 "{\n"
494 " sb_out.val = 1.0;\n"
495 "}\n";
496 static const char* const s_computeTemplate3D = "${GLSL_VERSION_DECL}\n"
497 "layout (local_size_x = 3, local_size_y = 2, local_size_z = 4) in;\n"
498 "layout(binding = 0) buffer Output\n"
499 "{\n"
500 " highp float val;\n"
501 "} sb_out;\n"
502 "\n"
503 "void main (void)\n"
504 "{\n"
505 " sb_out.val = 1.0;\n"
506 "}\n";
507
508 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
509 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
510
511 gl.enableLogging(true);
512
513 {
514 const tcu::ScopedLogSection section (m_testCtx.getLog(), "OneDimensional", "1D");
515 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate1D)));
516
517 m_testCtx.getLog() << program;
518
519 TCU_CHECK_MSG(program.isOk(), "failed to build program");
520
521 verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 1, 1), m_verifier);
522 }
523
524 {
525 const tcu::ScopedLogSection section (m_testCtx.getLog(), "TwoDimensional", "2D");
526 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate2D)));
527
528 m_testCtx.getLog() << program;
529
530 TCU_CHECK_MSG(program.isOk(), "failed to build program");
531
532 verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 1), m_verifier);
533 }
534
535 {
536 const tcu::ScopedLogSection section (m_testCtx.getLog(), "TreeDimensional", "3D");
537 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate3D)));
538
539 m_testCtx.getLog() << program;
540
541 TCU_CHECK_MSG(program.isOk(), "failed to build program");
542
543 verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 4), m_verifier);
544 }
545
546 result.setTestContextResult(m_testCtx);
547 return STOP;
548 }
549
550 class ActiveAtomicCounterBuffersCase : public TestCase
551 {
552 public:
553 ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc);
554 IterateResult iterate (void);
555
556 private:
557 const QueryType m_verifier;
558 };
559
ActiveAtomicCounterBuffersCase(Context & context,QueryType verifier,const char * name,const char * desc)560 ActiveAtomicCounterBuffersCase::ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc)
561 : TestCase (context, name, desc)
562 , m_verifier (verifier)
563 {
564 }
565
iterate(void)566 ActiveAtomicCounterBuffersCase::IterateResult ActiveAtomicCounterBuffersCase::iterate (void)
567 {
568 static const char* const s_computeTemplate0 = "${GLSL_VERSION_DECL}\n"
569 "layout (local_size_x = 3) in;\n"
570 "layout(binding = 0) buffer Output\n"
571 "{\n"
572 " highp float val;\n"
573 "} sb_out;\n"
574 "\n"
575 "void main (void)\n"
576 "{\n"
577 " sb_out.val = 1.0;\n"
578 "}\n";
579 static const char* const s_computeTemplate1 = "${GLSL_VERSION_DECL}\n"
580 "layout (local_size_x = 3) in;\n"
581 "layout(binding = 0) uniform highp atomic_uint u_counters[2];\n"
582 "layout(binding = 0) buffer Output\n"
583 "{\n"
584 " highp float val;\n"
585 "} sb_out;\n"
586 "\n"
587 "void main (void)\n"
588 "{\n"
589 " sb_out.val = float(atomicCounterIncrement(u_counters[0])) + float(atomicCounterIncrement(u_counters[1]));\n"
590 "}\n";
591
592 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
593 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: ");
594
595 gl.enableLogging(true);
596
597 {
598 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Initial", "Initial");
599 glu::Program program (m_context.getRenderContext());
600
601 verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
602 }
603
604 {
605 const tcu::ScopedLogSection section (m_testCtx.getLog(), "NoBuffers", "No buffers");
606 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate0)));
607
608 m_testCtx.getLog() << program;
609
610 TCU_CHECK_MSG(program.isOk(), "failed to build program");
611
612 verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
613 }
614
615 {
616 const tcu::ScopedLogSection section (m_testCtx.getLog(), "OneBuffer", "One buffer");
617 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate1)));
618
619 m_testCtx.getLog() << program;
620
621 TCU_CHECK_MSG(program.isOk(), "failed to build program");
622
623 verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 1, m_verifier);
624 }
625
626 result.setTestContextResult(m_testCtx);
627 return STOP;
628 }
629
630 class ProgramLogCase : public TestCase
631 {
632 public:
633 enum BuildErrorType
634 {
635 BUILDERROR_VERTEX_FRAGMENT = 0,
636 BUILDERROR_COMPUTE,
637 BUILDERROR_GEOMETRY,
638 BUILDERROR_TESSELLATION,
639 };
640
641 ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType);
642
643 private:
644 void init (void);
645 IterateResult iterate (void);
646 glu::ProgramSources getProgramSources (void) const;
647
648 const BuildErrorType m_buildErrorType;
649 };
650
ProgramLogCase(Context & ctx,const char * name,const char * desc,BuildErrorType errorType)651 ProgramLogCase::ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType)
652 : TestCase (ctx, name, desc)
653 , m_buildErrorType (errorType)
654 {
655 }
656
init(void)657 void ProgramLogCase::init (void)
658 {
659 const bool supportsES32orGL45 = checkSupport(m_context);
660
661 switch (m_buildErrorType)
662 {
663 case BUILDERROR_VERTEX_FRAGMENT:
664 case BUILDERROR_COMPUTE:
665 break;
666
667 case BUILDERROR_GEOMETRY:
668 if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
669 TCU_THROW(NotSupportedError, "Test requires GL_EXT_geometry_shader extension");
670 break;
671
672 case BUILDERROR_TESSELLATION:
673 if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
674 TCU_THROW(NotSupportedError, "Test requires GL_EXT_tessellation_shader extension");
675 break;
676
677 default:
678 DE_ASSERT(false);
679 break;
680 }
681 }
682
iterate(void)683 ProgramLogCase::IterateResult ProgramLogCase::iterate (void)
684 {
685 using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
686
687 tcu::ResultCollector result (m_testCtx.getLog());
688 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
689 glu::ShaderProgram program (m_context.getRenderContext(), getProgramSources());
690 StateQueryMemoryWriteGuard<glw::GLint> logLen;
691
692 gl.enableLogging(true);
693
694 m_testCtx.getLog() << tcu::TestLog::Message << "Trying to link a broken program." << tcu::TestLog::EndMessage;
695
696 gl.glGetProgramiv(program.getProgram(), GL_INFO_LOG_LENGTH, &logLen);
697 logLen.verifyValidity(result);
698
699 if (logLen.verifyValidity(result))
700 verifyInfoLogQuery(result, gl, logLen, program.getProgram(), &glu::CallLogWrapper::glGetProgramInfoLog, "glGetProgramInfoLog");
701
702 result.setTestContextResult(m_testCtx);
703 return STOP;
704 }
705
getProgramSources(void) const706 glu::ProgramSources ProgramLogCase::getProgramSources (void) const
707 {
708 const char* const vertexTemplate1 = "${GLSL_VERSION_DECL}\n"
709 "in highp vec4 a_pos;\n"
710 "uniform highp vec4 u_uniform;\n"
711 "void main()\n"
712 "{\n"
713 " gl_Position = a_pos + u_uniform;\n"
714 "}\n";
715 const char* const vertexTemplate2 = "${GLSL_VERSION_DECL}\n"
716 "in highp vec4 a_pos;\n"
717 "void main()\n"
718 "{\n"
719 " gl_Position = a_pos;\n"
720 "}\n";
721 const char* const fragmentTemplate1 = "${GLSL_VERSION_DECL}\n"
722 "in highp vec4 v_missingVar;\n"
723 "uniform highp int u_uniform;\n"
724 "layout(location = 0) out mediump vec4 fragColor;\n"
725 "void main()\n"
726 "{\n"
727 " fragColor = v_missingVar + vec4(float(u_uniform));\n"
728 "}\n";
729
730 const char* const fragmentTemplate2 = "${GLSL_VERSION_DECL}\n"
731 "layout(location = 0) out mediump vec4 fragColor;\n"
732 "void main()\n"
733 "{\n"
734 " fragColor = vec4(1.0);\n"
735 "}\n";
736 const char* const computeTemplate1 = "${GLSL_VERSION_DECL}\n"
737 "layout (binding = 0) buffer IOBuffer { highp float buf_var; };\n"
738 "uniform highp vec4 u_uniform;\n"
739 "void main()\n"
740 "{\n"
741 " buf_var = u_uniform.x;\n"
742 "}\n";
743 const char* const geometryTemplate1 = "${GLSL_VERSION_DECL}\n"
744 "${GEOMETRY_SHADER_REQUIRE}\n"
745 "layout(triangles) in;\n"
746 "layout(max_vertices=1, points) out;\n"
747 "in highp vec4 v_missingVar[];\n"
748 "uniform highp int u_uniform;\n"
749 "void main()\n"
750 "{\n"
751 " gl_Position = gl_in[0].gl_Position + v_missingVar[2] + vec4(float(u_uniform));\n"
752 " EmitVertex();\n"
753 "}\n";
754 const char* const tessCtrlTemplate1 = "${GLSL_VERSION_DECL}\n"
755 "${TESSELLATION_SHADER_REQUIRE}\n"
756 "layout(vertices=2) out;"
757 "patch out highp vec2 vp_var;\n"
758 "void main()\n"
759 "{\n"
760 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position\n"
761 " gl_TessLevelOuter[0] = 0.8;\n"
762 " gl_TessLevelOuter[1] = 0.8;\n"
763 " if (gl_InvocationID == 0)\n"
764 " vp_var = gl_in[gl_InvocationID].gl_Position.xy;\n"
765 "}\n";
766 const char* const tessEvalTemplate1 = "${GLSL_VERSION_DECL}\n"
767 "${TESSELLATION_SHADER_REQUIRE}\n"
768 "layout(isolines) in;"
769 "in highp float vp_var[];\n"
770 "void main()\n"
771 "{\n"
772 " gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(vp_var[1]);\n"
773 "}\n";
774
775 switch (m_buildErrorType)
776 {
777 case BUILDERROR_VERTEX_FRAGMENT:
778 return glu::ProgramSources()
779 << glu::VertexSource(specializeShader(m_context, vertexTemplate1))
780 << glu::FragmentSource(specializeShader(m_context, fragmentTemplate1));
781
782 case BUILDERROR_COMPUTE:
783 return glu::ProgramSources()
784 << glu::ComputeSource(specializeShader(m_context, computeTemplate1));
785
786 case BUILDERROR_GEOMETRY:
787 return glu::ProgramSources()
788 << glu::VertexSource(specializeShader(m_context, vertexTemplate1))
789 << glu::GeometrySource(specializeShader(m_context, geometryTemplate1))
790 << glu::FragmentSource(specializeShader(m_context, fragmentTemplate2));
791
792 case BUILDERROR_TESSELLATION:
793 return glu::ProgramSources()
794 << glu::VertexSource(specializeShader(m_context, vertexTemplate2))
795 << glu::TessellationControlSource(specializeShader(m_context, tessCtrlTemplate1))
796 << glu::TessellationEvaluationSource(specializeShader(m_context, tessEvalTemplate1))
797 << glu::FragmentSource(specializeShader(m_context, fragmentTemplate2));
798
799 default:
800 DE_ASSERT(false);
801 return glu::ProgramSources();
802 }
803 }
804
805 } // anonymous
806
ProgramStateQueryTests(Context & context)807 ProgramStateQueryTests::ProgramStateQueryTests (Context& context)
808 : TestCaseGroup(context, "program", "Program State Query tests")
809 {
810 }
811
~ProgramStateQueryTests(void)812 ProgramStateQueryTests::~ProgramStateQueryTests (void)
813 {
814 }
815
init(void)816 void ProgramStateQueryTests::init (void)
817 {
818 static const QueryType intVerifiers[] =
819 {
820 QUERY_PROGRAM_INTEGER,
821 };
822 static const QueryType intVec3Verifiers[] =
823 {
824 QUERY_PROGRAM_INTEGER_VEC3,
825 };
826
827 #define FOR_EACH_INT_VERIFIER(X) \
828 do { \
829 for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVerifiers); ++verifierNdx) \
830 { \
831 const char* verifierSuffix = getVerifierSuffix(intVerifiers[verifierNdx]); \
832 const QueryType verifier = intVerifiers[verifierNdx]; \
833 this->addChild(X); \
834 } \
835 } while (0)
836
837 #define FOR_EACH_VEC_VERIFIER(X) \
838 do { \
839 for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVec3Verifiers); ++verifierNdx) \
840 { \
841 const char* verifierSuffix = getVerifierSuffix(intVec3Verifiers[verifierNdx]); \
842 const QueryType verifier = intVec3Verifiers[verifierNdx]; \
843 this->addChild(X); \
844 } \
845 } while (0)
846
847 FOR_EACH_INT_VERIFIER(new ProgramSeparableCase (m_context, verifier, (std::string("program_separable_") + verifierSuffix).c_str(), "Test PROGRAM_SEPARABLE"));
848 FOR_EACH_VEC_VERIFIER(new ComputeWorkGroupSizeCase (m_context, verifier, (std::string("compute_work_group_size_") + verifierSuffix).c_str(), "Test COMPUTE_WORK_GROUP_SIZE"));
849 FOR_EACH_INT_VERIFIER(new ActiveAtomicCounterBuffersCase (m_context, verifier, (std::string("active_atomic_counter_buffers_") + verifierSuffix).c_str(), "Test ACTIVE_ATOMIC_COUNTER_BUFFERS"));
850 FOR_EACH_INT_VERIFIER(new GeometryShaderCase (m_context, verifier, (std::string("geometry_shader_state_") + verifierSuffix).c_str(), "Test Geometry Shader State"));
851 FOR_EACH_INT_VERIFIER(new TessellationShaderCase (m_context, verifier, (std::string("tesselation_shader_state_") + verifierSuffix).c_str(), "Test Tesselation Shader State"));
852
853 #undef FOR_EACH_INT_VERIFIER
854 #undef FOR_EACH_VEC_VERIFIER
855
856 // program info log tests
857 // \note, there exists similar tests in gles3 module. However, the gles31 could use a different
858 // shader compiler with different INFO_LOG bugs.
859 {
860 static const struct
861 {
862 const char* caseName;
863 ProgramLogCase::BuildErrorType caseType;
864 } shaderTypes[] =
865 {
866 { "info_log_vertex_fragment_link_fail", ProgramLogCase::BUILDERROR_VERTEX_FRAGMENT },
867 { "info_log_compute_link_fail", ProgramLogCase::BUILDERROR_COMPUTE },
868 { "info_log_geometry_link_fail", ProgramLogCase::BUILDERROR_GEOMETRY },
869 { "info_log_tessellation_link_fail", ProgramLogCase::BUILDERROR_TESSELLATION },
870 };
871
872 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
873 addChild(new ProgramLogCase(m_context, shaderTypes[ndx].caseName, "", shaderTypes[ndx].caseType));
874 }
875 }
876
877 } // Functional
878 } // gles31
879 } // deqp
880