1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2015 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Negative Shader Image Load Store Tests
22 *//*--------------------------------------------------------------------*/
24 #include "es31fNegativeShaderImageLoadStoreTests.hpp"
26 #include "deUniquePtr.hpp"
28 #include "glwEnums.hpp"
30 #include "gluShaderProgram.hpp"
32 #include "glsTextureTestUtil.hpp"
34 #include "tcuStringTemplate.hpp"
35 #include "tcuTexture.hpp"
36 #include "tcuTestLog.hpp"
44 namespace NegativeTestShared
61 IMAGE_OPERATION_STORE = 0,
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,
75 static const glu::ShaderType s_shaders[] =
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
85 static const glu::TextureTestUtil::TextureType s_imageTypes[] =
87 glu::TextureTestUtil::TEXTURETYPE_2D,
88 glu::TextureTestUtil::TEXTURETYPE_3D,
89 glu::TextureTestUtil::TEXTURETYPE_CUBE,
90 glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY,
91 glu::TextureTestUtil::TEXTURETYPE_BUFFER,
92 glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY
95 std::string getShaderImageLayoutQualifier (const tcu::TextureFormat& format)
97 std::ostringstream qualifier;
101 case tcu::TextureFormat::RGBA: qualifier << "rgba"; break;
102 case tcu::TextureFormat::R: qualifier << "r"; break;
105 return std::string("");
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;
122 return std::string("");
125 return qualifier.str();
128 std::string getShaderImageTypeDeclaration (const tcu::TextureFormat& format, glu::TextureTestUtil::TextureType imageType)
130 std::ostringstream declaration;
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;
139 case tcu::TextureFormat::SIGNED_INT32:
140 case tcu::TextureFormat::SIGNED_INT16:
141 case tcu::TextureFormat::SIGNED_INT8: declaration << "i"; break;
143 case tcu::TextureFormat::UNSIGNED_INT32:
144 case tcu::TextureFormat::UNSIGNED_INT16:
145 case tcu::TextureFormat::UNSIGNED_INT8: declaration << "u"; break;
149 return std::string("");
152 declaration << "image";
156 case glu::TextureTestUtil::TEXTURETYPE_2D: declaration << "2D"; break;
157 case glu::TextureTestUtil::TEXTURETYPE_3D: declaration << "3D"; break;
158 case glu::TextureTestUtil::TEXTURETYPE_CUBE: declaration << "Cube"; break;
159 case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY: declaration << "2DArray"; break;
160 case glu::TextureTestUtil::TEXTURETYPE_BUFFER: declaration << "Buffer"; break;
161 case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY: declaration << "CubeArray"; break;
164 return std::string("");
167 return declaration.str();
170 std::string getShaderImageTypeExtensionString (glu::TextureTestUtil::TextureType imageType)
172 std::string extension;
176 case glu::TextureTestUtil::TEXTURETYPE_2D:
177 case glu::TextureTestUtil::TEXTURETYPE_3D:
178 case glu::TextureTestUtil::TEXTURETYPE_CUBE:
179 case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY:
183 case glu::TextureTestUtil::TEXTURETYPE_BUFFER:
184 extension = "#extension GL_EXT_texture_buffer : enable";
187 case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY:
188 extension = "#extension GL_EXT_texture_cube_map_array : enable";
193 return std::string("");
199 std::string getShaderImageParamP (glu::TextureTestUtil::TextureType imageType)
203 case glu::TextureTestUtil::TEXTURETYPE_2D:
204 return "ivec2(1, 1)";
206 case glu::TextureTestUtil::TEXTURETYPE_3D:
207 case glu::TextureTestUtil::TEXTURETYPE_CUBE:
208 case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY:
209 case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY:
210 return "ivec3(1, 1, 1)";
212 case glu::TextureTestUtil::TEXTURETYPE_BUFFER:
217 return std::string("");
221 std::string getOtherFunctionArguments (const tcu::TextureFormat& format, ImageOperation function)
223 std::ostringstream data;
226 bool isFloat = false;
230 case tcu::TextureFormat::FLOAT:
231 case tcu::TextureFormat::HALF_FLOAT:
232 case tcu::TextureFormat::UNORM_INT8:
233 case tcu::TextureFormat::SNORM_INT8:
238 case tcu::TextureFormat::SIGNED_INT32:
239 case tcu::TextureFormat::SIGNED_INT16:
240 case tcu::TextureFormat::SIGNED_INT8:
244 case tcu::TextureFormat::UNSIGNED_INT32:
245 case tcu::TextureFormat::UNSIGNED_INT16:
246 case tcu::TextureFormat::UNSIGNED_INT8:
252 return std::string("");
257 case IMAGE_OPERATION_LOAD:
260 case IMAGE_OPERATION_STORE:
261 data << "vec4(1, 1, 1, 1)";
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:
272 case IMAGE_OPERATION_ATOMIC_EXCHANGE:
273 return isFloat ? ", 1.0" : ", 1";
275 case IMAGE_OPERATION_ATOMIC_COMP_SWAP:
280 return std::string("");
285 std::string getMemoryQualifier (MemoryQualifier memory)
290 return std::string("");
292 case MEMORY_WRITEONLY:
293 return std::string("writeonly");
295 case MEMORY_READONLY:
296 return std::string("readonly");
299 return std::string("writeonly readonly");
305 return std::string("");
308 std::string getShaderImageFunctionExtensionString (ImageOperation function)
312 case IMAGE_OPERATION_STORE:
313 case IMAGE_OPERATION_LOAD:
314 return std::string("");
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");
329 return std::string("");
332 std::string getFunctionName (ImageOperation function)
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");
349 return std::string("");
352 std::string generateShaderSource (ImageOperation function, MemoryQualifier memory, glu::TextureTestUtil::TextureType imageType, const tcu::TextureFormat& format, glu::ShaderType shaderType)
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"
361 " ${FUNCTION_NAME}(u_img0, ${IMAGE_PARAM_P}${FUNCTION_ARGUMENTS});\n"
364 std::map<std::string, std::string> params;
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);
377 return tcu::StringTemplate(shaderTemplate).specialize(params);
380 void testShader (NegativeTestContext& ctx, ImageOperation function, MemoryQualifier memory, glu::TextureTestUtil::TextureType imageType, const tcu::TextureFormat& format)
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++)
386 if (ctx.isShaderSupported(s_shaders[ndx]))
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)
394 log << tcu::TestLog::Message << "Expected program to fail, but compilation passed." << tcu::TestLog::EndMessage;
395 ctx.fail("Shader was not expected to compile.");
403 void image_store (NegativeTestContext& ctx)
405 const tcu::TextureFormat formats[] =
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),
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),
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)
424 const MemoryQualifier memoryOptions[] =
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)
433 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
435 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++typeNdx)
437 testShader(ctx, IMAGE_OPERATION_STORE, memoryOptions[memoryNdx], s_imageTypes[typeNdx], formats[fmtNdx]);
444 void image_load (NegativeTestContext& ctx)
446 const tcu::TextureFormat formats[] =
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),
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),
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)
465 const MemoryQualifier memoryOptions[] =
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)
474 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
476 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++typeNdx)
478 testShader(ctx, IMAGE_OPERATION_LOAD, memoryOptions[memoryNdx], s_imageTypes[typeNdx], formats[fmtNdx]);
485 void image_atomic (NegativeTestContext& ctx)
487 const tcu::TextureFormat formats[] =
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),
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)
500 const MemoryQualifier memoryOptions[] =
507 const ImageOperation imageOperations[] =
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
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)
521 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
523 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++typeNdx)
525 for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(imageOperations); ++functionNdx)
527 testShader(ctx, imageOperations[functionNdx], memoryOptions[memoryNdx], s_imageTypes[typeNdx], formats[fmtNdx]);
535 void image_atomic_exchange (NegativeTestContext& ctx)
537 const tcu::TextureFormat formats[] =
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),
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),
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)
556 const MemoryQualifier memoryOptions[] =
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)
566 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx)
568 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++typeNdx)
570 testShader(ctx, IMAGE_OPERATION_ATOMIC_EXCHANGE, memoryOptions[memoryNdx], s_imageTypes[typeNdx], formats[fmtNdx]);
579 std::vector<FunctionContainer> getNegativeShaderImageLoadStoreTestFunctions (void)
581 const FunctionContainer funcs[] =
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()" },
589 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
592 } // NegativeTestShared