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