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"
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;
54 class ShaderUniformInitializeGlobalCase : public TestCase
57 ShaderUniformInitializeGlobalCase(Context& context, const char* name, const char* description,
58 GLSLVersion glslVersion)
59 : TestCase(context, name, description), m_glslVersion(glslVersion)
63 ~ShaderUniformInitializeGlobalCase()
68 IterateResult iterate()
70 qpTestResult result = QP_TEST_RESULT_PASS;
72 static const char vertex_source_template[] =
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"
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"
86 "void main(void) { }\n";
88 std::map<std::string, std::string> args;
89 args["VERSION_DECL"] = getGLSLVersionDeclaration(m_glslVersion);
91 std::string vertex_code = tcu::StringTemplate(vertex_source_template).specialize(args);
92 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
95 ShaderProgram program(m_context.getRenderContext(),
96 makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
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
102 bool vertexOk = program.getShaderInfo(SHADERTYPE_VERTEX).compileOk;
103 bool fragmentOk = program.getShaderInfo(SHADERTYPE_FRAGMENT).compileOk;
104 bool linkOk = program.getProgramInfo().linkOk;
106 if (glslVersionIsES(m_glslVersion))
108 if (vertexOk && fragmentOk && linkOk)
109 result = QP_TEST_RESULT_FAIL;
113 if (!vertexOk && !fragmentOk && !linkOk)
114 result = QP_TEST_RESULT_FAIL;
117 m_testCtx.setTestResult(result, qpGetTestResultName(result));
123 GLSLVersion m_glslVersion;
126 class ShaderUniformPrecisionLinkCase : public TestCase
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)
139 ~ShaderUniformPrecisionLinkCase()
144 IterateResult iterate()
146 TestLog& log = m_testCtx.getLog();
147 qpTestResult result = QP_TEST_RESULT_PASS;
149 static const char vertex_source_template[] = "${VERSION_DECL}\n"
150 "uniform ${PREC_QUALIFIER} vec4 value;\n"
152 "void main(void) { ${BODY} }\n";
154 static const char fragment_source_template[] = "${VERSION_DECL}\n"
155 "out highp vec4 result;\n"
156 "uniform ${PREC_QUALIFIER} vec4 value;\n"
158 "void main(void) { ${BODY} }\n";
160 for (unsigned int i = 0; i < m_shaderVariantsCount; i++)
162 std::map<std::string, std::string> args;
164 if (m_glslVersion <= m_shaderVariants[i].minimum_supported_version)
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);
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);
179 ShaderProgram program(m_context.getRenderContext(), makeVtxFragSources(vcode.c_str(), fcode.c_str()));
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;
187 if (!vertexOk || !fragmentOk)
189 failReason = "expected shaders to compile, but failed.";
191 else if (m_shaderVariants[i].should_link && !linkOk)
193 failReason = "expected shaders to link, but failed.";
195 else if (!m_shaderVariants[i].should_link && linkOk)
197 failReason = "expected shaders to fail linking, but succeeded.";
200 if (failReason != DE_NULL)
202 log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage;
203 result = QP_TEST_RESULT_FAIL;
207 m_testCtx.setTestResult(result, qpGetTestResultName(result));
213 GLSLVersion m_glslVersion;
214 const ShaderVariants* m_shaderVariants;
215 unsigned int m_shaderVariantsCount;
218 class ShaderConstantSequenceExpressionCase : public TestCase
221 ShaderConstantSequenceExpressionCase(Context& context, const char* name, const char* description,
222 GLSLVersion glslVersion)
223 : TestCase(context, name, description), m_glslVersion(glslVersion)
227 ~ShaderConstantSequenceExpressionCase()
232 IterateResult iterate()
234 qpTestResult result = QP_TEST_RESULT_PASS;
236 static const char vertex_source_template[] = "${VERSION_DECL}\n"
237 "precision mediump float;\n"
238 "const int test = (1, 2);\n"
240 "void main(void) { gl_Position = vec4(test); }\n";
242 static const char fragment_source_template[] = "${VERSION_DECL}\n"
243 "precision mediump float;\n"
245 "void main(void) { }\n";
247 std::map<std::string, std::string> args;
248 args["VERSION_DECL"] = getGLSLVersionDeclaration(m_glslVersion);
250 std::string vertex_code = tcu::StringTemplate(vertex_source_template).specialize(args);
251 std::string fragment_code = tcu::StringTemplate(fragment_source_template).specialize(args);
254 ShaderProgram program(m_context.getRenderContext(),
255 makeVtxFragSources(vertex_code.c_str(), fragment_code.c_str()));
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;
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)
267 if (vertexOk && fragmentOk && linkOk)
268 result = QP_TEST_RESULT_FAIL;
271 m_testCtx.setTestResult(result, qpGetTestResultName(result));
277 GLSLVersion m_glslVersion;
280 ShaderNegativeTests::ShaderNegativeTests(Context& context, GLSLVersion glslVersion)
281 : TestCaseGroup(context, "negative", "Shader Negative tests"), m_glslVersion(glslVersion)
286 ShaderNegativeTests::~ShaderNegativeTests()
291 void ShaderNegativeTests::init(void)
293 addChild(new ShaderUniformInitializeGlobalCase(
294 m_context, "initialize", "Verify initialization of globals with non-constant expressions fails on ES.",
297 addChild(new ShaderConstantSequenceExpressionCase(
298 m_context, "constant_sequence", "Verify that the sequence operator cannot be used as a constant expression.",
301 if (isGLSLVersionSupported(m_context.getRenderContext().getType(), GLSL_VERSION_320_ES))
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.
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 },
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.
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 },
317 unsigned int used_variables_variants_count = sizeof(used_variables_variants) / sizeof(ShaderVariants);
319 addChild(new ShaderUniformPrecisionLinkCase(
320 m_context, "used_uniform_precision_matching",
321 "Verify that linking fails if precision qualifiers on default uniform do not match",
322 used_variables_variants, used_variables_variants_count, m_glslVersion));