• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getShaderImageLayoutQualifier(const tcu::TextureFormat & format)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 
getShaderImageTypeDeclaration(const tcu::TextureFormat & format,glu::TextureTestUtil::TextureType imageType)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 
getShaderImageTypeExtensionString(glu::TextureTestUtil::TextureType imageType)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 
getShaderImageParamP(glu::TextureTestUtil::TextureType imageType)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 
getOtherFunctionArguments(const tcu::TextureFormat & format,ImageOperation function)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 
getMemoryQualifier(MemoryQualifier memory)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 
getShaderImageFunctionExtensionString(ImageOperation function)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 
getFunctionName(ImageOperation function)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 
generateShaderSource(ImageOperation function,MemoryQualifier memory,glu::TextureTestUtil::TextureType imageType,const tcu::TextureFormat & format,glu::ShaderType shaderType)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 
testShader(NegativeTestContext & ctx,ImageOperation function,MemoryQualifier memory,glu::TextureTestUtil::TextureType imageType,const tcu::TextureFormat & format)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 
image_store(NegativeTestContext & ctx,glu::TextureTestUtil::TextureType imageType)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 
image_load(NegativeTestContext & ctx,glu::TextureTestUtil::TextureType imageType)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 
image_atomic(NegativeTestContext & ctx,glu::TextureTestUtil::TextureType imageType)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 
image_atomic_exchange(NegativeTestContext & ctx,glu::TextureTestUtil::TextureType imageType)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>
loadFuncWrapper(NegativeTestContext & ctx)559 void loadFuncWrapper (NegativeTestContext& ctx)
560 {
561 	image_load(ctx, (glu::TextureTestUtil::TextureType)Type);
562 }
563 
564 template <int Type>
storeFuncWrapper(NegativeTestContext & ctx)565 void storeFuncWrapper (NegativeTestContext& ctx)
566 {
567 	image_store(ctx, (glu::TextureTestUtil::TextureType)Type);
568 }
569 
570 template <int Type>
atomicFuncWrapper(NegativeTestContext & ctx)571 void atomicFuncWrapper (NegativeTestContext& ctx)
572 {
573 	image_atomic(ctx, (glu::TextureTestUtil::TextureType)Type);
574 }
575 
576 template <int Type>
atomicExchangeFuncWrapper(NegativeTestContext & ctx)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 
getNegativeShaderImageLoadTestFunctions(void)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 
getNegativeShaderImageStoreTestFunctions(void)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 
getNegativeShaderImageAtomicTestFunctions(void)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 
getNegativeShaderImageAtomicExchangeTestFunctions(void)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