Merge "Fix error mask generation in checkLineContinuity" into nougat-cts-dev am:...
[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
43 class ShaderUniformInitializeGlobalCase : public TestCase
44 {
45 public:
46         ShaderUniformInitializeGlobalCase(Context& context, const char* name, const char* description,
47                                                                           glu::GLSLVersion glslVersion)
48                 : TestCase(context, name, description), m_glslVersion(glslVersion)
49         {
50         }
51
52         ~ShaderUniformInitializeGlobalCase()
53         {
54                 // empty
55         }
56
57         IterateResult iterate()
58         {
59                 qpTestResult result = QP_TEST_RESULT_PASS;
60
61                 static const char vertex_source_template[] =
62                         "${VERSION_DECL}\n"
63                         "precision mediump float;\n"
64                         "uniform vec4 nonconstantexpression;\n"
65                         "vec4 globalconstant0 = vec4(1.0, 1.0, 1.0, 1.0);\n"
66                         "vec4 globalconstant1 = nonconstantexpression;\n"
67                         "\n"
68                         "void main(void) { gl_Position = globalconstant0+globalconstant1; }\n";
69                 static const char fragment_source_template[] = "${VERSION_DECL}\n"
70                                                                                                            "precision mediump float;\n"
71                                                                                                            "uniform vec4 nonconstantexpression;\n"
72                                                                                                            "vec4 globalconstant0 = vec4(1.0, 1.0, 1.0, 1.0);\n"
73                                                                                                            "vec4 globalconstant1 = nonconstantexpression;\n"
74                                                                                                            "\n"
75                                                                                                            "void main(void) { }\n";
76
77                 std::map<std::string, std::string> args;
78                 args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(m_glslVersion);
79
80                 std::string vertex_code   = tcu::StringTemplate(vertex_source_template).specialize(args);
81                 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
82
83                 // Setup program.
84                 glu::ShaderProgram program(m_context.getRenderContext(),
85                                                                    glu::makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
86
87                 // GLSL ES does not allow initialization of global variables with non-constant
88                 // expressions, but GLSL does.
89                 // Check that either compilation or linking fails for ES, and that everything
90                 // succeeds for GL.
91                 bool vertexOk   = program.getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk;
92                 bool fragmentOk = program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk;
93                 bool linkOk             = program.getProgramInfo().linkOk;
94
95                 if (glu::glslVersionIsES(m_glslVersion))
96                 {
97                         if (vertexOk && fragmentOk && linkOk)
98                                 result = QP_TEST_RESULT_FAIL;
99                 }
100                 else
101                 {
102                         if (!vertexOk && !fragmentOk && !linkOk)
103                                 result = QP_TEST_RESULT_FAIL;
104                 }
105
106                 m_testCtx.setTestResult(result, qpGetTestResultName(result));
107
108                 return STOP;
109         }
110
111 protected:
112         glu::GLSLVersion m_glslVersion;
113 };
114
115 class ShaderUniformPrecisionLinkCase : public TestCase
116 {
117 public:
118         ShaderUniformPrecisionLinkCase(Context& context, const char* name, const char* description,
119                                                                    glu::GLSLVersion glslVersion)
120                 : TestCase(context, name, description), m_glslVersion(glslVersion)
121         {
122         }
123
124         ~ShaderUniformPrecisionLinkCase()
125         {
126                 // empty
127         }
128
129         IterateResult iterate()
130         {
131                 TestLog&         log    = m_testCtx.getLog();
132                 qpTestResult result = QP_TEST_RESULT_PASS;
133
134                 static const char vertex_source_template[] = "${VERSION_DECL}\n"
135                                                                                                          "uniform ${PREC_QUALIFIER} vec4 value;\n"
136                                                                                                          "\n"
137                                                                                                          "void main(void) { ${BODY} }\n";
138
139                 static const char fragment_source_template[] = "${VERSION_DECL}\n"
140                                                                                                            "out highp vec4 result;\n"
141                                                                                                            "uniform ${PREC_QUALIFIER} vec4 value;\n"
142                                                                                                            "\n"
143                                                                                                            "void main(void) { ${BODY} }\n";
144
145                 static const struct
146                 {
147                         glu::GLSLVersion minimum_supported_version;
148                         const char*              vertex_precision;
149                         const char*              vertex_body;
150                         const char*              frag_precision;
151                         const char*              frag_body;
152                         bool                     should_link;
153                 } shader_variants[] = {
154                         /* Use highp on both stages. Check variations of:
155                          *  - of implicit and explicit precision qualifiers
156                          *  - used and unused variables
157                          * These variants should pass since the precision qualifiers match.
158                          *
159                          * These variants require highp to be supported, so will not be run for GLSL_VERSION_100_ES.
160                          */
161                         { glu::GLSL_VERSION_300_ES, "", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "highp", "result = value;",
162                           true },
163                         { glu::GLSL_VERSION_300_ES, "", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0) + value;", "highp",
164                           "result = value;", true },
165                         { glu::GLSL_VERSION_300_ES, "highp", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "highp", "result = value;",
166                           true },
167                         { glu::GLSL_VERSION_300_ES, "highp", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0) + value;", "highp",
168                           "result = value;", true },
169
170                         /* Use highp in vertex shaders, mediump in fragment shaders. Check variations as above.
171                          * These variants should fail since the precision qualifiers do not match, and matching is done
172                          * based on declaration - independent of static use.
173                          */
174                         { glu::GLSL_VERSION_100_ES, "", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "mediump", "result = value;",
175                           false },
176                         { glu::GLSL_VERSION_100_ES, "", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0) + value;", "mediump",
177                           "result = value;", false },
178                         { glu::GLSL_VERSION_100_ES, "highp", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "mediump",
179                           "result = value;", false },
180                         { glu::GLSL_VERSION_100_ES, "highp", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0) + value;", "mediump",
181                           "result = value;", false },
182
183                         /* Use mediump in vertex shaders, highp in fragment shaders. Check variations as above.
184                          * These variations should fail for the same reason as above.
185                          */
186                         { glu::GLSL_VERSION_300_ES, "mediump", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "highp",
187                           "result = vec4(1.0, 1.0, 1.0, 1.0);", false },
188                         { glu::GLSL_VERSION_300_ES, "mediump", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "highp",
189                           "result = value;", false },
190                 };
191
192                 for (int i = 0; i < DE_LENGTH_OF_ARRAY(shader_variants); i++)
193                 {
194                         std::map<std::string, std::string> args;
195
196                         if (m_glslVersion <= shader_variants[i].minimum_supported_version)
197                         {
198                                 continue;
199                         }
200
201                         args["VERSION_DECL"]   = glu::getGLSLVersionDeclaration(m_glslVersion);
202                         args["PREC_QUALIFIER"] = shader_variants[i].vertex_precision;
203                         args["BODY"]               = shader_variants[i].vertex_body;
204                         std::string vcode         = tcu::StringTemplate(vertex_source_template).specialize(args);
205
206                         args["PREC_QUALIFIER"] = shader_variants[i].frag_precision;
207                         args["BODY"]               = shader_variants[i].frag_body;
208                         std::string fcode         = tcu::StringTemplate(fragment_source_template).specialize(args);
209
210                         // Setup program.
211                         glu::ShaderProgram program(m_context.getRenderContext(),
212                                                                            glu::makeVtxFragSources(vcode.c_str(), fcode.c_str()));
213
214                         // Check that compile/link results are what we expect.
215                         bool            vertexOk   = program.getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk;
216                         bool            fragmentOk = program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk;
217                         bool            linkOk   = program.getProgramInfo().linkOk;
218                         const char* failReason = DE_NULL;
219
220                         if (!vertexOk || !fragmentOk)
221                         {
222                                 failReason = "expected shaders to compile, but failed.";
223                         }
224                         else if (shader_variants[i].should_link && !linkOk)
225                         {
226                                 failReason = "expected shaders to link, but failed.";
227                         }
228                         else if (!shader_variants[i].should_link && linkOk)
229                         {
230                                 failReason = "expected shaders to fail linking, but succeeded.";
231                         }
232
233                         if (failReason != DE_NULL)
234                         {
235                                 log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage;
236                                 result = QP_TEST_RESULT_FAIL;
237                         }
238                 }
239
240                 m_testCtx.setTestResult(result, qpGetTestResultName(result));
241
242                 return STOP;
243         }
244
245 protected:
246         glu::GLSLVersion m_glslVersion;
247 };
248
249 class ShaderConstantSequenceExpressionCase : public TestCase
250 {
251 public:
252         ShaderConstantSequenceExpressionCase(Context& context, const char* name, const char* description,
253                                                                                  glu::GLSLVersion glslVersion)
254                 : TestCase(context, name, description), m_glslVersion(glslVersion)
255         {
256         }
257
258         ~ShaderConstantSequenceExpressionCase()
259         {
260                 // empty
261         }
262
263         IterateResult iterate()
264         {
265                 qpTestResult result = QP_TEST_RESULT_PASS;
266
267                 static const char vertex_source_template[] = "${VERSION_DECL}\n"
268                                                                                                          "precision mediump float;\n"
269                                                                                                          "const int test = (1, 2);\n"
270                                                                                                          "\n"
271                                                                                                          "void main(void) { gl_Position = vec4(test); }\n";
272
273                 static const char fragment_source_template[] = "${VERSION_DECL}\n"
274                                                                                                            "precision mediump float;\n"
275                                                                                                            "\n"
276                                                                                                            "void main(void) { }\n";
277
278                 std::map<std::string, std::string> args;
279                 args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(m_glslVersion);
280
281                 std::string vertex_code   = tcu::StringTemplate(vertex_source_template).specialize(args);
282                 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
283
284                 // Setup program.
285                 glu::ShaderProgram program(m_context.getRenderContext(),
286                                                                    glu::makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
287
288                 // GLSL does not allow the sequence operator in a constant expression
289                 // Check that either compilation or linking fails
290                 bool vertexOk   = program.getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk;
291                 bool fragmentOk = program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk;
292                 bool linkOk             = program.getProgramInfo().linkOk;
293
294                 bool run_test_es          = (glu::glslVersionIsES(m_glslVersion) && m_glslVersion > glu::GLSL_VERSION_100_ES);
295                 bool run_test_desktop = (m_glslVersion > glu::GLSL_VERSION_420);
296                 if (run_test_es || run_test_desktop)
297                 {
298                         if (vertexOk && fragmentOk && linkOk)
299                                 result = QP_TEST_RESULT_FAIL;
300                 }
301
302                 m_testCtx.setTestResult(result, qpGetTestResultName(result));
303
304                 return STOP;
305         }
306
307 protected:
308         glu::GLSLVersion m_glslVersion;
309 };
310
311 ShaderNegativeTests::ShaderNegativeTests(Context& context, glu::GLSLVersion glslVersion)
312         : TestCaseGroup(context, "negative", "Shader Negative tests"), m_glslVersion(glslVersion)
313 {
314         // empty
315 }
316
317 ShaderNegativeTests::~ShaderNegativeTests()
318 {
319         // empty
320 }
321
322 void ShaderNegativeTests::init(void)
323 {
324         addChild(new ShaderUniformInitializeGlobalCase(
325                 m_context, "initialize", "Verify initialization of globals with non-constant expressions fails on ES.",
326                 m_glslVersion));
327 #if 0
328         /*
329          * This test is disabled for now since not all existing implementations follow these rules
330          * and enforcing them now would break existing applications, which is unacceptable.
331          *
332          * See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13922 for further details.
333          */
334         addChild(new ShaderUniformPrecisionLinkCase(m_context, "uniform_precision_matching",
335                         "Verify that linking fails if precision qualifiers on default uniform do not match",
336                         m_glslVersion));
337 #endif
338         addChild(new ShaderConstantSequenceExpressionCase(
339                 m_context, "constant_sequence", "Verify that the sequence operator cannot be used as a constant expression.",
340                 m_glslVersion));
341 }
342
343 } // deqp