--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Negative Shader Directive Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fNegativeShaderDirectiveTests.hpp"
+
+#include "gluShaderProgram.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+
+enum ExpectResult
+{
+ EXPECT_RESULT_PASS = 0,
+ EXPECT_RESULT_FAIL,
+
+ EXPECT_RESULT_LAST
+};
+
+void verifyProgram(NegativeTestContext& ctx, glu::ProgramSources sources, ExpectResult expect)
+{
+ DE_ASSERT(expect >= EXPECT_RESULT_PASS && expect < EXPECT_RESULT_LAST);
+
+ tcu::TestLog& log = ctx.getLog();
+ const glu::ShaderProgram program (ctx.getRenderContext(), sources);
+ bool testFailed = false;
+ std::string message;
+
+ log << program;
+
+ if (expect == EXPECT_RESULT_PASS)
+ {
+ testFailed = !program.getProgramInfo().linkOk;
+ message = "Program did not link.";
+ }
+ else
+ {
+ testFailed = program.getProgramInfo().linkOk;
+ message = "Program was not expected to link.";
+ }
+
+ if (testFailed)
+ {
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+ ctx.fail(message);
+ }
+}
+
+void verifyShader(NegativeTestContext& ctx, glu::ShaderType shaderType, std::string shaderSource, ExpectResult expect)
+{
+ DE_ASSERT(expect >= EXPECT_RESULT_PASS && expect < EXPECT_RESULT_LAST);
+
+ tcu::TestLog& log = ctx.getLog();
+ bool testFailed = false;
+ const char* const source = shaderSource.c_str();
+ const int length = (int) shaderSource.size();
+ glu::Shader shader (ctx.getRenderContext(), shaderType);
+ std::string message;
+
+ shader.setSources(1, &source, &length);
+ shader.compile();
+
+ log << shader;
+
+ if (expect == EXPECT_RESULT_PASS)
+ {
+ testFailed = !shader.getCompileStatus();
+ message = "Shader did not compile.";
+ }
+ else
+ {
+ testFailed = shader.getCompileStatus();
+ message = "Shader was not expected to compile.";
+ }
+
+ if (testFailed)
+ {
+ log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+ ctx.fail(message);
+ }
+}
+
+void primitive_bounding_box (NegativeTestContext& ctx)
+{
+ ctx.beginSection("GL_EXT_primitive_bounding_box features require enabling the extension in 310 es shaders.");
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "void main()\n"
+ "{\n"
+ " gl_BoundingBoxEXT[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " gl_BoundingBoxEXT[1] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+
+ if (contextSupports(ctx.getRenderContext().getType() , glu::ApiType::es(3, 2)))
+ {
+ ctx.beginSection("gl_BoundingBox does not require the OES/EXT suffix in a 320 es shader.");
+ const std::string source = "#version 320 es\n"
+ "layout(vertices = 3) out;\n"
+ "void main()\n"
+ "{\n"
+ " gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ " gl_BoundingBox[1] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_PASS);
+ ctx.endSection();
+ }
+}
+
+void blend_equation_advanced (NegativeTestContext& ctx)
+{
+ static const char* const s_qualifiers[] =
+ {
+ "blend_support_multiply",
+ "blend_support_screen",
+ "blend_support_overlay",
+ "blend_support_darken",
+ "blend_support_lighten",
+ "blend_support_colordodge",
+ "blend_support_colorburn",
+ "blend_support_hardlight",
+ "blend_support_softlight",
+ "blend_support_difference",
+ "blend_support_exclusion",
+ "blend_support_hsl_hue",
+ "blend_support_hsl_saturation",
+ "blend_support_hsl_color",
+ "blend_support_hsl_luminosity",
+ };
+
+ ctx.beginSection("GL_KHR_blend_equation_advanced features require enabling the extension in 310 es shaders.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_qualifiers); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "layout(" << s_qualifiers[ndx] << ") out;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+}
+
+void sample_variables (NegativeTestContext& ctx)
+{
+ TCU_CHECK_AND_THROW(NotSupportedError, contextSupports(ctx.getRenderContext().getType() , glu::ApiType::es(3, 2)), "Test requires a context version 3.2 or higher.");
+
+ static const char* const s_tests[] =
+ {
+ "int sampleId = gl_SampleID;",
+ "vec2 samplePos = gl_SamplePosition;",
+ "int sampleMaskIn0 = gl_SampleMaskIn[0];",
+ "int sampleMask0 = gl_SampleMask[0];",
+ "int numSamples = gl_NumSamples;",
+ };
+
+ ctx.beginSection("GL_OES_sample_variables features require enabling the extension in 310 es shaders.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_tests); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{\n"
+ " " << s_tests[ndx] << "\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+}
+
+void shader_image_atomic (NegativeTestContext& ctx)
+{
+ static const char* const s_tests[] =
+ {
+ "imageAtomicAdd(u_image, ivec2(1, 1), 1u);",
+ "imageAtomicMin(u_image, ivec2(1, 1), 1u);",
+ "imageAtomicMax(u_image, ivec2(1, 1), 1u);",
+ "imageAtomicAnd(u_image, ivec2(1, 1), 1u);",
+ "imageAtomicOr(u_image, ivec2(1, 1), 1u);",
+ "imageAtomicXor(u_image, ivec2(1, 1), 1u);",
+ "imageAtomicExchange(u_image, ivec2(1, 1), 1u);",
+ "imageAtomicCompSwap(u_image, ivec2(1, 1), 1u, 1u);",
+ };
+
+ ctx.beginSection("GL_OES_shader_image_atomic features require enabling the extension in 310 es shaders.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_tests); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "layout(binding=0, r32ui) coherent uniform highp uimage2D u_image;\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{\n"
+ " " << s_tests[ndx] << "\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+}
+
+void shader_multisample_interpolation (NegativeTestContext& ctx)
+{
+ static const char* const s_sampleTests[] =
+ {
+ "sample in highp float v_var;",
+ "sample out highp float v_var;"
+ };
+
+ static const char* const s_interpolateAtTests[] =
+ {
+ "interpolateAtCentroid(interpolant);",
+ "interpolateAtSample(interpolant, 1);",
+ "interpolateAtOffset(interpolant, vec2(1.0, 0.0));"
+ };
+
+ ctx.beginSection("GL_OES_shader_multisample_interpolation features require enabling the extension in 310 es shaders.");
+ ctx.beginSection("Test sample in/out qualifiers.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_sampleTests); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ " " << s_sampleTests[ndx] << "\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+
+ ctx.beginSection("Test interpolateAt* functions.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_sampleTests); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "in mediump float interpolant;\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{\n"
+ " " << s_interpolateAtTests[ndx] << "\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+ ctx.endSection();
+}
+
+void texture_storage_multisample_2d_array (NegativeTestContext& ctx)
+{
+ static const char* const s_samplerTypeTests[] =
+ {
+ "uniform mediump sampler2DMSArray u_sampler;",
+ "uniform mediump isampler2DMSArray u_sampler;",
+ "uniform mediump usampler2DMSArray u_sampler;",
+ };
+
+ ctx.beginSection("GL_OES_texture_storage_multisample_2d_array features require enabling the extension in 310 es shaders.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_samplerTypeTests); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ " " << s_samplerTypeTests[ndx] << "\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+}
+
+void geometry_shader (NegativeTestContext& ctx)
+{
+ const std::string simpleVtxFrag = "#version 310 es\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ const std::string geometry = "#version 310 es\n"
+ "layout(points, invocations = 1) in;\n"
+ "layout(points, max_vertices = 3) out;\n"
+ "precision mediump float;\n"
+ "void main()\n"
+ "{\n"
+ " EmitVertex();\n"
+ " EndPrimitive();\n"
+ "}\n";
+ ctx.beginSection("GL_EXT_geometry_shader features require enabling the extension in 310 es shaders.");
+ verifyProgram(ctx, glu::ProgramSources() << glu::VertexSource(simpleVtxFrag) << glu::GeometrySource(geometry) << glu::FragmentSource(simpleVtxFrag), EXPECT_RESULT_FAIL);
+ ctx.endSection();
+}
+
+void gpu_shader_5 (NegativeTestContext& ctx)
+{
+ ctx.beginSection("GL_EXT_gpu_shader5 features require enabling the extension in 310 es shaders.");
+ ctx.beginSection("Testing the precise qualifier.");
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "void main()\n"
+ "{\n"
+ " int low = 0;\n"
+ " int high = 10;\n"
+ " precise int middle = low + ((high - low) / 2);\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+
+ ctx.beginSection("Testing fused multiply-add.");
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "in mediump float v_var;"
+ "void main()\n"
+ "{\n"
+ " float fmaResult = fma(v_var, v_var, v_var);"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+
+ ctx.beginSection("Testing textureGatherOffsets.");
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "uniform mediump sampler2D u_tex;\n"
+ "void main()\n"
+ "{\n"
+ " highp vec2 coords = vec2(0.0, 1.0);\n"
+ " const ivec2 offsets[4] = ivec2[](ivec2(0,0), ivec2(1, 0), ivec2(0, 1), ivec2(1, 1));\n"
+ " textureGatherOffsets(u_tex, coords, offsets);\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+
+ ctx.endSection();
+}
+
+void shader_io_blocks (NegativeTestContext& ctx)
+{
+ ctx.beginSection("GL_EXT_shader_io_blocks features require enabling the extension in 310 es shaders.");
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "in Data\n"
+ "{\n"
+ " mediump vec3 a;\n"
+ "} data;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+}
+
+void tessellation_shader (NegativeTestContext& ctx)
+{
+ const std::string simpleVtxFrag = "#version 310 es\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ const std::string tessControl = "#version 310 es\n"
+ "layout(vertices = 3) out;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ const std::string tessEvaluation = "#version 310 es\n"
+ "layout(triangles, equal_spacing, cw) in;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ ctx.beginSection("GL_EXT_tessellation_shader features require enabling the extension in 310 es shaders.");
+ glu::ProgramSources sources;
+ sources << glu::VertexSource(simpleVtxFrag)
+ << glu::TessellationControlSource(tessControl)
+ << glu::TessellationEvaluationSource(tessEvaluation)
+ << glu::FragmentSource(simpleVtxFrag);
+ verifyProgram(ctx, sources, EXPECT_RESULT_FAIL);
+ ctx.endSection();
+}
+
+void texture_buffer (NegativeTestContext& ctx)
+{
+ static const char* const s_samplerBufferTypes[] =
+ {
+ "uniform mediump samplerBuffer",
+ "uniform mediump isamplerBuffer",
+ "uniform mediump usamplerBuffer",
+ "layout(rgba32f) uniform mediump writeonly imageBuffer",
+ "layout(rgba32i) uniform mediump writeonly iimageBuffer",
+ "layout(rgba32ui) uniform mediump writeonly uimageBuffer"
+ };
+
+ ctx.beginSection("GL_EXT_texture_buffer features require enabling the extension in 310 es shaders.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_samplerBufferTypes); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "" << s_samplerBufferTypes[ndx] << " u_buffer;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+}
+
+
+void texture_cube_map_array (NegativeTestContext& ctx)
+{
+ static const char* const s_samplerCubeArrayTypes[] =
+ {
+ "uniform mediump samplerCubeArray",
+ "uniform mediump isamplerCubeArray",
+ "uniform mediump usamplerCubeArray",
+ "uniform mediump samplerCubeArrayShadow",
+ "layout(rgba32f) uniform mediump writeonly imageCubeArray",
+ "layout(rgba32i) uniform mediump writeonly iimageCubeArray",
+ "layout(rgba32ui) uniform mediump writeonly uimageCubeArray"
+ };
+
+ ctx.beginSection("GL_EXT_texture_cube_map_array features require enabling the extension in 310 es shaders.");
+ for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_samplerCubeArrayTypes); ++ndx)
+ {
+ std::ostringstream source;
+ source << "#version 310 es\n"
+ "" << s_samplerCubeArrayTypes[ndx] << " u_cube;\n"
+ "void main()\n"
+ "{\n"
+ "}\n";
+ verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
+ }
+ ctx.endSection();
+}
+
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeShaderDirectiveTestFunctions (void)
+{
+ const FunctionContainer funcs[] =
+ {
+ {primitive_bounding_box, "primitive_bounding_box", "GL_EXT_primitive_bounding_box required in 310 es shaders to use AEP features. Version 320 es shaders do not require suffixes." },
+ {blend_equation_advanced, "blend_equation_advanced", "GL_KHR_blend_equation_advanced is required in 310 es shaders to use AEP features" },
+ {sample_variables, "sample_variables", "GL_OES_sample_variables is required in 310 es shaders to use AEP features" },
+ {shader_image_atomic, "shader_image_atomic", "GL_OES_shader_image_atomic is required in 310 es shaders to use AEP features" },
+ {shader_multisample_interpolation, "shader_multisample_interpolation", "GL_OES_shader_multisample_interpolation is required in 310 es shaders to use AEP features" },
+ {texture_storage_multisample_2d_array, "texture_storage_multisample_2d_array", "GL_OES_texture_storage_multisample_2d_array is required in 310 es shaders to use AEP features" },
+ {geometry_shader, "geometry_shader", "GL_EXT_geometry_shader is required in 310 es shaders to use AEP features" },
+ {gpu_shader_5, "gpu_shader_5", "GL_EXT_gpu_shader5 is required in 310 es shaders to use AEP features" },
+ {shader_io_blocks, "shader_io_blocks", "GL_EXT_shader_io_blocks is required in 310 es shaders to use AEP features" },
+ {tessellation_shader, "tessellation_shader", "GL_EXT_tessellation_shader is required in 310 es shaders to use AEP features" },
+ {texture_buffer, "texture_buffer", "GL_EXT_texture_buffer is required in 310 es shaders to use AEP features" },
+ {texture_cube_map_array, "texture_cube_map_array", "GL_EXT_texture_cube_map_array is required in 310 es shaders to use AEP features" },
+ };
+
+ return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp