| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES 3.1 Module |
| * ------------------------------------------------- |
| * |
| * Copyright 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Negative Shader Image Load Store Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es31fNegativeShaderImageLoadStoreTests.hpp" |
| |
| #include "deUniquePtr.hpp" |
| |
| #include "glwEnums.hpp" |
| |
| #include "gluShaderProgram.hpp" |
| |
| #include "glsTextureTestUtil.hpp" |
| |
| #include "tcuStringTemplate.hpp" |
| #include "tcuTexture.hpp" |
| #include "tcuTestLog.hpp" |
| |
| namespace deqp |
| { |
| namespace gles31 |
| { |
| namespace Functional |
| { |
| namespace NegativeTestShared |
| { |
| namespace |
| { |
| |
| enum MemoryQualifier |
| { |
| MEMORY_NONE = 0, |
| MEMORY_READONLY, |
| MEMORY_WRITEONLY, |
| MEMORY_BOTH, |
| |
| MEMORY_LAST |
| }; |
| |
| enum ImageOperation |
| { |
| IMAGE_OPERATION_STORE = 0, |
| IMAGE_OPERATION_LOAD, |
| IMAGE_OPERATION_ATOMIC_ADD, |
| IMAGE_OPERATION_ATOMIC_MIN, |
| IMAGE_OPERATION_ATOMIC_MAX, |
| IMAGE_OPERATION_ATOMIC_AND, |
| IMAGE_OPERATION_ATOMIC_OR, |
| IMAGE_OPERATION_ATOMIC_XOR, |
| IMAGE_OPERATION_ATOMIC_EXCHANGE, |
| IMAGE_OPERATION_ATOMIC_COMP_SWAP, |
| |
| IMAGE_OPERATION_LAST |
| }; |
| |
| static const glu::ShaderType s_shaders[] = |
| { |
| glu::SHADERTYPE_VERTEX, |
| glu::SHADERTYPE_FRAGMENT, |
| glu::SHADERTYPE_GEOMETRY, |
| glu::SHADERTYPE_TESSELLATION_CONTROL, |
| glu::SHADERTYPE_TESSELLATION_EVALUATION, |
| glu::SHADERTYPE_COMPUTE |
| }; |
| |
| std::string getShaderImageLayoutQualifier (const tcu::TextureFormat& format) |
| { |
| std::ostringstream qualifier; |
| |
| switch (format.order) |
| { |
| case tcu::TextureFormat::RGBA: qualifier << "rgba"; break; |
| case tcu::TextureFormat::R: qualifier << "r"; break; |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| |
| switch (format.type) |
| { |
| case tcu::TextureFormat::FLOAT: qualifier << "32f"; break; |
| case tcu::TextureFormat::HALF_FLOAT: qualifier << "16f"; break; |
| case tcu::TextureFormat::UNORM_INT8: qualifier << "8"; break; |
| case tcu::TextureFormat::SNORM_INT8: qualifier << "8_snorm"; break; |
| case tcu::TextureFormat::SIGNED_INT32: qualifier << "32i"; break; |
| case tcu::TextureFormat::SIGNED_INT16: qualifier << "16i"; break; |
| case tcu::TextureFormat::SIGNED_INT8: qualifier << "8i"; break; |
| case tcu::TextureFormat::UNSIGNED_INT32: qualifier << "32ui"; break; |
| case tcu::TextureFormat::UNSIGNED_INT16: qualifier << "16ui"; break; |
| case tcu::TextureFormat::UNSIGNED_INT8: qualifier << "8ui"; break; |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| |
| return qualifier.str(); |
| } |
| |
| std::string getShaderImageTypeDeclaration (const tcu::TextureFormat& format, glu::TextureTestUtil::TextureType imageType) |
| { |
| std::ostringstream declaration; |
| |
| switch (format.type) |
| { |
| case tcu::TextureFormat::FLOAT: |
| case tcu::TextureFormat::HALF_FLOAT: |
| case tcu::TextureFormat::UNORM_INT8: |
| case tcu::TextureFormat::SNORM_INT8: declaration << ""; break; |
| |
| case tcu::TextureFormat::SIGNED_INT32: |
| case tcu::TextureFormat::SIGNED_INT16: |
| case tcu::TextureFormat::SIGNED_INT8: declaration << "i"; break; |
| |
| case tcu::TextureFormat::UNSIGNED_INT32: |
| case tcu::TextureFormat::UNSIGNED_INT16: |
| case tcu::TextureFormat::UNSIGNED_INT8: declaration << "u"; break; |
| |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| |
| declaration << "image"; |
| |
| switch(imageType) |
| { |
| case glu::TextureTestUtil::TEXTURETYPE_2D: declaration << "2D"; break; |
| case glu::TextureTestUtil::TEXTURETYPE_3D: declaration << "3D"; break; |
| case glu::TextureTestUtil::TEXTURETYPE_CUBE: declaration << "Cube"; break; |
| case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY: declaration << "2DArray"; break; |
| case glu::TextureTestUtil::TEXTURETYPE_BUFFER: declaration << "Buffer"; break; |
| case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY: declaration << "CubeArray"; break; |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| |
| return declaration.str(); |
| } |
| |
| std::string getShaderImageTypeExtensionString (glu::TextureTestUtil::TextureType imageType) |
| { |
| std::string extension; |
| |
| switch(imageType) |
| { |
| case glu::TextureTestUtil::TEXTURETYPE_2D: |
| case glu::TextureTestUtil::TEXTURETYPE_3D: |
| case glu::TextureTestUtil::TEXTURETYPE_CUBE: |
| case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY: |
| extension = ""; |
| break; |
| |
| case glu::TextureTestUtil::TEXTURETYPE_BUFFER: |
| extension = "#extension GL_EXT_texture_buffer : enable"; |
| break; |
| |
| case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY: |
| extension = "#extension GL_EXT_texture_cube_map_array : enable"; |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| |
| return extension; |
| } |
| |
| std::string getShaderImageParamP (glu::TextureTestUtil::TextureType imageType) |
| { |
| switch(imageType) |
| { |
| case glu::TextureTestUtil::TEXTURETYPE_2D: |
| return "ivec2(1, 1)"; |
| |
| case glu::TextureTestUtil::TEXTURETYPE_3D: |
| case glu::TextureTestUtil::TEXTURETYPE_CUBE: |
| case glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY: |
| case glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY: |
| return "ivec3(1, 1, 1)"; |
| |
| case glu::TextureTestUtil::TEXTURETYPE_BUFFER: |
| return "1"; |
| |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| } |
| |
| std::string getOtherFunctionArguments (const tcu::TextureFormat& format, ImageOperation function) |
| { |
| std::ostringstream data; |
| data << ", "; |
| |
| bool isFloat = false; |
| |
| switch(format.type) |
| { |
| case tcu::TextureFormat::FLOAT: |
| case tcu::TextureFormat::HALF_FLOAT: |
| case tcu::TextureFormat::UNORM_INT8: |
| case tcu::TextureFormat::SNORM_INT8: |
| data << ""; |
| isFloat = true; |
| break; |
| |
| case tcu::TextureFormat::SIGNED_INT32: |
| case tcu::TextureFormat::SIGNED_INT16: |
| case tcu::TextureFormat::SIGNED_INT8: |
| data << "i"; |
| break; |
| |
| case tcu::TextureFormat::UNSIGNED_INT32: |
| case tcu::TextureFormat::UNSIGNED_INT16: |
| case tcu::TextureFormat::UNSIGNED_INT8: |
| data << "u"; |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| |
| switch (function) |
| { |
| case IMAGE_OPERATION_LOAD: |
| return ""; |
| |
| case IMAGE_OPERATION_STORE: |
| data << "vec4(1, 1, 1, 1)"; |
| break; |
| |
| case IMAGE_OPERATION_ATOMIC_ADD: |
| case IMAGE_OPERATION_ATOMIC_MIN: |
| case IMAGE_OPERATION_ATOMIC_MAX: |
| case IMAGE_OPERATION_ATOMIC_AND: |
| case IMAGE_OPERATION_ATOMIC_OR: |
| case IMAGE_OPERATION_ATOMIC_XOR: |
| return ", 1"; |
| |
| case IMAGE_OPERATION_ATOMIC_EXCHANGE: |
| return isFloat ? ", 1.0" : ", 1"; |
| |
| case IMAGE_OPERATION_ATOMIC_COMP_SWAP: |
| return ", 1, 1"; |
| |
| default: |
| DE_ASSERT(false); |
| return std::string(""); |
| } |
| return data.str(); |
| } |
| |
| std::string getMemoryQualifier (MemoryQualifier memory) |
| { |
| switch (memory) |
| { |
| case MEMORY_NONE: |
| return std::string(""); |
| |
| case MEMORY_WRITEONLY: |
| return std::string("writeonly"); |
| |
| case MEMORY_READONLY: |
| return std::string("readonly"); |
| |
| case MEMORY_BOTH: |
| return std::string("writeonly readonly"); |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| |
| return std::string(""); |
| } |
| |
| std::string getShaderImageFunctionExtensionString (ImageOperation function) |
| { |
| switch (function) |
| { |
| case IMAGE_OPERATION_STORE: |
| case IMAGE_OPERATION_LOAD: |
| return std::string(""); |
| |
| case IMAGE_OPERATION_ATOMIC_ADD: |
| case IMAGE_OPERATION_ATOMIC_MIN: |
| case IMAGE_OPERATION_ATOMIC_MAX: |
| case IMAGE_OPERATION_ATOMIC_AND: |
| case IMAGE_OPERATION_ATOMIC_OR: |
| case IMAGE_OPERATION_ATOMIC_XOR: |
| case IMAGE_OPERATION_ATOMIC_EXCHANGE: |
| case IMAGE_OPERATION_ATOMIC_COMP_SWAP: |
| return std::string("#extension GL_OES_shader_image_atomic : enable"); |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| return std::string(""); |
| } |
| |
| std::string getFunctionName (ImageOperation function) |
| { |
| switch (function) |
| { |
| case IMAGE_OPERATION_STORE: return std::string("imageStore"); |
| case IMAGE_OPERATION_LOAD: return std::string("imageLoad"); |
| case IMAGE_OPERATION_ATOMIC_ADD: return std::string("imageAtomicAdd"); |
| case IMAGE_OPERATION_ATOMIC_MIN: return std::string("imageAtomicMin"); |
| case IMAGE_OPERATION_ATOMIC_MAX: return std::string("imageAtomicMax"); |
| case IMAGE_OPERATION_ATOMIC_AND: return std::string("imageAtomicAnd"); |
| case IMAGE_OPERATION_ATOMIC_OR: return std::string("imageAtomicOr"); |
| case IMAGE_OPERATION_ATOMIC_XOR: return std::string("imageAtomicXor"); |
| case IMAGE_OPERATION_ATOMIC_EXCHANGE: return std::string("imageAtomicExchange"); |
| case IMAGE_OPERATION_ATOMIC_COMP_SWAP: return std::string("imageAtomicCompSwap"); |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| return std::string(""); |
| } |
| |
| std::string generateShaderSource (ImageOperation function, MemoryQualifier memory, glu::TextureTestUtil::TextureType imageType, const tcu::TextureFormat& format, glu::ShaderType shaderType) |
| { |
| const char* shaderTemplate = "${GLSL_VERSION_DECL}\n" |
| "${GLSL_TYPE_EXTENSION}\n" |
| "${GLSL_FUNCTION_EXTENSION}\n" |
| "${GEOMETRY_SHADER_LAYOUT}\n" |
| "layout(${LAYOUT_FORMAT}, binding = 0) highp uniform ${MEMORY_QUALIFIER} ${IMAGE_TYPE} u_img0;\n" |
| "void main(void)\n" |
| "{\n" |
| " ${FUNCTION_NAME}(u_img0, ${IMAGE_PARAM_P}${FUNCTION_ARGUMENTS});\n" |
| "}\n"; |
| |
| std::map<std::string, std::string> params; |
| |
| params["GLSL_VERSION_DECL"] = getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); |
| params["GLSL_TYPE_EXTENSION"] = getShaderImageTypeExtensionString(imageType); |
| params["GLSL_FUNCTION_EXTENSION"] = getShaderImageFunctionExtensionString(function); |
| params["GEOMETRY_SHADER_LAYOUT"] = getGLShaderType(shaderType) == GL_GEOMETRY_SHADER ? "layout(max_vertices = 3) out;" : ""; |
| params["LAYOUT_FORMAT"] = getShaderImageLayoutQualifier(format); |
| params["MEMORY_QUALIFIER"] = getMemoryQualifier(memory); |
| params["IMAGE_TYPE"] = getShaderImageTypeDeclaration(format, imageType); |
| params["FUNCTION_NAME"] = getFunctionName(function); |
| params["IMAGE_PARAM_P"] = getShaderImageParamP(imageType); |
| params["FUNCTION_ARGUMENTS"] = getOtherFunctionArguments(format, function); |
| |
| return tcu::StringTemplate(shaderTemplate).specialize(params); |
| } |
| |
| void testShader (NegativeTestContext& ctx, ImageOperation function, MemoryQualifier memory, glu::TextureTestUtil::TextureType imageType, const tcu::TextureFormat& format) |
| { |
| tcu::TestLog& log = ctx.getLog(); |
| ctx.beginSection(getFunctionName(function) + " " + getMemoryQualifier(memory) + " " + getShaderImageLayoutQualifier(format)); |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_shaders); ndx++) |
| { |
| if (ctx.isShaderSupported(s_shaders[ndx])) |
| { |
| ctx.beginSection(std::string("Verify shader: ") + glu::getShaderTypeName(s_shaders[ndx])); |
| std::string shaderSource(generateShaderSource(function, memory, imageType, format, s_shaders[ndx])); |
| const glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << glu::ShaderSource(s_shaders[ndx], shaderSource)); |
| if (program.getShaderInfo(s_shaders[ndx]).compileOk) |
| { |
| log << program; |
| log << tcu::TestLog::Message << "Expected program to fail, but compilation passed." << tcu::TestLog::EndMessage; |
| ctx.fail("Shader was not expected to compile."); |
| } |
| ctx.endSection(); |
| } |
| } |
| ctx.endSection(); |
| } |
| |
| void image_store (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType) |
| { |
| const tcu::TextureFormat formats[] = |
| { |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::HALF_FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SNORM_INT8), |
| |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32), |
| |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32) |
| }; |
| |
| const MemoryQualifier memoryOptions[] = |
| { |
| MEMORY_READONLY, |
| MEMORY_BOTH |
| }; |
| |
| ctx.beginSection("It is an error to pass a readonly image to imageStore."); |
| for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx) |
| { |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx) |
| { |
| testShader(ctx, IMAGE_OPERATION_STORE, memoryOptions[memoryNdx], imageType, formats[fmtNdx]); |
| } |
| } |
| ctx.endSection(); |
| } |
| |
| void image_load (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType) |
| { |
| const tcu::TextureFormat formats[] = |
| { |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::HALF_FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SNORM_INT8), |
| |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32), |
| |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32) |
| }; |
| |
| const MemoryQualifier memoryOptions[] = |
| { |
| MEMORY_WRITEONLY, |
| MEMORY_BOTH |
| }; |
| |
| ctx.beginSection("It is an error to pass a writeonly image to imageLoad."); |
| for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx) |
| { |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx) |
| { |
| testShader(ctx, IMAGE_OPERATION_LOAD, memoryOptions[memoryNdx], imageType, formats[fmtNdx]); |
| } |
| } |
| ctx.endSection(); |
| } |
| |
| void image_atomic (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType) |
| { |
| const tcu::TextureFormat formats[] = |
| { |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32), |
| |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32) |
| }; |
| |
| const MemoryQualifier memoryOptions[] = |
| { |
| MEMORY_READONLY, |
| MEMORY_WRITEONLY, |
| MEMORY_BOTH |
| }; |
| |
| const ImageOperation imageOperations[] = |
| { |
| IMAGE_OPERATION_ATOMIC_ADD, |
| IMAGE_OPERATION_ATOMIC_MIN, |
| IMAGE_OPERATION_ATOMIC_MAX, |
| IMAGE_OPERATION_ATOMIC_AND, |
| IMAGE_OPERATION_ATOMIC_OR, |
| IMAGE_OPERATION_ATOMIC_XOR, |
| IMAGE_OPERATION_ATOMIC_COMP_SWAP |
| }; |
| |
| ctx.beginSection("It is an error to pass a writeonly and/or readonly image to imageAtomic*."); |
| for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx) |
| { |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx) |
| { |
| for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(imageOperations); ++functionNdx) |
| { |
| testShader(ctx, imageOperations[functionNdx], memoryOptions[memoryNdx], imageType, formats[fmtNdx]); |
| } |
| } |
| } |
| ctx.endSection(); |
| } |
| |
| void image_atomic_exchange (NegativeTestContext& ctx, glu::TextureTestUtil::TextureType imageType) |
| { |
| const tcu::TextureFormat formats[] = |
| { |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::HALF_FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SNORM_INT8), |
| |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32), |
| |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT16), |
| tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8), |
| tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32) |
| }; |
| |
| const MemoryQualifier memoryOptions[] = |
| { |
| MEMORY_READONLY, |
| MEMORY_WRITEONLY, |
| MEMORY_BOTH |
| }; |
| |
| ctx.beginSection("It is an error to pass a writeonly and/or readonly image to imageAtomic*."); |
| for (int memoryNdx = 0; memoryNdx < DE_LENGTH_OF_ARRAY(memoryOptions); ++memoryNdx) |
| { |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(formats); ++fmtNdx) |
| { |
| testShader(ctx, IMAGE_OPERATION_ATOMIC_EXCHANGE, memoryOptions[memoryNdx], imageType, formats[fmtNdx]); |
| } |
| } |
| ctx.endSection(); |
| } |
| |
| // Re-routing function template for generating the standard negative |
| // test function signature with texture type added. |
| |
| template <int Type> |
| void loadFuncWrapper (NegativeTestContext& ctx) |
| { |
| image_load(ctx, (glu::TextureTestUtil::TextureType)Type); |
| } |
| |
| template <int Type> |
| void storeFuncWrapper (NegativeTestContext& ctx) |
| { |
| image_store(ctx, (glu::TextureTestUtil::TextureType)Type); |
| } |
| |
| template <int Type> |
| void atomicFuncWrapper (NegativeTestContext& ctx) |
| { |
| image_atomic(ctx, (glu::TextureTestUtil::TextureType)Type); |
| } |
| |
| template <int Type> |
| void atomicExchangeFuncWrapper (NegativeTestContext& ctx) |
| { |
| image_atomic_exchange(ctx, (glu::TextureTestUtil::TextureType)Type); |
| } |
| |
| } // anonymous |
| |
| // Set of texture types to create tests for. |
| #define CREATE_TEST_FUNC_PER_TEXTURE_TYPE(NAME, FUNC) const FunctionContainer NAME[] = \ |
| { \ |
| {FUNC<glu::TextureTestUtil::TEXTURETYPE_2D>, "texture_2d", "Texture2D negative tests."}, \ |
| {FUNC<glu::TextureTestUtil::TEXTURETYPE_3D>, "texture_3d", "Texture3D negative tests."}, \ |
| {FUNC<glu::TextureTestUtil::TEXTURETYPE_CUBE>, "cube", "Cube texture negative tests."}, \ |
| {FUNC<glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY>, "2d_array", "2D array texture negative tests."}, \ |
| {FUNC<glu::TextureTestUtil::TEXTURETYPE_BUFFER>, "buffer", "Buffer negative tests."}, \ |
| {FUNC<glu::TextureTestUtil::TEXTURETYPE_CUBE_ARRAY>, "cube_array", "Cube array texture negative tests."} \ |
| } |
| |
| std::vector<FunctionContainer> getNegativeShaderImageLoadTestFunctions (void) |
| { |
| CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, loadFuncWrapper); |
| return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); |
| } |
| |
| std::vector<FunctionContainer> getNegativeShaderImageStoreTestFunctions (void) |
| { |
| CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, storeFuncWrapper); |
| return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); |
| } |
| |
| std::vector<FunctionContainer> getNegativeShaderImageAtomicTestFunctions (void) |
| { |
| CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, atomicFuncWrapper); |
| return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); |
| } |
| |
| std::vector<FunctionContainer> getNegativeShaderImageAtomicExchangeTestFunctions (void) |
| { |
| CREATE_TEST_FUNC_PER_TEXTURE_TYPE(funcs, atomicExchangeFuncWrapper); |
| return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); |
| } |
| |
| } // NegativeTestShared |
| } // Functional |
| } // gles31 |
| } // deqp |