You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
623 lines
20 KiB
623 lines
20 KiB
/*-------------------------------------------------------------------------
|
|
* 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
|