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
38namespace deqp
39{
40namespace gles31
41{
42namespace Functional
43{
44namespace NegativeTestShared
45{
46namespace
47{
48
49enum MemoryQualifier
50{
51	MEMORY_NONE = 0,
52	MEMORY_READONLY,
53	MEMORY_WRITEONLY,
54	MEMORY_BOTH,
55
56	MEMORY_LAST
57};
58
59enum 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
75static 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
85std::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
118std::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
160std::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
189std::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
211std::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
275std::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
298std::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
322std::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
342std::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
370void 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
393void 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
431void 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
469void 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
516void 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
558template <int Type>
559void loadFuncWrapper (NegativeTestContext& ctx)
560{
561	image_load(ctx, (glu::TextureTestUtil::TextureType)Type);
562}
563
564template <int Type>
565void storeFuncWrapper (NegativeTestContext& ctx)
566{
567	image_store(ctx, (glu::TextureTestUtil::TextureType)Type);
568}
569
570template <int Type>
571void atomicFuncWrapper (NegativeTestContext& ctx)
572{
573	image_atomic(ctx, (glu::TextureTestUtil::TextureType)Type);
574}
575
576template <int Type>
577void 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
595std::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
601std::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
607std::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
613std::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