C++程序  |  497行  |  16 KB

/*-------------------------------------------------------------------------
 * 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