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