Merge vk-gl-cts/opengl-es-cts-3.2.4 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcShaderNegativeTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23
24 /*!
25  * \file glcShaderNegativeTests.cpp
26  * \brief Negative tests for shaders and interface matching.
27  */ /*-------------------------------------------------------------------*/
28
29 #include "glcShaderNegativeTests.hpp"
30 #include "deString.h"
31 #include "deStringUtil.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluShaderProgram.hpp"
34 #include "glw.h"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuTestLog.hpp"
37
38 namespace deqp
39 {
40
41 using tcu::TestLog;
42 using namespace glu;
43
44 struct ShaderVariants
45 {
46         GLSLVersion minimum_supported_version;
47         const char* vertex_precision;
48         const char* vertex_body;
49         const char* frag_precision;
50         const char* frag_body;
51         bool            should_link;
52 };
53
54 class ShaderUniformInitializeGlobalCase : public TestCase
55 {
56 public:
57         ShaderUniformInitializeGlobalCase(Context& context, const char* name, const char* description,
58                                                                           GLSLVersion glslVersion)
59                 : TestCase(context, name, description), m_glslVersion(glslVersion)
60         {
61         }
62
63         ~ShaderUniformInitializeGlobalCase()
64         {
65                 // empty
66         }
67
68         IterateResult iterate()
69         {
70                 qpTestResult result = QP_TEST_RESULT_PASS;
71
72                 static const char vertex_source_template[] =
73                         "${VERSION_DECL}\n"
74                         "precision mediump float;\n"
75                         "uniform vec4 nonconstantexpression;\n"
76                         "vec4 globalconstant0 = vec4(1.0, 1.0, 1.0, 1.0);\n"
77                         "vec4 globalconstant1 = nonconstantexpression;\n"
78                         "\n"
79                         "void main(void) { gl_Position = globalconstant0+globalconstant1; }\n";
80                 static const char fragment_source_template[] = "${VERSION_DECL}\n"
81                                                                                                            "precision mediump float;\n"
82                                                                                                            "uniform vec4 nonconstantexpression;\n"
83                                                                                                            "vec4 globalconstant0 = vec4(1.0, 1.0, 1.0, 1.0);\n"
84                                                                                                            "vec4 globalconstant1 = nonconstantexpression;\n"
85                                                                                                            "\n"
86                                                                                                            "void main(void) { }\n";
87
88                 std::map<std::string, std::string> args;
89                 args["VERSION_DECL"] = getGLSLVersionDeclaration(m_glslVersion);
90
91                 std::string vertex_code   = tcu::StringTemplate(vertex_source_template).specialize(args);
92                 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
93
94                 // Setup program.
95                 ShaderProgram program(m_context.getRenderContext(),
96                                                           makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
97
98                 // GLSL ES does not allow initialization of global variables with non-constant
99                 // expressions, but GLSL does.
100                 // Check that either compilation or linking fails for ES, and that everything
101                 // succeeds for GL.
102                 bool vertexOk   = program.getShaderInfo(SHADERTYPE_VERTEX).compileOk;
103                 bool fragmentOk = program.getShaderInfo(SHADERTYPE_FRAGMENT).compileOk;
104                 bool linkOk             = program.getProgramInfo().linkOk;
105
106                 if (glslVersionIsES(m_glslVersion))
107                 {
108                         if (vertexOk && fragmentOk && linkOk)
109                                 result = QP_TEST_RESULT_FAIL;
110                 }
111                 else
112                 {
113                         if (!vertexOk && !fragmentOk && !linkOk)
114                                 result = QP_TEST_RESULT_FAIL;
115                 }
116
117                 m_testCtx.setTestResult(result, qpGetTestResultName(result));
118
119                 return STOP;
120         }
121
122 protected:
123         GLSLVersion m_glslVersion;
124 };
125
126 class ShaderUniformPrecisionLinkCase : public TestCase
127 {
128 public:
129         ShaderUniformPrecisionLinkCase(Context& context, const char* name, const char* description,
130                                                                    const ShaderVariants* shaderVariants, unsigned int shaderVariantsCount,
131                                                                    GLSLVersion glslVersion)
132                 : TestCase(context, name, description)
133                 , m_glslVersion(glslVersion)
134                 , m_shaderVariants(shaderVariants)
135                 , m_shaderVariantsCount(shaderVariantsCount)
136         {
137         }
138
139         ~ShaderUniformPrecisionLinkCase()
140         {
141                 // empty
142         }
143
144         IterateResult iterate()
145         {
146                 TestLog&         log    = m_testCtx.getLog();
147                 qpTestResult result = QP_TEST_RESULT_PASS;
148
149                 static const char vertex_source_template[] = "${VERSION_DECL}\n"
150                                                                                                          "uniform ${PREC_QUALIFIER} vec4 value;\n"
151                                                                                                          "\n"
152                                                                                                          "void main(void) { ${BODY} }\n";
153
154                 static const char fragment_source_template[] = "${VERSION_DECL}\n"
155                                                                                                            "out highp vec4 result;\n"
156                                                                                                            "uniform ${PREC_QUALIFIER} vec4 value;\n"
157                                                                                                            "\n"
158                                                                                                            "void main(void) { ${BODY} }\n";
159
160                 for (unsigned int i = 0; i < m_shaderVariantsCount; i++)
161                 {
162                         std::map<std::string, std::string> args;
163
164                         if (m_glslVersion <= m_shaderVariants[i].minimum_supported_version)
165                         {
166                                 continue;
167                         }
168
169                         args["VERSION_DECL"]   = getGLSLVersionDeclaration(m_glslVersion);
170                         args["PREC_QUALIFIER"] = m_shaderVariants[i].vertex_precision;
171                         args["BODY"]               = m_shaderVariants[i].vertex_body;
172                         std::string vcode         = tcu::StringTemplate(vertex_source_template).specialize(args);
173
174                         args["PREC_QUALIFIER"] = m_shaderVariants[i].frag_precision;
175                         args["BODY"]               = m_shaderVariants[i].frag_body;
176                         std::string fcode         = tcu::StringTemplate(fragment_source_template).specialize(args);
177
178                         // Setup program.
179                         ShaderProgram program(m_context.getRenderContext(), makeVtxFragSources(vcode.c_str(), fcode.c_str()));
180
181                         // Check that compile/link results are what we expect.
182                         bool            vertexOk   = program.getShaderInfo(SHADERTYPE_VERTEX).compileOk;
183                         bool            fragmentOk = program.getShaderInfo(SHADERTYPE_FRAGMENT).compileOk;
184                         bool            linkOk   = program.getProgramInfo().linkOk;
185                         const char* failReason = DE_NULL;
186
187                         if (!vertexOk || !fragmentOk)
188                         {
189                                 failReason = "expected shaders to compile, but failed.";
190                         }
191                         else if (m_shaderVariants[i].should_link && !linkOk)
192                         {
193                                 failReason = "expected shaders to link, but failed.";
194                         }
195                         else if (!m_shaderVariants[i].should_link && linkOk)
196                         {
197                                 failReason = "expected shaders to fail linking, but succeeded.";
198                         }
199
200                         if (failReason != DE_NULL)
201                         {
202                                 log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage;
203                                 result = QP_TEST_RESULT_FAIL;
204                         }
205                 }
206
207                 m_testCtx.setTestResult(result, qpGetTestResultName(result));
208
209                 return STOP;
210         }
211
212 protected:
213         GLSLVersion                       m_glslVersion;
214         const ShaderVariants* m_shaderVariants;
215         unsigned int              m_shaderVariantsCount;
216 };
217
218 class ShaderConstantSequenceExpressionCase : public TestCase
219 {
220 public:
221         ShaderConstantSequenceExpressionCase(Context& context, const char* name, const char* description,
222                                                                                  GLSLVersion glslVersion)
223                 : TestCase(context, name, description), m_glslVersion(glslVersion)
224         {
225         }
226
227         ~ShaderConstantSequenceExpressionCase()
228         {
229                 // empty
230         }
231
232         IterateResult iterate()
233         {
234                 qpTestResult result = QP_TEST_RESULT_PASS;
235
236                 static const char vertex_source_template[] = "${VERSION_DECL}\n"
237                                                                                                          "precision mediump float;\n"
238                                                                                                          "const int test = (1, 2);\n"
239                                                                                                          "\n"
240                                                                                                          "void main(void) { gl_Position = vec4(test); }\n";
241
242                 static const char fragment_source_template[] = "${VERSION_DECL}\n"
243                                                                                                            "precision mediump float;\n"
244                                                                                                            "\n"
245                                                                                                            "void main(void) { }\n";
246
247                 std::map<std::string, std::string> args;
248                 args["VERSION_DECL"] = getGLSLVersionDeclaration(m_glslVersion);
249
250                 std::string vertex_code   = tcu::StringTemplate(vertex_source_template).specialize(args);
251                 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
252
253                 // Setup program.
254                 ShaderProgram program(m_context.getRenderContext(),
255                                                           makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
256
257                 // GLSL does not allow the sequence operator in a constant expression
258                 // Check that either compilation or linking fails
259                 bool vertexOk   = program.getShaderInfo(SHADERTYPE_VERTEX).compileOk;
260                 bool fragmentOk = program.getShaderInfo(SHADERTYPE_FRAGMENT).compileOk;
261                 bool linkOk             = program.getProgramInfo().linkOk;
262
263                 bool run_test_es          = (glslVersionIsES(m_glslVersion) && m_glslVersion > GLSL_VERSION_100_ES);
264                 bool run_test_desktop = (m_glslVersion > GLSL_VERSION_420);
265                 if (run_test_es || run_test_desktop)
266                 {
267                         if (vertexOk && fragmentOk && linkOk)
268                                 result = QP_TEST_RESULT_FAIL;
269                 }
270
271                 m_testCtx.setTestResult(result, qpGetTestResultName(result));
272
273                 return STOP;
274         }
275
276 protected:
277         GLSLVersion m_glslVersion;
278 };
279
280 ShaderNegativeTests::ShaderNegativeTests(Context& context, GLSLVersion glslVersion)
281         : TestCaseGroup(context, "negative", "Shader Negative tests"), m_glslVersion(glslVersion)
282 {
283         // empty
284 }
285
286 ShaderNegativeTests::~ShaderNegativeTests()
287 {
288         // empty
289 }
290
291 void ShaderNegativeTests::init(void)
292 {
293         addChild(new ShaderUniformInitializeGlobalCase(
294                 m_context, "initialize", "Verify initialization of globals with non-constant expressions fails on ES.",
295                 m_glslVersion));
296
297         addChild(new ShaderConstantSequenceExpressionCase(
298                 m_context, "constant_sequence", "Verify that the sequence operator cannot be used as a constant expression.",
299                 m_glslVersion));
300
301         if (isGLSLVersionSupported(m_context.getRenderContext().getType(), GLSL_VERSION_320_ES))
302         {
303                 static const ShaderVariants used_variables_variants[] = {
304                         /* These variants should pass since the precision qualifiers match.
305                          * These variants require highp to be supported, so will not be run for GLSL_VERSION_100_ES.
306                          */
307                         { GLSL_VERSION_300_ES, "", "gl_Position = vec4(1.0) + value;", "highp", "result = value;", true },
308                         { GLSL_VERSION_300_ES, "highp", "gl_Position = vec4(1.0) + value;", "highp", "result = value;", true },
309
310                         /* Use highp in vertex shaders, mediump in fragment shaders. Check variations as above.
311                          * These variants should fail since the precision qualifiers do not match, and matching is done
312                          * based on declaration - independent of static use.
313                          */
314                         { GLSL_VERSION_100_ES, "", "gl_Position = vec4(1.0) + value;", "mediump", "result = value;", false },
315                         { GLSL_VERSION_100_ES, "highp", "gl_Position = vec4(1.0) + value;", "mediump", "result = value;", false },
316                 };
317                 unsigned int used_variables_variants_count = sizeof(used_variables_variants) / sizeof(ShaderVariants);
318
319                 static const ShaderVariants unused_variables_variants[] = {
320                         /* These variants should pass since the precision qualifiers match.
321                          * These variants require highp to be supported, so will not be run for GLSL_VERSION_100_ES.
322                          */
323                         { GLSL_VERSION_300_ES, "", "gl_Position = vec4(1.0);", "highp", "result = value;", true },
324                         { GLSL_VERSION_300_ES, "highp", "gl_Position = vec4(1.0);", "highp", "result = value;", true },
325
326                         /* Use highp in vertex shaders, mediump in fragment shaders. Check variations as above.
327                          * These variants should fail since the precision qualifiers do not match, and matching is done
328                          * based on declaration - independent of static use.
329                          */
330                         { GLSL_VERSION_100_ES, "", "gl_Position = vec4(1.0);", "mediump", "result = value;", false },
331                         { GLSL_VERSION_100_ES, "highp", "gl_Position = vec4(1.0);", "mediump", "result = value;", false },
332
333                         /* Use mediump in vertex shaders, highp in fragment shaders. Check variations as above.
334                          * These variations should fail for the same reason as above.
335                          */
336                         { GLSL_VERSION_300_ES, "mediump", "gl_Position = vec4(1.0);", "highp", "result = vec4(1.0);", false },
337                         { GLSL_VERSION_300_ES, "mediump", "gl_Position = vec4(1.0);", "highp", "result = value;", false },
338                 };
339                 unsigned int unused_variables_variants_count = sizeof(unused_variables_variants) / sizeof(ShaderVariants);
340
341                 addChild(new ShaderUniformPrecisionLinkCase(
342                         m_context, "used_uniform_precision_matching",
343                         "Verify that linking fails if precision qualifiers on default uniform do not match",
344                         used_variables_variants, used_variables_variants_count, m_glslVersion));
345
346                 addChild(new ShaderUniformPrecisionLinkCase(
347                         m_context, "unused_uniform_precision_matching",
348                         "Verify that linking fails if precision qualifiers on default not used uniform do not match",
349                         unused_variables_variants, unused_variables_variants_count, m_glslVersion));
350         }
351 }
352
353 } // deqp