/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 2.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 unaligned access stress tests
*//*--------------------------------------------------------------------*/
#include "es2sVertexArrayTests.hpp"
#include "glsVertexArrayTests.hpp"
#include "glwEnums.hpp"
using namespace deqp::gls;
namespace deqp
{
namespace gles2
{
namespace Stress
{
namespace
{
template<class T>
static std::string typeToString (T t)
{
std::stringstream strm;
strm << t;
return strm.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};
int counts[] = {1, 256};
int strides[] = {17};
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++)
{
for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
{
const int componentCount = 2;
const int stride = (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * componentCount : strides[strideNdx]);
const bool aligned = (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
Array::OUTPUTTYPE_VEC2,
Array::STORAGE_BUFFER,
usages[usageNdx],
componentCount,
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);
std::string name = spec.getName();
if (!aligned)
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)
{
// Test strides with different input types, component counts and storage, Usage(?)
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED};
Array::Storage storages[] = {Array::STORAGE_BUFFER};
int counts[] = {1, 256};
int strides[] = {17};
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
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 int stride = (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * componentCount : strides[strideNdx]);
const bool bufferUnaligned = (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) != 0;
MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
Array::OUTPUTTYPE_VEC4,
storages[storageNdx],
Array::USAGE_DYNAMIC_DRAW,
componentCount,
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);
std::string name = spec.getName();
if (bufferUnaligned)
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 atribute different first values")
{
}
SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
{
}
void SingleVertexArrayFirstTests::init (void)
{
// Test strides with different input types, component counts and storage, Usage(?)
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_FIXED};
int counts[] = {5, 256};
int firsts[] = {6, 24};
int offsets[] = {1, 17};
int strides[] = {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
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 int stride = (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
const bool aligned = ((stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0) && (offsets[offsetNdx] % Array::inputTypeSize(inputTypes[inputTypeNdx]) == 0);
MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
Array::OUTPUTTYPE_VEC2,
Array::STORAGE_BUFFER,
Array::USAGE_DYNAMIC_DRAW,
2,
offsets[offsetNdx],
stride,
false,
GLValue::getMinValue(inputTypes[inputTypeNdx]),
GLValue::getMaxValue(inputTypes[inputTypeNdx]));
MultiVertexArrayTest::Spec spec;
spec.primitive = Array::PRIMITIVE_TRIANGLES;
spec.drawCount = counts[countNdx];
spec.first = firsts[firstNdx];
spec.arrays.push_back(arraySpec);
std::string name = Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
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 strides with different input types, component counts and storage, Usage(?)
Array::InputType inputTypes[] = {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_FIXED};
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 inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
{
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 int stride = (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
const bool aligned = ((stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0) && ((offsets[offsetNdx] % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0);
MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
Array::OUTPUTTYPE_VEC2,
Array::STORAGE_BUFFER,
Array::USAGE_DYNAMIC_DRAW,
2,
offsets[offsetNdx],
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);
std::string name = spec.getName();
if (!aligned)
addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
}
}
}
}
}
} // anonymous
VertexArrayTests::VertexArrayTests (Context& context)
: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
{
}
VertexArrayTests::~VertexArrayTests (void)
{
}
void VertexArrayTests::init (void)
{
tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "single_attribute", "Single attribute");
addChild(group);
// .single_attribute
{
group->addChild(new SingleVertexArrayStrideTests(m_context));
group->addChild(new SingleVertexArrayUsageTests(m_context));
group->addChild(new SingleVertexArrayOffsetTests(m_context));
group->addChild(new SingleVertexArrayFirstTests(m_context));
}
}
} // Stress
} // gles2
} // deqp