1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2015-2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 */ /*-------------------------------------------------------------------*/
25 * \file glcShaderNegativeTests.cpp
26 * \brief Negative tests for shaders and interface matching.
27 */ /*-------------------------------------------------------------------*/
29 #include "glcShaderNegativeTests.hpp"
31 #include "deStringUtil.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluShaderProgram.hpp"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuTestLog.hpp"
43 class ShaderUniformInitializeGlobalCase : public TestCase
46 ShaderUniformInitializeGlobalCase(Context& context, const char* name, const char* description,
47 glu::GLSLVersion glslVersion)
48 : TestCase(context, name, description), m_glslVersion(glslVersion)
52 ~ShaderUniformInitializeGlobalCase()
57 IterateResult iterate()
59 qpTestResult result = QP_TEST_RESULT_PASS;
61 static const char vertex_source_template[] =
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"
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"
75 "void main(void) { }\n";
77 std::map<std::string, std::string> args;
78 args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(m_glslVersion);
80 std::string vertex_code = tcu::StringTemplate(vertex_source_template).specialize(args);
81 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
84 glu::ShaderProgram program(m_context.getRenderContext(),
85 glu::makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
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
91 bool vertexOk = program.getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk;
92 bool fragmentOk = program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk;
93 bool linkOk = program.getProgramInfo().linkOk;
95 if (glu::glslVersionIsES(m_glslVersion))
97 if (vertexOk && fragmentOk && linkOk)
98 result = QP_TEST_RESULT_FAIL;
102 if (!vertexOk && !fragmentOk && !linkOk)
103 result = QP_TEST_RESULT_FAIL;
106 m_testCtx.setTestResult(result, qpGetTestResultName(result));
112 glu::GLSLVersion m_glslVersion;
115 class ShaderUniformPrecisionLinkCase : public TestCase
118 ShaderUniformPrecisionLinkCase(Context& context, const char* name, const char* description,
119 glu::GLSLVersion glslVersion)
120 : TestCase(context, name, description), m_glslVersion(glslVersion)
124 ~ShaderUniformPrecisionLinkCase()
129 IterateResult iterate()
131 TestLog& log = m_testCtx.getLog();
132 qpTestResult result = QP_TEST_RESULT_PASS;
134 static const char vertex_source_template[] = "${VERSION_DECL}\n"
135 "uniform ${PREC_QUALIFIER} vec4 value;\n"
137 "void main(void) { ${BODY} }\n";
139 static const char fragment_source_template[] = "${VERSION_DECL}\n"
140 "out highp vec4 result;\n"
141 "uniform ${PREC_QUALIFIER} vec4 value;\n"
143 "void main(void) { ${BODY} }\n";
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;
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.
159 * These variants require highp to be supported, so will not be run for GLSL_VERSION_100_ES.
161 { glu::GLSL_VERSION_300_ES, "", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "highp", "result = value;",
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;",
167 { glu::GLSL_VERSION_300_ES, "highp", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0) + value;", "highp",
168 "result = value;", true },
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.
174 { glu::GLSL_VERSION_100_ES, "", "gl_Position = vec4(1.0, 1.0, 1.0, 1.0);", "mediump", "result = value;",
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 },
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.
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 },
192 for (int i = 0; i < DE_LENGTH_OF_ARRAY(shader_variants); i++)
194 std::map<std::string, std::string> args;
196 if (m_glslVersion <= shader_variants[i].minimum_supported_version)
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);
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);
211 glu::ShaderProgram program(m_context.getRenderContext(),
212 glu::makeVtxFragSources(vcode.c_str(), fcode.c_str()));
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;
220 if (!vertexOk || !fragmentOk)
222 failReason = "expected shaders to compile, but failed.";
224 else if (shader_variants[i].should_link && !linkOk)
226 failReason = "expected shaders to link, but failed.";
228 else if (!shader_variants[i].should_link && linkOk)
230 failReason = "expected shaders to fail linking, but succeeded.";
233 if (failReason != DE_NULL)
235 log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage;
236 result = QP_TEST_RESULT_FAIL;
240 m_testCtx.setTestResult(result, qpGetTestResultName(result));
246 glu::GLSLVersion m_glslVersion;
249 class ShaderConstantSequenceExpressionCase : public TestCase
252 ShaderConstantSequenceExpressionCase(Context& context, const char* name, const char* description,
253 glu::GLSLVersion glslVersion)
254 : TestCase(context, name, description), m_glslVersion(glslVersion)
258 ~ShaderConstantSequenceExpressionCase()
263 IterateResult iterate()
265 qpTestResult result = QP_TEST_RESULT_PASS;
267 static const char vertex_source_template[] = "${VERSION_DECL}\n"
268 "precision mediump float;\n"
269 "const int test = (1, 2);\n"
271 "void main(void) { gl_Position = vec4(test); }\n";
273 static const char fragment_source_template[] = "${VERSION_DECL}\n"
274 "precision mediump float;\n"
276 "void main(void) { }\n";
278 std::map<std::string, std::string> args;
279 args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(m_glslVersion);
281 std::string vertex_code = tcu::StringTemplate(vertex_source_template).specialize(args);
282 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
285 glu::ShaderProgram program(m_context.getRenderContext(),
286 glu::makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
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;
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)
298 if (vertexOk && fragmentOk && linkOk)
299 result = QP_TEST_RESULT_FAIL;
302 m_testCtx.setTestResult(result, qpGetTestResultName(result));
308 glu::GLSLVersion m_glslVersion;
311 ShaderNegativeTests::ShaderNegativeTests(Context& context, glu::GLSLVersion glslVersion)
312 : TestCaseGroup(context, "negative", "Shader Negative tests"), m_glslVersion(glslVersion)
317 ShaderNegativeTests::~ShaderNegativeTests()
322 void ShaderNegativeTests::init(void)
324 addChild(new ShaderUniformInitializeGlobalCase(
325 m_context, "initialize", "Verify initialization of globals with non-constant expressions fails on ES.",
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.
332 * See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13922 for further details.
334 addChild(new ShaderUniformPrecisionLinkCase(m_context, "uniform_precision_matching",
335 "Verify that linking fails if precision qualifiers on default uniform do not match",
338 addChild(new ShaderConstantSequenceExpressionCase(
339 m_context, "constant_sequence", "Verify that the sequence operator cannot be used as a constant expression.",