xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fProgramStateQueryTests.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 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