blob: 4533ed53f441ca1c1a8e13f2de217ff04d55b0ba [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.0 Module
* -------------------------------------------------
*
* Copyright 2014 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 Vertex array and buffer tests
*//*--------------------------------------------------------------------*/
#include "es3fVertexArrayTest.hpp"
#include "glsVertexArrayTests.hpp"
#include <sstream>
using namespace deqp::gls;
namespace deqp
{
namespace gles3
{
namespace Functional
{
class SingleVertexArrayUsageGroup : public TestCaseGroup
{
public:
SingleVertexArrayUsageGroup(Context &context, Array::Usage usage);
virtual ~SingleVertexArrayUsageGroup(void);
virtual void init(void);
private:
SingleVertexArrayUsageGroup(const SingleVertexArrayUsageGroup &other);
SingleVertexArrayUsageGroup &operator=(const SingleVertexArrayUsageGroup &other);
Array::Usage m_usage;
};
SingleVertexArrayUsageGroup::SingleVertexArrayUsageGroup(Context &context, Array::Usage usage)
: TestCaseGroup(context, Array::usageTypeToString(usage).c_str(), Array::usageTypeToString(usage).c_str())
, m_usage(usage)
{
}
SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup(void)
{
}
template <class T>
static std::string typeToString(T t)
{
std::stringstream strm;
strm << t;
return strm.str();
}
void SingleVertexArrayUsageGroup::init(void)
{
int counts[] = {1, 256};
int strides[] = {0, -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT,
Array::INPUTTYPE_BYTE};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
{
for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
{
const int stride =
(strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
const bool aligned = (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
const std::string name = "stride" + typeToString(stride) + "_" +
Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_quads" +
typeToString(counts[countNdx]);
MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx], Array::OUTPUTTYPE_VEC2,
Array::STORAGE_BUFFER, m_usage, 2, 0, stride, false,
GLValue::getMinValue(inputTypes[inputTypeNdx]),
GLValue::getMaxValue(inputTypes[inputTypeNdx]));
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = counts[countNdx];
spec.first = 0;
spec.arrays.push_back(arraySpec);
if (aligned)
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
name.c_str()));
}
}
}
}
class SingleVertexArrayUsageTests : public TestCaseGroup
{
public:
SingleVertexArrayUsageTests(Context &context);
virtual ~SingleVertexArrayUsageTests(void);
virtual void init(void);
private:
SingleVertexArrayUsageTests(const SingleVertexArrayUsageTests &other);
SingleVertexArrayUsageTests &operator=(const SingleVertexArrayUsageTests &other);
};
SingleVertexArrayUsageTests::SingleVertexArrayUsageTests(Context &context)
: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
{
}
SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests(void)
{
}
void SingleVertexArrayUsageTests::init(void)
{
// Test usage
Array::Usage usages[] = {Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW,
Array::USAGE_STATIC_COPY, Array::USAGE_STREAM_COPY, Array::USAGE_DYNAMIC_COPY,
Array::USAGE_STATIC_READ, Array::USAGE_STREAM_READ, Array::USAGE_DYNAMIC_READ};
for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
{
addChild(new SingleVertexArrayUsageGroup(m_context, usages[usageNdx]));
}
}
class SingleVertexArrayStrideGroup : public TestCaseGroup
{
public:
SingleVertexArrayStrideGroup(Context &context, Array::InputType type);
virtual ~SingleVertexArrayStrideGroup(void);
virtual void init(void);
private:
SingleVertexArrayStrideGroup(const SingleVertexArrayStrideGroup &other);
SingleVertexArrayStrideGroup &operator=(const SingleVertexArrayStrideGroup &other);
Array::InputType m_type;
};
SingleVertexArrayStrideGroup::SingleVertexArrayStrideGroup(Context &context, Array::InputType type)
: TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
, m_type(type)
{
}
SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup(void)
{
}
void SingleVertexArrayStrideGroup::init(void)
{
Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER};
int counts[] = {1, 256};
int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
{
for (int componentCount = 2; componentCount < 5; componentCount++)
{
for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
{
for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
{
const bool packed =
m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
const int stride = (strides[strideNdx] < 0) ?
((packed) ? (16) : (Array::inputTypeSize(m_type) * componentCount)) :
(strides[strideNdx]);
const int alignment =
(packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
const bool bufferUnaligned =
(storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % alignment) != 0;
std::string name = Array::storageToString(storages[storageNdx]) + "_stride" + typeToString(stride) +
"_components" + typeToString(componentCount) + "_quads" +
typeToString(counts[countNdx]);
if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 ||
m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
componentCount != 4)
continue;
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
m_type, Array::OUTPUTTYPE_VEC4, storages[storageNdx], Array::USAGE_DYNAMIC_DRAW, componentCount,
0, stride, false, GLValue::getMinValue(m_type), GLValue::getMaxValue(m_type));
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = counts[countNdx];
spec.first = 0;
spec.arrays.push_back(arraySpec);
if (!bufferUnaligned)
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
name.c_str()));
}
}
}
}
}
class SingleVertexArrayStrideTests : public TestCaseGroup
{
public:
SingleVertexArrayStrideTests(Context &context);
virtual ~SingleVertexArrayStrideTests(void);
virtual void init(void);
private:
SingleVertexArrayStrideTests(const SingleVertexArrayStrideTests &other);
SingleVertexArrayStrideTests &operator=(const SingleVertexArrayStrideTests &other);
};
SingleVertexArrayStrideTests::SingleVertexArrayStrideTests(Context &context)
: TestCaseGroup(context, "strides", "Single stride vertex atribute")
{
}
SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests(void)
{
}
void SingleVertexArrayStrideTests::init(void)
{
Array::InputType inputTypes[] = {
Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE,
/*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED,
Array::INPUTTYPE_INT_2_10_10_10};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
addChild(new SingleVertexArrayStrideGroup(m_context, inputTypes[inputTypeNdx]));
}
}
class SingleVertexArrayFirstGroup : public TestCaseGroup
{
public:
SingleVertexArrayFirstGroup(Context &context, Array::InputType type);
virtual ~SingleVertexArrayFirstGroup(void);
virtual void init(void);
private:
SingleVertexArrayFirstGroup(const SingleVertexArrayFirstGroup &other);
SingleVertexArrayFirstGroup &operator=(const SingleVertexArrayFirstGroup &other);
Array::InputType m_type;
};
SingleVertexArrayFirstGroup::SingleVertexArrayFirstGroup(Context &context, Array::InputType type)
: TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
, m_type(type)
{
}
SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup(void)
{
}
void SingleVertexArrayFirstGroup::init(void)
{
int counts[] = {5, 256};
int firsts[] = {6, 24};
int offsets[] = {1, 16, 17};
int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
{
for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
{
for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
{
for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++)
{
const bool packed =
m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
const int componentCount = (packed) ? (4) : (2);
const int stride = (strides[strideNdx] < 0) ?
((packed) ? (8) : (Array::inputTypeSize(m_type) * componentCount)) :
(strides[strideNdx]);
const int alignment =
(packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
const bool aligned = ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
std::string name = "first" + typeToString(firsts[firstNdx]) + "_offset" +
typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" +
typeToString(counts[countNdx]);
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
m_type, Array::OUTPUTTYPE_VEC2, Array::STORAGE_BUFFER, Array::USAGE_DYNAMIC_DRAW,
componentCount, offsets[offsetNdx], stride, false, GLValue::getMinValue(m_type),
GLValue::getMaxValue(m_type));
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = counts[countNdx];
spec.first = firsts[firstNdx];
spec.arrays.push_back(arraySpec);
if (aligned)
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
name.c_str()));
}
}
}
}
}
class SingleVertexArrayFirstTests : public TestCaseGroup
{
public:
SingleVertexArrayFirstTests(Context &context);
virtual ~SingleVertexArrayFirstTests(void);
virtual void init(void);
private:
SingleVertexArrayFirstTests(const SingleVertexArrayFirstTests &other);
SingleVertexArrayFirstTests &operator=(const SingleVertexArrayFirstTests &other);
};
SingleVertexArrayFirstTests::SingleVertexArrayFirstTests(Context &context)
: TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays")
{
}
SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests(void)
{
}
void SingleVertexArrayFirstTests::init(void)
{
// Test offset with different input types, component counts and storage, Usage(?)
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
addChild(new SingleVertexArrayFirstGroup(m_context, inputTypes[inputTypeNdx]));
}
}
class SingleVertexArrayOffsetGroup : public TestCaseGroup
{
public:
SingleVertexArrayOffsetGroup(Context &context, Array::InputType type);
virtual ~SingleVertexArrayOffsetGroup(void);
virtual void init(void);
private:
SingleVertexArrayOffsetGroup(const SingleVertexArrayOffsetGroup &other);
SingleVertexArrayOffsetGroup &operator=(const SingleVertexArrayOffsetGroup &other);
Array::InputType m_type;
};
SingleVertexArrayOffsetGroup::SingleVertexArrayOffsetGroup(Context &context, Array::InputType type)
: TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
, m_type(type)
{
}
SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup(void)
{
}
void SingleVertexArrayOffsetGroup::init(void)
{
int counts[] = {1, 256};
int offsets[] = {1, 4, 17, 32};
int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
{
for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
{
for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
{
const bool packed =
m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
const int componentCount = (packed) ? (4) : (2);
const int stride =
(strides[strideNdx] < 0 ? Array::inputTypeSize(m_type) * componentCount : strides[strideNdx]);
const int alignment =
(packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
const bool aligned = ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
const std::string name = "offset" + typeToString(offsets[offsetNdx]) + "_stride" +
typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
m_type, Array::OUTPUTTYPE_VEC2, Array::STORAGE_BUFFER, Array::USAGE_DYNAMIC_DRAW, componentCount,
offsets[offsetNdx], stride, false, GLValue::getMinValue(m_type), GLValue::getMaxValue(m_type));
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = counts[countNdx];
spec.first = 0;
spec.arrays.push_back(arraySpec);
if (aligned)
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
name.c_str()));
}
}
}
}
class SingleVertexArrayOffsetTests : public TestCaseGroup
{
public:
SingleVertexArrayOffsetTests(Context &context);
virtual ~SingleVertexArrayOffsetTests(void);
virtual void init(void);
private:
SingleVertexArrayOffsetTests(const SingleVertexArrayOffsetTests &other);
SingleVertexArrayOffsetTests &operator=(const SingleVertexArrayOffsetTests &other);
};
SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests(Context &context)
: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
{
}
SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests(void)
{
}
void SingleVertexArrayOffsetTests::init(void)
{
// Test offset with different input types, component counts and storage, Usage(?)
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
addChild(new SingleVertexArrayOffsetGroup(m_context, inputTypes[inputTypeNdx]));
}
}
class SingleVertexArrayNormalizeGroup : public TestCaseGroup
{
public:
SingleVertexArrayNormalizeGroup(Context &context, Array::InputType type);
virtual ~SingleVertexArrayNormalizeGroup(void);
virtual void init(void);
private:
SingleVertexArrayNormalizeGroup(const SingleVertexArrayNormalizeGroup &other);
SingleVertexArrayNormalizeGroup &operator=(const SingleVertexArrayNormalizeGroup &other);
Array::InputType m_type;
};
SingleVertexArrayNormalizeGroup::SingleVertexArrayNormalizeGroup(Context &context, Array::InputType type)
: TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
, m_type(type)
{
}
SingleVertexArrayNormalizeGroup::~SingleVertexArrayNormalizeGroup(void)
{
}
void SingleVertexArrayNormalizeGroup::init(void)
{
int counts[] = {1, 256};
for (int componentCount = 2; componentCount < 5; componentCount++)
{
for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
{
if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
componentCount != 4)
continue;
std::string name = "components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);
MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type, Array::OUTPUTTYPE_VEC4, Array::STORAGE_USER,
Array::USAGE_DYNAMIC_DRAW, componentCount, 0, 0, true,
GLValue::getMinValue(m_type), GLValue::getMaxValue(m_type));
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = counts[countNdx];
spec.first = 0;
spec.arrays.push_back(arraySpec);
addChild(
new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
}
}
}
class SingleVertexArrayNormalizeTests : public TestCaseGroup
{
public:
SingleVertexArrayNormalizeTests(Context &context);
virtual ~SingleVertexArrayNormalizeTests(void);
virtual void init(void);
private:
SingleVertexArrayNormalizeTests(const SingleVertexArrayNormalizeTests &other);
SingleVertexArrayNormalizeTests &operator=(const SingleVertexArrayNormalizeTests &other);
};
SingleVertexArrayNormalizeTests::SingleVertexArrayNormalizeTests(Context &context)
: TestCaseGroup(context, "normalize", "Single normalize vertex atribute")
{
}
SingleVertexArrayNormalizeTests::~SingleVertexArrayNormalizeTests(void)
{
}
void SingleVertexArrayNormalizeTests::init(void)
{
// Test normalization with different input types, component counts and storage
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT,
Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT,
Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED,
Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT,
Array::INPUTTYPE_HALF, Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
Array::INPUTTYPE_INT_2_10_10_10};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
addChild(new SingleVertexArrayNormalizeGroup(m_context, inputTypes[inputTypeNdx]));
}
}
class SingleVertexArrayOutputTypeGroup : public TestCaseGroup
{
public:
SingleVertexArrayOutputTypeGroup(Context &context, Array::InputType type);
virtual ~SingleVertexArrayOutputTypeGroup(void);
virtual void init(void);
private:
SingleVertexArrayOutputTypeGroup(const SingleVertexArrayOutputTypeGroup &other);
SingleVertexArrayOutputTypeGroup &operator=(const SingleVertexArrayOutputTypeGroup &other);
Array::InputType m_type;
};
SingleVertexArrayOutputTypeGroup::SingleVertexArrayOutputTypeGroup(Context &context, Array::InputType type)
: TestCaseGroup(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
, m_type(type)
{
}
SingleVertexArrayOutputTypeGroup::~SingleVertexArrayOutputTypeGroup(void)
{
}
void SingleVertexArrayOutputTypeGroup::init(void)
{
Array::OutputType outputTypes[] = {Array::OUTPUTTYPE_VEC2, Array::OUTPUTTYPE_VEC3, Array::OUTPUTTYPE_VEC4,
Array::OUTPUTTYPE_IVEC2, Array::OUTPUTTYPE_IVEC3, Array::OUTPUTTYPE_IVEC4,
Array::OUTPUTTYPE_UVEC2, Array::OUTPUTTYPE_UVEC3, Array::OUTPUTTYPE_UVEC4};
Array::Storage storages[] = {Array::STORAGE_USER};
int counts[] = {1, 256};
for (int outputTypeNdx = 0; outputTypeNdx < DE_LENGTH_OF_ARRAY(outputTypes); outputTypeNdx++)
{
for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
{
for (int componentCount = 2; componentCount < 5; componentCount++)
{
for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
{
std::string name = "components" + typeToString(componentCount) + "_" +
Array::outputTypeToString(outputTypes[outputTypeNdx]) + "_quads" +
typeToString(counts[countNdx]);
const bool inputIsSignedInteger = m_type == Array::INPUTTYPE_INT ||
m_type == Array::INPUTTYPE_SHORT ||
m_type == Array::INPUTTYPE_BYTE;
const bool inputIsUnignedInteger = m_type == Array::INPUTTYPE_UNSIGNED_INT ||
m_type == Array::INPUTTYPE_UNSIGNED_SHORT ||
m_type == Array::INPUTTYPE_UNSIGNED_BYTE;
const bool outputIsSignedInteger = outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC2 ||
outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC3 ||
outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC4;
const bool outputIsUnsignedInteger = outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC2 ||
outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC3 ||
outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC4;
// If input type is float type and output type is int type skip
if ((m_type == Array::INPUTTYPE_FLOAT || m_type == Array::INPUTTYPE_HALF ||
m_type == Array::INPUTTYPE_FIXED) &&
(outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
continue;
if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 ||
m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
(outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
continue;
if ((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 ||
m_type == Array::INPUTTYPE_INT_2_10_10_10) &&
componentCount != 4)
continue;
// Loading signed data as unsigned causes undefined values and vice versa
if (inputIsSignedInteger && outputIsUnsignedInteger)
continue;
if (inputIsUnignedInteger && outputIsSignedInteger)
continue;
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
m_type, outputTypes[outputTypeNdx], storages[storageNdx], Array::USAGE_DYNAMIC_DRAW,
componentCount, 0, 0, false, GLValue::getMinValue(m_type), GLValue::getMaxValue(m_type));
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = counts[countNdx];
spec.first = 0;
spec.arrays.push_back(arraySpec);
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(),
name.c_str()));
}
}
}
}
}
class SingleVertexArrayOutputTypeTests : public TestCaseGroup
{
public:
SingleVertexArrayOutputTypeTests(Context &context);
virtual ~SingleVertexArrayOutputTypeTests(void);
virtual void init(void);
private:
SingleVertexArrayOutputTypeTests(const SingleVertexArrayOutputTypeTests &other);
SingleVertexArrayOutputTypeTests &operator=(const SingleVertexArrayOutputTypeTests &other);
};
SingleVertexArrayOutputTypeTests::SingleVertexArrayOutputTypeTests(Context &context)
: TestCaseGroup(context, "output_types", "Single output type vertex atribute")
{
}
SingleVertexArrayOutputTypeTests::~SingleVertexArrayOutputTypeTests(void)
{
}
void SingleVertexArrayOutputTypeTests::init(void)
{
// Test output types with different input types, component counts and storage, Usage?, Precision?, float?
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT,
Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT,
Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED,
Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT,
Array::INPUTTYPE_HALF, Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
Array::INPUTTYPE_INT_2_10_10_10};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
addChild(new SingleVertexArrayOutputTypeGroup(m_context, inputTypes[inputTypeNdx]));
}
}
class SingleVertexArrayTestGroup : public TestCaseGroup
{
public:
SingleVertexArrayTestGroup(Context &context);
virtual ~SingleVertexArrayTestGroup(void);
virtual void init(void);
private:
SingleVertexArrayTestGroup(const SingleVertexArrayTestGroup &other);
SingleVertexArrayTestGroup &operator=(const SingleVertexArrayTestGroup &other);
};
SingleVertexArrayTestGroup::SingleVertexArrayTestGroup(Context &context)
: TestCaseGroup(context, "single_attribute", "Single vertex atribute")
{
}
SingleVertexArrayTestGroup::~SingleVertexArrayTestGroup(void)
{
}
void SingleVertexArrayTestGroup::init(void)
{
addChild(new SingleVertexArrayStrideTests(m_context));
addChild(new SingleVertexArrayNormalizeTests(m_context));
addChild(new SingleVertexArrayOutputTypeTests(m_context));
addChild(new SingleVertexArrayUsageTests(m_context));
addChild(new SingleVertexArrayOffsetTests(m_context));
addChild(new SingleVertexArrayFirstTests(m_context));
}
class MultiVertexArrayCountTests : public TestCaseGroup
{
public:
MultiVertexArrayCountTests(Context &context);
virtual ~MultiVertexArrayCountTests(void);
virtual void init(void);
private:
MultiVertexArrayCountTests(const MultiVertexArrayCountTests &other);
MultiVertexArrayCountTests &operator=(const MultiVertexArrayCountTests &other);
std::string getTestName(const MultiVertexArrayTest::Spec &spec);
};
MultiVertexArrayCountTests::MultiVertexArrayCountTests(Context &context)
: TestCaseGroup(context, "attribute_count", "Attribute counts")
{
}
MultiVertexArrayCountTests::~MultiVertexArrayCountTests(void)
{
}
std::string MultiVertexArrayCountTests::getTestName(const MultiVertexArrayTest::Spec &spec)
{
std::stringstream name;
name << spec.arrays.size();
return name.str();
}
void MultiVertexArrayCountTests::init(void)
{
// Test attribute counts
int arrayCounts[] = {2, 3, 4, 5, 6, 7, 8};
for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
{
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = 256;
spec.first = 0;
for (int arrayNdx = 0; arrayNdx < arrayCounts[arrayCountNdx]; arrayNdx++)
{
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
Array::INPUTTYPE_FLOAT, Array::OUTPUTTYPE_VEC2, Array::STORAGE_USER, Array::USAGE_DYNAMIC_DRAW, 2, 0, 0,
false, GLValue::getMinValue(Array::INPUTTYPE_FLOAT), GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
spec.arrays.push_back(arraySpec);
}
std::string name = getTestName(spec);
std::string desc = getTestName(spec);
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
}
}
class MultiVertexArrayStorageTests : public TestCaseGroup
{
public:
MultiVertexArrayStorageTests(Context &context);
virtual ~MultiVertexArrayStorageTests(void);
virtual void init(void);
private:
MultiVertexArrayStorageTests(const MultiVertexArrayStorageTests &other);
MultiVertexArrayStorageTests &operator=(const MultiVertexArrayStorageTests &other);
void addStorageCases(MultiVertexArrayTest::Spec spec, int depth);
std::string getTestName(const MultiVertexArrayTest::Spec &spec);
};
MultiVertexArrayStorageTests::MultiVertexArrayStorageTests(Context &context)
: TestCaseGroup(context, "storage", "Attribute storages")
{
}
MultiVertexArrayStorageTests::~MultiVertexArrayStorageTests(void)
{
}
std::string MultiVertexArrayStorageTests::getTestName(const MultiVertexArrayTest::Spec &spec)
{
std::stringstream name;
name << spec.arrays.size();
for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
{
name << "_" << Array::storageToString(spec.arrays[arrayNdx].storage);
}
return name.str();
}
void MultiVertexArrayStorageTests::addStorageCases(MultiVertexArrayTest::Spec spec, int depth)
{
if (depth == 0)
{
// Skip trivial case, used elsewhere
bool ok = false;
for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
{
if (spec.arrays[arrayNdx].storage != Array::STORAGE_USER)
{
ok = true;
break;
}
}
if (!ok)
return;
std::string name = getTestName(spec);
std::string desc = getTestName(spec);
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
return;
}
Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER};
for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
{
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
Array::INPUTTYPE_FLOAT, Array::OUTPUTTYPE_VEC2, storages[storageNdx], Array::USAGE_DYNAMIC_DRAW, 2, 0, 0,
false, GLValue::getMinValue(Array::INPUTTYPE_FLOAT), GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
MultiVertexArrayTest::Spec _spec = spec;
_spec.arrays.push_back(arraySpec);
addStorageCases(_spec, depth - 1);
}
}
void MultiVertexArrayStorageTests::init(void)
{
// Test different storages
int arrayCounts[] = {3};
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = 256;
spec.first = 0;
for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
addStorageCases(spec, arrayCounts[arrayCountNdx]);
}
class MultiVertexArrayStrideTests : public TestCaseGroup
{
public:
MultiVertexArrayStrideTests(Context &context);
virtual ~MultiVertexArrayStrideTests(void);
virtual void init(void);
private:
MultiVertexArrayStrideTests(const MultiVertexArrayStrideTests &other);
MultiVertexArrayStrideTests &operator=(const MultiVertexArrayStrideTests &other);
void addStrideCases(MultiVertexArrayTest::Spec spec, int depth);
std::string getTestName(const MultiVertexArrayTest::Spec &spec);
};
MultiVertexArrayStrideTests::MultiVertexArrayStrideTests(Context &context) : TestCaseGroup(context, "stride", "Strides")
{
}
MultiVertexArrayStrideTests::~MultiVertexArrayStrideTests(void)
{
}
std::string MultiVertexArrayStrideTests::getTestName(const MultiVertexArrayTest::Spec &spec)
{
std::stringstream name;
name << spec.arrays.size();
for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
{
name << "_" << Array::inputTypeToString(spec.arrays[arrayNdx].inputType) << spec.arrays[arrayNdx].componentCount
<< "_" << spec.arrays[arrayNdx].stride;
}
return name.str();
}
void MultiVertexArrayStrideTests::init(void)
{
// Test different strides, with multiple arrays, input types??
int arrayCounts[] = {3};
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = 256;
spec.first = 0;
for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
addStrideCases(spec, arrayCounts[arrayCountNdx]);
}
void MultiVertexArrayStrideTests::addStrideCases(MultiVertexArrayTest::Spec spec, int depth)
{
if (depth == 0)
{
std::string name = getTestName(spec);
std::string desc = getTestName(spec);
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
return;
}
int strides[] = {0, -1, 17, 32};
for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
{
const int componentCount = 2;
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
Array::INPUTTYPE_FLOAT, Array::OUTPUTTYPE_VEC2, Array::STORAGE_USER, Array::USAGE_DYNAMIC_DRAW,
componentCount, 0,
(strides[strideNdx] >= 0 ? strides[strideNdx] :
componentCount * Array::inputTypeSize(Array::INPUTTYPE_FLOAT)),
false, GLValue::getMinValue(Array::INPUTTYPE_FLOAT), GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
MultiVertexArrayTest::Spec _spec = spec;
_spec.arrays.push_back(arraySpec);
addStrideCases(_spec, depth - 1);
}
}
class MultiVertexArrayOutputTests : public TestCaseGroup
{
public:
MultiVertexArrayOutputTests(Context &context);
virtual ~MultiVertexArrayOutputTests(void);
virtual void init(void);
private:
MultiVertexArrayOutputTests(const MultiVertexArrayOutputTests &other);
MultiVertexArrayOutputTests &operator=(const MultiVertexArrayOutputTests &other);
void addInputTypeCases(MultiVertexArrayTest::Spec spec, int depth);
std::string getTestName(const MultiVertexArrayTest::Spec &spec);
};
MultiVertexArrayOutputTests::MultiVertexArrayOutputTests(Context &context)
: TestCaseGroup(context, "input_types", "input types")
{
}
MultiVertexArrayOutputTests::~MultiVertexArrayOutputTests(void)
{
}
std::string MultiVertexArrayOutputTests::getTestName(const MultiVertexArrayTest::Spec &spec)
{
std::stringstream name;
name << spec.arrays.size();
for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
{
name << "_" << Array::inputTypeToString(spec.arrays[arrayNdx].inputType) << spec.arrays[arrayNdx].componentCount
<< "_" << Array::outputTypeToString(spec.arrays[arrayNdx].outputType);
}
return name.str();
}
void MultiVertexArrayOutputTests::init(void)
{
// Test different input types, with multiple arrays
int arrayCounts[] = {3};
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = 256;
spec.first = 0;
for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
addInputTypeCases(spec, arrayCounts[arrayCountNdx]);
}
void MultiVertexArrayOutputTests::addInputTypeCases(MultiVertexArrayTest::Spec spec, int depth)
{
if (depth == 0)
{
std::string name = getTestName(spec);
std::string desc = getTestName(spec);
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
return;
}
Array::InputType inputTypes[] = {Array::INPUTTYPE_FIXED, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_SHORT,
Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
MultiVertexArrayTest::Spec::ArraySpec arraySpec(
inputTypes[inputTypeNdx], Array::OUTPUTTYPE_VEC2, Array::STORAGE_USER, Array::USAGE_DYNAMIC_DRAW, 2, 0, 0,
false, GLValue::getMinValue(inputTypes[inputTypeNdx]), GLValue::getMaxValue(inputTypes[inputTypeNdx]));
MultiVertexArrayTest::Spec _spec = spec;
_spec.arrays.push_back(arraySpec);
addInputTypeCases(_spec, depth - 1);
}
}
class MultiVertexArrayTestGroup : public TestCaseGroup
{
public:
MultiVertexArrayTestGroup(Context &context);
virtual ~MultiVertexArrayTestGroup(void);
virtual void init(void);
private:
MultiVertexArrayTestGroup(const MultiVertexArrayTestGroup &other);
MultiVertexArrayTestGroup &operator=(const MultiVertexArrayTestGroup &other);
};
MultiVertexArrayTestGroup::MultiVertexArrayTestGroup(Context &context)
: TestCaseGroup(context, "multiple_attributes", "Multiple vertex atributes")
{
}
MultiVertexArrayTestGroup::~MultiVertexArrayTestGroup(void)
{
}
void MultiVertexArrayTestGroup::init(void)
{
addChild(new MultiVertexArrayCountTests(m_context));
addChild(new MultiVertexArrayStorageTests(m_context));
addChild(new MultiVertexArrayStrideTests(m_context));
addChild(new MultiVertexArrayOutputTests(m_context));
}
VertexArrayTestGroup::VertexArrayTestGroup(Context &context)
: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
{
}
VertexArrayTestGroup::~VertexArrayTestGroup(void)
{
}
void VertexArrayTestGroup::init(void)
{
addChild(new SingleVertexArrayTestGroup(m_context));
addChild(new MultiVertexArrayTestGroup(m_context));
}
} // namespace Functional
} // namespace gles3
} // namespace deqp