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 Shader Image Load Store Tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fNegativeShaderImageLoadStoreTests.hpp"
     25 
     26 #include "deUniquePtr.hpp"
     27 
     28 #include "glwEnums.hpp"
     29 
     30 #include "gluShaderProgram.hpp"
     31 
     32 #include "glsTextureTestUtil.hpp"
     33 
     34 #include "tcuStringTemplate.hpp"
     35 #include "tcuTexture.hpp"
     36 #include "tcuTestLog.hpp"
     37 
     38 namespace deqp
     39 {
     40 namespace gles31
     41 {
     42 namespace Functional
     43 {
     44 namespace NegativeTestShared
     45 {
     46 namespace
     47 {
     48 
     49 enum MemoryQualifier
     50 {
     51 	MEMORY_NONE = 0,
     52 	MEMORY_READONLY,
     53 	MEMORY_WRITEONLY,
     54 	MEMORY_BOTH,
     55 
     56 	MEMORY_LAST
     57 };
     58 
     59 enum ImageOperation
     60 {
     61 	IMAGE_OPERATION_STORE = 0,
     62 	IMAGE_OPERATION_LOAD,
     63 	IMAGE_OPERATION_ATOMIC_ADD,
     64 	IMAGE_OPERATION_ATOMIC_MIN,
     65 	IMAGE_OPERATION_ATOMIC_MAX,
     66 	IMAGE_OPERATION_ATOMIC_AND,
     67 	IMAGE_OPERATION_ATOMIC_OR,
     68 	IMAGE_OPERATION_ATOMIC_XOR,
     69 	IMAGE_OPERATION_ATOMIC_EXCHANGE,
     70 	IMAGE_OPERATION_ATOMIC_COMP_SWAP,
     71 
     72 	IMAGE_OPERATION_LAST
     73 };
     74 
     75 static const glu::ShaderType s_shaders[] =
     76 {
     77 	glu::SHADERTYPE_VERTEX,
     78 	glu::SHADERTYPE_FRAGMENT,
     79 	glu::SHADERTYPE_GEOMETRY,
     80 	glu::SHADERTYPE_TESSELLATION_CONTROL,
     81 	glu::SHADERTYPE_TESSELLATION_EVALUATION,
     82 	glu::SHADERTYPE_COMPUTE
     83 };
     84 
     85 std::string getShaderImageLayoutQualifier (const tcu::TextureFormat& format)
     86 {
     87 	std::ostringstream qualifier;
     88 
     89 	switch (format.order)
     90 	{
     91 		case tcu::TextureFormat::RGBA:	qualifier << "rgba";	break;
     92 		case tcu::TextureFormat::R:		qualifier << "r";		break;
     93 		default:
     94 			DE_ASSERT(false);
     95 			return std::string("");
     96 	}
     97 
     98 	switch (format.type)
     99 	{
    100 		case tcu::TextureFormat::FLOAT:				qualifier << "32f";			break;
    101 		case tcu::TextureFormat::HALF_FLOAT:		qualifier << "16f";			break;
    102 		case tcu::TextureFormat::UNORM_INT8:		qualifier << "8";			break;
    103 		case tcu::TextureFormat::SNORM_INT8:		qualifier << "8_snorm";		break;
    104 		case tcu::TextureFormat::SIGNED_INT32:		qualifier << "32i";			break;
    105 		case tcu::TextureFormat::SIGNED_INT16:		qualifier << "16i";			break;
    106 		case tcu::TextureFormat::SIGNED_INT8:		qualifier << "8i";			break;
    107 		case tcu::TextureFormat::UNSIGNED_INT32:	qualifier << "32ui";		break;
    108 		case tcu::TextureFormat::UNSIGNED_INT16:	qualifier << "16ui";		break;
    109 		case tcu::TextureFormat::UNSIGNED_INT8:		qualifier << "8ui";			break;
    110 		default:
    111 			DE_ASSERT(false);
    112 			return std::string("");
    113 	}
    114 
    115 	return qualifier.str();
    116 }
    117 
    118 std::string getShaderImageTypeDeclaration (const tcu::TextureFormat& format, glu::TextureTestUtil::TextureType imageType)
    119 {
    120 	std::ostringstream declaration;
    121 
    122 	switch (format.type)
    123 	{
    124 		case tcu::TextureFormat::FLOAT:
    125 		case tcu::TextureFormat::HALF_FLOAT:
    126 		case tcu::TextureFormat::UNORM_INT8:
    127 		case tcu::TextureFormat::SNORM_INT8:		declaration << "";		break;
    128 
    129 		case tcu::TextureFormat::SIGNED_INT32:
    130 		case tcu::TextureFormat::SIGNED_INT16:
    131 		case tcu::TextureFormat::SIGNED_INT8:		declaration << "i";		break;
    132 
    133 		case tcu::TextureFormat::UNSIGNED_INT32:
    134 		case tcu::TextureFormat::UNSIGNED_INT16:
    135 		case tcu::TextureFormat::UNSIGNED_INT8:		declaration << "u";		break;
    136 
    137 		default:
    138 			DE_ASSERT(false);
    139 			return std::string("");
    140 	}
    141 
    142 	declaration << "image";
    143 
    144 	switch(imageType)
    145 	{
    146 		case glu::TextureTestUtil::TEXTURETYPE_2D:			declaration << "2D";			break;
    147 		case glu::TextureTestUtil::TEXTURETYPE_3D:			declaration << "3D";			break;
    148 		case glu::TextureTestUtil::TEXTURETYPE_CUBE:		declaration << "Cube";			break;
    149 		case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY:	declaration << "2DArray";		break;
    150 		case glu::TextureTestUtil::TEXTURETYPE_BUFFER:		declaration << "Buffer";		break;
    151 		case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY:	declaration << "CubeArray";		break;
    152 		default:
    153 			DE_ASSERT(false);
    154 			return std::string("");
    155 	}
    156 
    157 	return declaration.str();
    158 }
    159 
    160 std::string getShaderImageTypeExtensionString (glu::TextureTestUtil::TextureType imageType)
    161 {
    162 	std::string extension;
    163 
    164 	switch(imageType)
    165 	{
    166 		case glu::TextureTestUtil::TEXTURETYPE_2D:
    167 		case glu::TextureTestUtil::TEXTURETYPE_3D:
    168 		case glu::TextureTestUtil::TEXTURETYPE_CUBE:
    169 		case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY:
    170 			extension = "";
    171 			break;
    172 
    173 		case glu::TextureTestUtil::TEXTURETYPE_BUFFER:
    174 			extension = "#extension GL_EXT_texture_buffer : enable";
    175 			break;
    176 
    177 		case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY:
    178 			extension = "#extension GL_EXT_texture_cube_map_array : enable";
    179 			break;
    180 
    181 		default:
    182 			DE_ASSERT(false);
    183 			return std::string("");
    184 	}
    185 
    186 	return extension;
    187 }
    188 
    189 std::string getShaderImageParamP (glu::TextureTestUtil::TextureType imageType)
    190 {
    191 	switch(imageType)
    192 	{
    193 		case glu::TextureTestUtil::TEXTURETYPE_2D:
    194 			return "ivec2(1, 1)";
    195 
    196 		case glu::TextureTestUtil::TEXTURETYPE_3D:
    197 		case glu::TextureTestUtil::TEXTURETYPE_CUBE:
    198 		case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY:
    199 		case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY:
    200 			return "ivec3(1, 1, 1)";
    201 
    202 		case glu::TextureTestUtil::TEXTURETYPE_BUFFER:
    203 			return "1";
    204 
    205 		default:
    206 			DE_ASSERT(false);
    207 			return std::string("");
    208 	}
    209 }
    210 
    211 std::string getOtherFunctionArguments (const tcu::TextureFormat& format, ImageOperation function)
    212 {
    213 	std::ostringstream data;
    214 	data << ", ";
    215 
    216 	bool isFloat = false;
    217 
    218 	switch(format.type)
    219 	{
    220 		case tcu::TextureFormat::FLOAT:
    221 		case tcu::TextureFormat::HALF_FLOAT:
    222 		case tcu::TextureFormat::UNORM_INT8:
    223 		case tcu::TextureFormat::SNORM_INT8:
    224 			data << "";
    225 			isFloat = true;
    226 			break;
    227 
    228 		case tcu::TextureFormat::SIGNED_INT32:
    229 		case tcu::TextureFormat::SIGNED_INT16:
    230 		case tcu::TextureFormat::SIGNED_INT8:
    231 			data << "i";
    232 			break;
    233 
    234 		case tcu::TextureFormat::UNSIGNED_INT32:
    235 		case tcu::TextureFormat::UNSIGNED_INT16:
    236 		case tcu::TextureFormat::UNSIGNED_INT8:
    237 			data << "u";
    238 			break;
    239 
    240 		default:
    241 			DE_ASSERT(false);
    242 			return std::string("");
    243 	}
    244 
    245 	switch (function)
    246 	{
    247 		case IMAGE_OPERATION_LOAD:
    248 			return "";
    249 
    250 		case IMAGE_OPERATION_STORE:
    251 			data << "vec4(1, 1, 1, 1)";
    252 			break;
    253 
    254 		case IMAGE_OPERATION_ATOMIC_ADD:
    255 		case IMAGE_OPERATION_ATOMIC_MIN:
    256 		case IMAGE_OPERATION_ATOMIC_MAX:
    257 		case IMAGE_OPERATION_ATOMIC_AND:
    258 		case IMAGE_OPERATION_ATOMIC_OR:
    259 		case IMAGE_OPERATION_ATOMIC_XOR:
    260 			return ", 1";
    261 
    262 		case IMAGE_OPERATION_ATOMIC_EXCHANGE:
    263 			return isFloat ? ", 1.0" : ", 1";
    264 
    265 		case IMAGE_OPERATION_ATOMIC_COMP_SWAP:
    266 			return ", 1, 1";
    267 
    268 		default:
    269 			DE_ASSERT(false);
    270 			return std::string("");
    271 	}
    272 	return data.str();
    273 }
    274 
    275 std::string getMemoryQualifier (MemoryQualifier memory)
    276 {
    277 	switch (memory)
    278 	{
    279 		case MEMORY_NONE:
    280 			return std::string("");
    281 
    282 		case MEMORY_WRITEONLY:
    283 			return std::string("writeonly");
    284 
    285 		case MEMORY_READONLY:
    286 			return std::string("readonly");
    287 
    288 		case MEMORY_BOTH:
    289 			return std::string("writeonly readonly");
    290 
    291 		default:
    292 			DE_ASSERT(DE_FALSE);
    293 	}
    294 
    295 	return std::string("");
    296 }
    297 
    298 std::string getShaderImageFunctionExtensionString (ImageOperation function)
    299 {
    300 	switch (function)
    301 	{
    302 		case IMAGE_OPERATION_STORE:
    303 		case IMAGE_OPERATION_LOAD:
    304 			return std::string("");
    305 
    306 		case IMAGE_OPERATION_ATOMIC_ADD:
    307 		case IMAGE_OPERATION_ATOMIC_MIN:
    308 		case IMAGE_OPERATION_ATOMIC_MAX:
    309 		case IMAGE_OPERATION_ATOMIC_AND:
    310 		case IMAGE_OPERATION_ATOMIC_OR:
    311 		case IMAGE_OPERATION_ATOMIC_XOR:
    312 		case IMAGE_OPERATION_ATOMIC_EXCHANGE:
    313 		case IMAGE_OPERATION_ATOMIC_COMP_SWAP:
    314 			return std::string("#extension GL_OES_shader_image_atomic : enable");
    315 
    316 		default:
    317 			DE_ASSERT(DE_FALSE);
    318 	}
    319 	return std::string("");
    320 }
    321 
    322 std::string getFunctionName (ImageOperation function)
    323 {
    324 	switch (function)
    325 	{
    326 		case IMAGE_OPERATION_STORE:				return std::string("imageStore");
    327 		case IMAGE_OPERATION_LOAD:				return std::string("imageLoad");
    328 		case IMAGE_OPERATION_ATOMIC_ADD:		return std::string("imageAtomicAdd");
    329 		case IMAGE_OPERATION_ATOMIC_MIN:		return std::string("imageAtomicMin");
    330 		case IMAGE_OPERATION_ATOMIC_MAX:		return std::string("imageAtomicMax");
    331 		case IMAGE_OPERATION_ATOMIC_AND:		return std::string("imageAtomicAnd");
    332 		case IMAGE_OPERATION_ATOMIC_OR:			return std::string("imageAtomicOr");
    333 		case IMAGE_OPERATION_ATOMIC_XOR:		return std::string("imageAtomicXor");
    334 		case IMAGE_OPERATION_ATOMIC_EXCHANGE:	return std::string("imageAtomicExchange");
    335 		case IMAGE_OPERATION_ATOMIC_COMP_SWAP:	return std::string("imageAtomicCompSwap");
    336 		default:
    337 			DE_ASSERT(DE_FALSE);
    338 	}
    339 	return std::string("");
    340 }
    341 
    342 std::string generateShaderSource (ImageOperation function, MemoryQualifier memory, glu::TextureTestUtil::TextureType imageType, const tcu::TextureFormat& format, glu::ShaderType shaderType)
    343 {
    344 	const char* shaderTemplate =	"${GLSL_VERSION_DECL}\n"
    345 									"${GLSL_TYPE_EXTENSION}\n"
    346 									"${GLSL_FUNCTION_EXTENSION}\n"
    347 									"${GEOMETRY_SHADER_LAYOUT}\n"
    348 									"layout(${LAYOUT_FORMAT}, binding = 0) highp uniform ${MEMORY_QUALIFIER} ${IMAGE_TYPE} u_img0;\n"
    349 									"void main(void)\n"
    350 									"{\n"
    351 									" ${FUNCTION_NAME}(u_img0, ${IMAGE_PARAM_P}${FUNCTION_ARGUMENTS});\n"
    352 									"}\n";
    353 
    354 	std::map<std::string, std::string> params;
    355 
    356 	params["GLSL_VERSION_DECL"] = getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
    357 	params["GLSL_TYPE_EXTENSION"] = getShaderImageTypeExtensionString(imageType);
    358 	params["GLSL_FUNCTION_EXTENSION"] = getShaderImageFunctionExtensionString(function);
    359 	params["GEOMETRY_SHADER_LAYOUT"] = getGLShaderType(shaderType) == GL_GEOMETRY_SHADER ? "layout(max_vertices = 3) out;" : "";
    360 	params["LAYOUT_FORMAT"] = getShaderImageLayoutQualifier(format);
    361 	params["MEMORY_QUALIFIER"] = getMemoryQualifier(memory);
    362 	params["IMAGE_TYPE"] = getShaderImageTypeDeclaration(format, imageType);
    363 	params["FUNCTION_NAME"] = getFunctionName(function);
    364 	params["IMAGE_PARAM_P"] = getShaderImageParamP(imageType);
    365 	params["FUNCTION_ARGUMENTS"] = getOtherFunctionArguments(format, function);
    366 
    367 	return tcu::StringTemplate(shaderTemplate).specialize(params);
    368 }
    369 
    370 void testShader (NegativeTestContext& ctx, ImageOperation function, MemoryQualifier memory, glu::TextureTestUtil::TextureType imageType, const tcu::TextureFormat& format)
    371 {
    372 	tcu::TestLog& log = ctx.getLog();
    373 	ctx.beginSection(getFunctionName(function) + " " + getMemoryQualifier(memory) + " " + getShaderImageLayoutQualifier(format));
    374 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_shaders); ndx++)
    375 	{
    376 		if (ctx.isShaderSupported(s_shaders[ndx]))
    377 		{
    378 			ctx.beginSection(std::string("Verify shader: ") + glu::getShaderTypeName(s_shaders[ndx]));
    379 			std::string					shaderSource(generateShaderSource(function, memory, imageType, format, s_shaders[ndx]));
    380 			const glu::ShaderProgram	program(ctx.getRenderContext(), glu::ProgramSources() << glu::ShaderSource(s_shaders[ndx], shaderSource));
    381 			if (program.getShaderInfo(s_shaders[ndx]).compileOk)
    382 			{
    383 				log << program;
    384 				log << tcu::TestLog::Message << "Expected program to fail, but compilation passed." << tcu::TestLog::EndMessage;
    385 				ctx.fail("Shader was not expected to compile.");
    386 			}
    387 			ctx.endSection();
    388 		}
    389 	}
    390 	ctx.endSection();
    391 }
    392 
    393 void image_store (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType)
    394 {
    395 	const tcu::TextureFormat formats[] =
    396 	{
    397 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::FLOAT),
    398 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::HALF_FLOAT),
    399 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::FLOAT),
    400 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8),
    401 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SNORM_INT8),
    402 
    403 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT32),
    404 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT16),
    405 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT8),
    406 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::SIGNED_INT32),
    407 
    408 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT32),
    409 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT16),
    410 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT8),
    411 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::UNSIGNED_INT32)
    412 	};
    413 
    414 	const MemoryQualifier memoryOptions[] =
    415 	{
    416 		MEMORY_READONLY,
    417 		MEMORY_BOTH
    418 	};
    419 
    420 	ctx.beginSection("It is an error to pass a readonly image to imageStore.");
    421 	for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx)
    422 	{
    423 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
    424 		{
    425 			testShader(ctx, IMAGE_OPERATION_STORE, memoryOptions[memoryNdx], imageType, formats[fmtNdx]);
    426 		}
    427 	}
    428 	ctx.endSection();
    429 }
    430 
    431 void image_load (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType)
    432 {
    433 	const tcu::TextureFormat formats[] =
    434 	{
    435 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::FLOAT),
    436 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::HALF_FLOAT),
    437 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::FLOAT),
    438 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8),
    439 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SNORM_INT8),
    440 
    441 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT32),
    442 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT16),
    443 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT8),
    444 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::SIGNED_INT32),
    445 
    446 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT32),
    447 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT16),
    448 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT8),
    449 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::UNSIGNED_INT32)
    450 	};
    451 
    452 	const MemoryQualifier memoryOptions[] =
    453 	{
    454 		MEMORY_WRITEONLY,
    455 		MEMORY_BOTH
    456 	};
    457 
    458 	ctx.beginSection("It is an error to pass a writeonly image to imageLoad.");
    459 	for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx)
    460 	{
    461 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
    462 		{
    463 			testShader(ctx, IMAGE_OPERATION_LOAD, memoryOptions[memoryNdx], imageType, formats[fmtNdx]);
    464 		}
    465 	}
    466 	ctx.endSection();
    467 }
    468 
    469 void image_atomic (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType)
    470 {
    471 	const tcu::TextureFormat formats[] =
    472 	{
    473 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT32),
    474 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT16),
    475 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT8),
    476 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::SIGNED_INT32),
    477 
    478 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT32),
    479 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT16),
    480 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT8),
    481 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::UNSIGNED_INT32)
    482 	};
    483 
    484 	const MemoryQualifier memoryOptions[] =
    485 	{
    486 		MEMORY_READONLY,
    487 		MEMORY_WRITEONLY,
    488 		MEMORY_BOTH
    489 	};
    490 
    491 	const ImageOperation imageOperations[] =
    492 	{
    493 		IMAGE_OPERATION_ATOMIC_ADD,
    494 		IMAGE_OPERATION_ATOMIC_MIN,
    495 		IMAGE_OPERATION_ATOMIC_MAX,
    496 		IMAGE_OPERATION_ATOMIC_AND,
    497 		IMAGE_OPERATION_ATOMIC_OR,
    498 		IMAGE_OPERATION_ATOMIC_XOR,
    499 		IMAGE_OPERATION_ATOMIC_COMP_SWAP
    500 	};
    501 
    502 	ctx.beginSection("It is an error to pass a writeonly and/or readonly image to imageAtomic*.");
    503 	for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx)
    504 	{
    505 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
    506 		{
    507 			for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(imageOperations); ++functionNdx)
    508 			{
    509 				testShader(ctx, imageOperations[functionNdx], memoryOptions[memoryNdx], imageType, formats[fmtNdx]);
    510 			}
    511 		}
    512 	}
    513 	ctx.endSection();
    514 }
    515 
    516 void image_atomic_exchange (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType)
    517 {
    518 	const tcu::TextureFormat formats[] =
    519 	{
    520 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::FLOAT),
    521 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::HALF_FLOAT),
    522 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::FLOAT),
    523 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8),
    524 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SNORM_INT8),
    525 
    526 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT32),
    527 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT16),
    528 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::SIGNED_INT8),
    529 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::SIGNED_INT32),
    530 
    531 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT32),
    532 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT16),
    533 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT8),
    534 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::UNSIGNED_INT32)
    535 	};
    536 
    537 	const MemoryQualifier memoryOptions[] =
    538 	{
    539 		MEMORY_READONLY,
    540 		MEMORY_WRITEONLY,
    541 		MEMORY_BOTH
    542 	};
    543 
    544 	ctx.beginSection("It is an error to pass a writeonly and/or readonly image to imageAtomic*.");
    545 	for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx)
    546 	{
    547 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
    548 		{
    549 			testShader(ctx, IMAGE_OPERATION_ATOMIC_EXCHANGE, memoryOptions[memoryNdx], imageType, formats[fmtNdx]);
    550 		}
    551 	}
    552 	ctx.endSection();
    553 }
    554 
    555 // Re-routing function template for generating the standard negative
    556 // test function signature with texture type added.
    557 
    558 template <int Type>
    559 void loadFuncWrapper (NegativeTestContext& ctx)
    560 {
    561 	image_load(ctx, (glu::TextureTestUtil::TextureType)Type);
    562 }
    563 
    564 template <int Type>
    565 void storeFuncWrapper (NegativeTestContext& ctx)
    566 {
    567 	image_store(ctx, (glu::TextureTestUtil::TextureType)Type);
    568 }
    569 
    570 template <int Type>
    571 void atomicFuncWrapper (NegativeTestContext& ctx)
    572 {
    573 	image_atomic(ctx, (glu::TextureTestUtil::TextureType)Type);
    574 }
    575 
    576 template <int Type>
    577 void atomicExchangeFuncWrapper (NegativeTestContext& ctx)
    578 {
    579 	image_atomic_exchange(ctx, (glu::TextureTestUtil::TextureType)Type);
    580 }
    581 
    582 } // anonymous
    583 
    584 // Set of texture types to create tests for.
    585 #define CREATE_TEST_FUNC_PER_TEXTURE_TYPE(NAME, FUNC) const FunctionContainer NAME[] =									\
    586 	{																													\
    587 		{FUNC<glu::TextureTestUtil::TEXTURETYPE_2D>,			"texture_2d",	"Texture2D negative tests."},			\
    588 		{FUNC<glu::TextureTestUtil::TEXTURETYPE_3D>,			"texture_3d",	"Texture3D negative tests."},			\
    589 		{FUNC<glu::TextureTestUtil::TEXTURETYPE_CUBE>,			"cube",			"Cube texture negative tests."},		\
    590 		{FUNC<glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY>,		"2d_array",		"2D array texture negative tests."},	\
    591 		{FUNC<glu::TextureTestUtil::TEXTURETYPE_BUFFER>,		"buffer",		"Buffer negative tests."},				\
    592 		{FUNC<glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY>,	"cube_array",	"Cube array texture negative tests."}	\
    593 	}
    594 
    595 std::vector<FunctionContainer> getNegativeShaderImageLoadTestFunctions (void)
    596 {
    597 	CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, loadFuncWrapper);
    598 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    599 }
    600 
    601 std::vector<FunctionContainer> getNegativeShaderImageStoreTestFunctions (void)
    602 {
    603 	CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, storeFuncWrapper);
    604 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    605 }
    606 
    607 std::vector<FunctionContainer> getNegativeShaderImageAtomicTestFunctions (void)
    608 {
    609 	CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, atomicFuncWrapper);
    610 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    611 }
    612 
    613 std::vector<FunctionContainer> getNegativeShaderImageAtomicExchangeTestFunctions (void)
    614 {
    615 	CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, atomicExchangeFuncWrapper);
    616 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    617 }
    618 
    619 } // NegativeTestShared
    620 } // Functional
    621 } // gles31
    622 } // deqp
    623