Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2015 The Android Open Source Project
      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 Negative Atomic Counter Tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fNegativeAtomicCounterTests.hpp"
     25 
     26 #include "deUniquePtr.hpp"
     27 
     28 #include "glwEnums.hpp"
     29 #include "gluShaderProgram.hpp"
     30 
     31 #include "tcuTestLog.hpp"
     32 
     33 namespace deqp
     34 {
     35 namespace gles31
     36 {
     37 namespace Functional
     38 {
     39 namespace NegativeTestShared
     40 {
     41 namespace
     42 {
     43 
     44 enum TestCase
     45 {
     46 	TESTCASE_LAYOUT_LARGE_BINDING = 0,
     47 	TESTCASE_LAYOUT_MEDIUMP_PRECISION,
     48 	TESTCASE_LAYOUT_LOWP_PRECISION,
     49 	TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP,
     50 	TESTCASE_LAYOUT_BINDING_OMITTED,
     51 	TESTCASE_STRUCT,
     52 	TESTCASE_BODY_WRITE,
     53 	TESTCASE_BODY_DECLARE,
     54 
     55 	TESTCASE_LAST
     56 };
     57 
     58 static const glu::ShaderType s_shaders[] =
     59 {
     60 	glu::SHADERTYPE_VERTEX,
     61 	glu::SHADERTYPE_FRAGMENT,
     62 	glu::SHADERTYPE_GEOMETRY,
     63 	glu::SHADERTYPE_TESSELLATION_CONTROL,
     64 	glu::SHADERTYPE_TESSELLATION_EVALUATION,
     65 	glu::SHADERTYPE_COMPUTE
     66 };
     67 
     68 std::string genShaderSource (NegativeTestContext& ctx, TestCase test, glu::ShaderType type)
     69 {
     70 	DE_ASSERT(test < TESTCASE_LAST && type < glu::SHADERTYPE_LAST);
     71 
     72 	glw::GLint maxBuffers = -1;
     73 	std::ostringstream shader;
     74 
     75 	ctx.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxBuffers);
     76 
     77 	shader << getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n";
     78 
     79 	switch (type)
     80 	{
     81 		case glu::SHADERTYPE_GEOMETRY:
     82 			shader << "#extension GL_EXT_geometry_shader : enable\n";
     83 			shader << "layout(max_vertices = 3) out;\n";
     84 			break;
     85 
     86 		case glu::SHADERTYPE_TESSELLATION_CONTROL:
     87 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
     88 			shader << "#extension GL_EXT_tessellation_shader : enable\n";
     89 			break;
     90 
     91 		default:
     92 			break;
     93 	}
     94 
     95 	switch (test)
     96 	{
     97 		case TESTCASE_LAYOUT_LARGE_BINDING:
     98 			shader << "layout (binding = " << maxBuffers << ", offset = 0) uniform atomic_uint counter0;\n";
     99 			break;
    100 
    101 		case TESTCASE_LAYOUT_MEDIUMP_PRECISION:
    102 			shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_MEDIUMP) << " uniform atomic_uint counter0;\n";
    103 			break;
    104 
    105 		case TESTCASE_LAYOUT_LOWP_PRECISION:
    106 			shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_LOWP) << " uniform atomic_uint counter0;\n";
    107 			break;
    108 
    109 		case TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP:
    110 			shader << "layout (binding = 1, offset = 0) uniform atomic_uint counter0;\n"
    111 				   << "layout (binding = 1, offset = 2) uniform atomic_uint counter1;\n";
    112 			break;
    113 
    114 		case TESTCASE_LAYOUT_BINDING_OMITTED:
    115 			shader << "layout (offset = 0) uniform atomic_uint counter0;\n";
    116 			break;
    117 
    118 		case TESTCASE_STRUCT:
    119 			shader << "struct\n"
    120 				   << "{\n"
    121 				   << "  int a;\n"
    122 				   << "  atomic_uint counter;\n"
    123 				   << "} S;\n";
    124 			break;
    125 
    126 		case TESTCASE_BODY_WRITE:
    127 			shader << "layout (binding = 1) uniform atomic_uint counter;\n";
    128 			break;
    129 
    130 		default:
    131 			break;
    132 	}
    133 
    134 	shader << "void main (void)\n"
    135 				 << "{\n";
    136 
    137 	switch (test)
    138 	{
    139 		case TESTCASE_BODY_WRITE:
    140 			shader << "counter = 1;\n";
    141 			break;
    142 
    143 		case TESTCASE_BODY_DECLARE:
    144 			shader << "atomic_uint counter;\n";
    145 			break;
    146 
    147 		default:
    148 			break;
    149 	}
    150 
    151 	shader << "}\n";
    152 
    153 	return shader.str();
    154 }
    155 
    156 void iterateShaders (NegativeTestContext& ctx, TestCase testCase)
    157 {
    158 	tcu::TestLog& log = ctx.getLog();
    159 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_shaders); ndx++)
    160 	{
    161 		if (ctx.isShaderSupported(s_shaders[ndx]))
    162 		{
    163 			ctx.beginSection(std::string("Verify shader: ") + glu::getShaderTypeName(s_shaders[ndx]));
    164 			const glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << glu::ShaderSource(s_shaders[ndx], genShaderSource(ctx, testCase, s_shaders[ndx])));
    165 			if (program.getShaderInfo(s_shaders[ndx]).compileOk)
    166 			{
    167 				log << program;
    168 				log << tcu::TestLog::Message << "Expected program to fail, but compilation passed." << tcu::TestLog::EndMessage;
    169 				ctx.fail("Shader was not expected to compile.");
    170 			}
    171 			ctx.endSection();
    172 		}
    173 	}
    174 }
    175 
    176 void atomic_max_counter_bindings (NegativeTestContext& ctx)
    177 {
    178 	ctx.beginSection("It is a compile-time error to bind an atomic counter with a binding value greater than or equal to gl_MaxAtomicCounterBindings.");
    179 	iterateShaders(ctx, TESTCASE_LAYOUT_LARGE_BINDING);
    180 	ctx.endSection();
    181 }
    182 
    183 void atomic_precision (NegativeTestContext& ctx)
    184 {
    185 	ctx.beginSection("It is an error to declare an atomic type with a lowp or mediump precision.");
    186 	iterateShaders(ctx, TESTCASE_LAYOUT_MEDIUMP_PRECISION);
    187 	iterateShaders(ctx, TESTCASE_LAYOUT_LOWP_PRECISION);
    188 	ctx.endSection();
    189 }
    190 
    191 void atomic_binding_offset_overlap (NegativeTestContext& ctx)
    192 {
    193 	ctx.beginSection("Atomic counters may not have overlapping offsets in the same binding.");
    194 	iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP);
    195 	ctx.endSection();
    196 }
    197 
    198 void atomic_binding_omitted (NegativeTestContext& ctx)
    199 {
    200 	ctx.beginSection("Atomic counters must specify a binding point");
    201 	iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OMITTED);
    202 	ctx.endSection();
    203 }
    204 
    205 void atomic_struct (NegativeTestContext& ctx)
    206 {
    207 	ctx.beginSection("Structures may not have an atomic_uint variable.");
    208 	iterateShaders(ctx, TESTCASE_STRUCT);
    209 	ctx.endSection();
    210 }
    211 
    212 void atomic_body_write (NegativeTestContext& ctx)
    213 {
    214 	ctx.beginSection("An atomic_uint variable cannot be directly written to.");
    215 	iterateShaders(ctx, TESTCASE_BODY_WRITE);
    216 	ctx.endSection();
    217 }
    218 
    219 void atomic_body_declare (NegativeTestContext& ctx)
    220 {
    221 	ctx.beginSection("An atomic_uint variable cannot be declared in local scope");
    222 	iterateShaders(ctx, TESTCASE_BODY_DECLARE);
    223 	ctx.endSection();
    224 }
    225 
    226 } // anonymous
    227 
    228 std::vector<FunctionContainer> getNegativeAtomicCounterTestFunctions ()
    229 {
    230 	const FunctionContainer funcs[] =
    231 	{
    232 		{atomic_max_counter_bindings,		"atomic_max_counter_bindings",		"Invalid atomic counter buffer binding."	},
    233 		{atomic_precision,					"atomic_precision",					"Invalid precision qualifier."				},
    234 		{atomic_binding_offset_overlap,		"atomic_binding_offset_overlap",	"Invalid offset."							},
    235 		{atomic_binding_omitted,			"atomic_binding_omitted",			"Binding not specified."					},
    236 		{atomic_struct,						"atomic_struct",					"Invalid atomic_uint usage in struct."		},
    237 		{atomic_body_write,					"atomic_body_write",				"Invalid write access to atomic_uint."		},
    238 		{atomic_body_declare,				"atomic_body_declare",				"Invalid precision qualifier."				},
    239 	};
    240 
    241 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    242 }
    243 
    244 } // NegativeTestShared
    245 } // Functional
    246 } // gles31
    247 } // deqp
    248