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