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.
665 lines
23 KiB
665 lines
23 KiB
/*------------------------------------------------------------------------- |
|
* 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 Default vertex attribute test |
|
*//*--------------------------------------------------------------------*/ |
|
|
|
#include "es3fDefaultVertexAttributeTests.hpp" |
|
#include "tcuVector.hpp" |
|
#include "tcuRenderTarget.hpp" |
|
#include "tcuSurface.hpp" |
|
#include "tcuTextureUtil.hpp" |
|
#include "gluRenderContext.hpp" |
|
#include "gluCallLogWrapper.hpp" |
|
#include "gluShaderProgram.hpp" |
|
#include "gluObjectWrapper.hpp" |
|
#include "gluPixelTransfer.hpp" |
|
#include "glwEnums.hpp" |
|
#include "glwFunctions.hpp" |
|
#include "deMath.h" |
|
#include "deStringUtil.hpp" |
|
#include "deString.h" |
|
|
|
#include <limits> |
|
|
|
namespace deqp |
|
{ |
|
namespace gles3 |
|
{ |
|
namespace Functional |
|
{ |
|
namespace |
|
{ |
|
|
|
static const int s_valueRange = 10; |
|
|
|
static const char* const s_passThroughFragmentShaderSource = "#version 300 es\n" |
|
"layout(location = 0) out mediump vec4 fragColor;\n" |
|
"in mediump vec4 v_color;\n" |
|
"void main (void)\n" |
|
"{\n" |
|
" fragColor = v_color;\n" |
|
"}\n"; |
|
|
|
template <typename T1, int S1, typename T2, int S2> |
|
tcu::Vector<T1, S1> convertToTypeVec (const tcu::Vector<T2, S2>& v) |
|
{ |
|
tcu::Vector<T1, S1> retVal; |
|
|
|
for (int ndx = 0; ndx < S1; ++ndx) |
|
retVal[ndx] = T1(0); |
|
|
|
if (S1 == 4) |
|
retVal[3] = T1(1); |
|
|
|
for (int ndx = 0; ndx < de::min(S1, S2); ++ndx) |
|
retVal[ndx] = T1(v[ndx]); |
|
|
|
return retVal; |
|
} |
|
|
|
class FloatLoader |
|
{ |
|
public: |
|
virtual ~FloatLoader (void) {}; |
|
|
|
// returns the value loaded |
|
virtual tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const = 0; |
|
}; |
|
|
|
#define GEN_DIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME, VALUES) \ |
|
class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader \ |
|
{ \ |
|
public: \ |
|
enum \ |
|
{ \ |
|
NORMALIZING = 0, \ |
|
}; \ |
|
enum \ |
|
{ \ |
|
COMPONENTS = (COMPS) \ |
|
}; \ |
|
typedef TYPE Type; \ |
|
\ |
|
tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const \ |
|
{ \ |
|
tcu::Vector<TYPE, COMPONENTS> value; \ |
|
value = convertToTypeVec<Type, COMPONENTS>(v); \ |
|
\ |
|
gl.glVertexAttrib ##COMPS ##TYPECODE VALUES; \ |
|
return convertToTypeVec<float, 4>(value); \ |
|
} \ |
|
\ |
|
static const char* getCaseName (void) \ |
|
{ \ |
|
return CASENAME; \ |
|
} \ |
|
\ |
|
static const char* getName (void) \ |
|
{ \ |
|
return "VertexAttrib" #COMPS #TYPECODE; \ |
|
} \ |
|
} |
|
|
|
#define GEN_INDIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME) \ |
|
class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader \ |
|
{ \ |
|
public: \ |
|
enum \ |
|
{ \ |
|
NORMALIZING = 0, \ |
|
}; \ |
|
enum \ |
|
{ \ |
|
COMPONENTS = (COMPS) \ |
|
}; \ |
|
typedef TYPE Type; \ |
|
\ |
|
tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const \ |
|
{ \ |
|
tcu::Vector<TYPE, COMPONENTS> value; \ |
|
value = convertToTypeVec<Type, COMPONENTS>(v); \ |
|
\ |
|
gl.glVertexAttrib ##COMPS ##TYPECODE (index, value.getPtr()); \ |
|
return convertToTypeVec<float, 4>(value); \ |
|
} \ |
|
\ |
|
static const char* getCaseName (void) \ |
|
{ \ |
|
return CASENAME; \ |
|
} \ |
|
\ |
|
static const char* getName (void) \ |
|
{ \ |
|
return "VertexAttrib" #COMPS #TYPECODE; \ |
|
} \ |
|
} |
|
|
|
#define GEN_DIRECT_INTEGER_LOADER(TYPE, COMPS, TYPECODE, CASENAME, VALUES) \ |
|
class LoaderVertexAttribI##COMPS##TYPECODE : public FloatLoader \ |
|
{ \ |
|
public: \ |
|
enum \ |
|
{ \ |
|
NORMALIZING = 0, \ |
|
}; \ |
|
enum \ |
|
{ \ |
|
COMPONENTS = (COMPS) \ |
|
}; \ |
|
typedef TYPE Type; \ |
|
\ |
|
tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const \ |
|
{ \ |
|
tcu::Vector<TYPE, COMPONENTS> value; \ |
|
value = convertToTypeVec<Type, COMPONENTS>(v); \ |
|
\ |
|
gl.glVertexAttribI ##COMPS ##TYPECODE VALUES; \ |
|
return convertToTypeVec<float, 4>(value); \ |
|
} \ |
|
\ |
|
static const char* getCaseName (void) \ |
|
{ \ |
|
return CASENAME; \ |
|
} \ |
|
\ |
|
static const char* getName (void) \ |
|
{ \ |
|
return "VertexAttrib" #COMPS #TYPECODE; \ |
|
} \ |
|
} |
|
|
|
#define GEN_INDIRECT_INTEGER_LOADER(TYPE, COMPS, TYPECODE, CASENAME) \ |
|
class LoaderVertexAttribI##COMPS##TYPECODE : public FloatLoader \ |
|
{ \ |
|
public: \ |
|
enum \ |
|
{ \ |
|
NORMALIZING = 0, \ |
|
}; \ |
|
enum \ |
|
{ \ |
|
COMPONENTS = (COMPS) \ |
|
}; \ |
|
typedef TYPE Type; \ |
|
\ |
|
tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const \ |
|
{ \ |
|
tcu::Vector<TYPE, COMPONENTS> value; \ |
|
value = convertToTypeVec<Type, COMPONENTS>(v); \ |
|
\ |
|
gl.glVertexAttribI ##COMPS ##TYPECODE (index, value.getPtr()); \ |
|
return convertToTypeVec<float, 4>(value); \ |
|
} \ |
|
\ |
|
static const char* getCaseName (void) \ |
|
{ \ |
|
return CASENAME; \ |
|
} \ |
|
\ |
|
static const char* getName (void) \ |
|
{ \ |
|
return "VertexAttrib" #COMPS #TYPECODE; \ |
|
} \ |
|
} |
|
|
|
GEN_DIRECT_FLOAT_LOADER(float, 1, f, "vertex_attrib_1f", (index, value.x())); |
|
GEN_DIRECT_FLOAT_LOADER(float, 2, f, "vertex_attrib_2f", (index, value.x(), value.y())); |
|
GEN_DIRECT_FLOAT_LOADER(float, 3, f, "vertex_attrib_3f", (index, value.x(), value.y(), value.z())); |
|
GEN_DIRECT_FLOAT_LOADER(float, 4, f, "vertex_attrib_4f", (index, value.x(), value.y(), value.z(), value.w())); |
|
|
|
GEN_INDIRECT_FLOAT_LOADER(float, 1, fv, "vertex_attrib_1fv"); |
|
GEN_INDIRECT_FLOAT_LOADER(float, 2, fv, "vertex_attrib_2fv"); |
|
GEN_INDIRECT_FLOAT_LOADER(float, 3, fv, "vertex_attrib_3fv"); |
|
GEN_INDIRECT_FLOAT_LOADER(float, 4, fv, "vertex_attrib_4fv"); |
|
|
|
GEN_DIRECT_INTEGER_LOADER(deInt32, 4, i, "vertex_attribi_4i", (index, value.x(), value.y(), value.z(), value.w())); |
|
GEN_INDIRECT_INTEGER_LOADER(deInt32, 4, iv, "vertex_attribi_4iv"); |
|
|
|
GEN_DIRECT_INTEGER_LOADER(deUint32, 4, ui, "vertex_attribi_4ui", (index, value.x(), value.y(), value.z(), value.w())); |
|
GEN_INDIRECT_INTEGER_LOADER(deUint32, 4, uiv, "vertex_attribi_4uiv"); |
|
|
|
class AttributeCase : public TestCase |
|
{ |
|
AttributeCase (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType); |
|
public: |
|
template<typename LoaderType> |
|
static AttributeCase* create (Context& ctx, glu::DataType dataType); |
|
~AttributeCase (void); |
|
|
|
private: |
|
void init (void); |
|
void deinit (void); |
|
IterateResult iterate (void); |
|
|
|
glu::DataType getTargetType (void) const; |
|
std::string genVertexSource (void) const; |
|
bool renderWithValue (const tcu::Vec4& v); |
|
tcu::Vec4 computeColor (const tcu::Vec4& value); |
|
bool verifyUnicoloredBuffer (const tcu::Surface& scene, const tcu::Vec4& refValue); |
|
|
|
const bool m_normalizing; |
|
const bool m_useNegativeValues; |
|
const char* const m_funcName; |
|
const glu::DataType m_dataType; |
|
const FloatLoader* m_loader; |
|
glu::ShaderProgram* m_program; |
|
deUint32 m_bufID; |
|
bool m_allIterationsPassed; |
|
int m_iteration; |
|
|
|
enum |
|
{ |
|
RENDER_SIZE = 32 |
|
}; |
|
}; |
|
|
|
AttributeCase::AttributeCase (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType) |
|
: TestCase (ctx, name, desc) |
|
, m_normalizing (normalizing) |
|
, m_useNegativeValues (useNegative) |
|
, m_funcName (funcName) |
|
, m_dataType (dataType) |
|
, m_loader (DE_NULL) |
|
, m_program (DE_NULL) |
|
, m_bufID (0) |
|
, m_allIterationsPassed (true) |
|
, m_iteration (0) |
|
{ |
|
} |
|
|
|
template<typename LoaderType> |
|
AttributeCase* AttributeCase::create (Context& ctx, glu::DataType dataType) |
|
{ |
|
AttributeCase* retVal = new AttributeCase(ctx, |
|
LoaderType::getCaseName(), |
|
(std::string("Test ") + LoaderType::getName()).c_str(), |
|
LoaderType::getName(), |
|
LoaderType::NORMALIZING != 0, |
|
std::numeric_limits<typename LoaderType::Type>::is_signed, |
|
dataType); |
|
retVal->m_loader = new LoaderType(); |
|
return retVal; |
|
} |
|
|
|
AttributeCase::~AttributeCase (void) |
|
{ |
|
deinit(); |
|
} |
|
|
|
void AttributeCase::init (void) |
|
{ |
|
if (m_context.getRenderTarget().getWidth() < RENDER_SIZE || m_context.getRenderTarget().getHeight() < RENDER_SIZE) |
|
throw tcu::NotSupportedError("Render target must be at least " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE)); |
|
|
|
// log test info |
|
|
|
{ |
|
const float maxRange = (m_normalizing) ? (1.0f) : (s_valueRange); |
|
const float minRange = (m_useNegativeValues) ? (-maxRange) : (0.0f); |
|
|
|
m_testCtx.getLog() |
|
<< tcu::TestLog::Message |
|
<< "Loading attribute values using " << m_funcName << "\n" |
|
<< "Attribute type: " << glu::getDataTypeName(m_dataType) << "\n" |
|
<< "Attribute value range: [" << minRange << ", " << maxRange << "]" |
|
<< tcu::TestLog::EndMessage; |
|
} |
|
|
|
// gen shader and base quad |
|
|
|
m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource()) << glu::FragmentSource(s_passThroughFragmentShaderSource)); |
|
m_testCtx.getLog() << *m_program; |
|
if (!m_program->isOk()) |
|
throw tcu::TestError("could not build program"); |
|
|
|
{ |
|
const tcu::Vec4 fullscreenQuad[] = |
|
{ |
|
tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), |
|
tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), |
|
tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), |
|
tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), |
|
}; |
|
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
|
|
|
gl.genBuffers(1, &m_bufID); |
|
gl.bindBuffer(GL_ARRAY_BUFFER, m_bufID); |
|
gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW); |
|
GLU_EXPECT_NO_ERROR(gl.getError(), "fill buffer"); |
|
} |
|
} |
|
|
|
void AttributeCase::deinit (void) |
|
{ |
|
delete m_loader; |
|
m_loader = DE_NULL; |
|
|
|
delete m_program; |
|
m_program = DE_NULL; |
|
|
|
if (m_bufID) |
|
{ |
|
m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_bufID); |
|
m_bufID = 0; |
|
} |
|
} |
|
|
|
AttributeCase::IterateResult AttributeCase::iterate (void) |
|
{ |
|
static const tcu::Vec4 testValues[] = |
|
{ |
|
tcu::Vec4(0.0f, 0.5f, 0.2f, 1.0f), |
|
tcu::Vec4(0.1f, 0.7f, 1.0f, 0.6f), |
|
tcu::Vec4(0.4f, 0.2f, 0.0f, 0.5f), |
|
tcu::Vec4(0.5f, 0.0f, 0.9f, 0.1f), |
|
tcu::Vec4(0.6f, 0.2f, 0.2f, 0.9f), |
|
tcu::Vec4(0.9f, 1.0f, 0.0f, 0.0f), |
|
tcu::Vec4(1.0f, 0.5f, 0.3f, 0.8f), |
|
}; |
|
|
|
const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", "Iteration " + de::toString(m_iteration+1) + "/" + de::toString(DE_LENGTH_OF_ARRAY(testValues))); |
|
|
|
// Test normalizing transfers with whole range, non-normalizing with up to s_valueRange |
|
const tcu::Vec4 testValue = ((m_useNegativeValues) ? (testValues[m_iteration] * 2.0f - tcu::Vec4(1.0f)) : (testValues[m_iteration])) * ((m_normalizing) ? (1.0f) : ((float)s_valueRange)); |
|
|
|
if (!renderWithValue(testValue)) |
|
m_allIterationsPassed = false; |
|
|
|
// continue |
|
|
|
if (++m_iteration < DE_LENGTH_OF_ARRAY(testValues)) |
|
return CONTINUE; |
|
|
|
if (m_allIterationsPassed) |
|
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
|
else |
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected values"); |
|
|
|
return STOP; |
|
} |
|
|
|
std::string AttributeCase::genVertexSource (void) const |
|
{ |
|
const int vectorSize = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeScalarSize(m_dataType)) : (-1); |
|
const char* const vectorType = glu::getDataTypeName((glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) : (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) : (glu::TYPE_FLOAT)); |
|
const int components = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType)); |
|
std::ostringstream buf; |
|
|
|
buf << "#version 300 es\n" |
|
"in highp vec4 a_position;\n" |
|
"in highp " << glu::getDataTypeName(m_dataType) << " a_value;\n" |
|
"out highp vec4 v_color;\n" |
|
"void main (void)\n" |
|
"{\n" |
|
" gl_Position = a_position;\n" |
|
"\n"; |
|
|
|
if (m_normalizing) |
|
buf << " highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ");\n"; |
|
else |
|
buf << " highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ") / float(" << s_valueRange << ");\n"; |
|
|
|
if (m_useNegativeValues) |
|
buf << " highp " << vectorType << " positiveNormalizedValue = (normalizedValue + " << vectorType << "(1.0)) / 2.0;\n"; |
|
else |
|
buf << " highp " << vectorType << " positiveNormalizedValue = normalizedValue;\n"; |
|
|
|
if (components == 1) |
|
buf << " v_color = vec4(positiveNormalizedValue, 0.0, 0.0, 1.0);\n"; |
|
else if (components == 2) |
|
buf << " v_color = vec4(positiveNormalizedValue.xy, 0.0, 1.0);\n"; |
|
else if (components == 3) |
|
buf << " v_color = vec4(positiveNormalizedValue.xyz, 1.0);\n"; |
|
else if (components == 4) |
|
buf << " v_color = vec4((positiveNormalizedValue.xy + positiveNormalizedValue.zz) / 2.0, positiveNormalizedValue.w, 1.0);\n"; |
|
else |
|
DE_ASSERT(DE_FALSE); |
|
|
|
buf << "}\n"; |
|
|
|
return buf.str(); |
|
} |
|
|
|
bool AttributeCase::renderWithValue (const tcu::Vec4& v) |
|
{ |
|
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); |
|
|
|
gl.enableLogging(true); |
|
|
|
const int positionIndex = gl.glGetAttribLocation(m_program->getProgram(), "a_position"); |
|
const int valueIndex = gl.glGetAttribLocation(m_program->getProgram(), "a_value"); |
|
tcu::Surface dest (RENDER_SIZE, RENDER_SIZE); |
|
tcu::Vec4 loadedValue; |
|
|
|
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
|
gl.glClear(GL_COLOR_BUFFER_BIT); |
|
gl.glViewport(0, 0, RENDER_SIZE, RENDER_SIZE); |
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup"); |
|
|
|
gl.glBindBuffer(GL_ARRAY_BUFFER, m_bufID); |
|
gl.glVertexAttribPointer(positionIndex, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); |
|
gl.glEnableVertexAttribArray(positionIndex); |
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "position va"); |
|
|
|
// transfer test value. Load to the second column in the matrix case |
|
loadedValue = m_loader->load(gl, (glu::isDataTypeMatrix(m_dataType)) ? (valueIndex + 1) : (valueIndex), v); |
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "default va"); |
|
|
|
gl.glUseProgram(m_program->getProgram()); |
|
gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
|
gl.glUseProgram(0); |
|
GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw"); |
|
|
|
glu::readPixels(m_context.getRenderContext(), 0, 0, dest.getAccess()); |
|
|
|
// check whole result is colored correctly |
|
return verifyUnicoloredBuffer(dest, computeColor(loadedValue)); |
|
} |
|
|
|
tcu::Vec4 AttributeCase::computeColor (const tcu::Vec4& value) |
|
{ |
|
const tcu::Vec4 normalizedValue = value / ((m_normalizing) ? (1.0f) : ((float)s_valueRange)); |
|
const tcu::Vec4 positiveNormalizedValue = ((m_useNegativeValues) ? ((normalizedValue + tcu::Vec4(1.0f)) / 2.0f) : (normalizedValue)); |
|
const int components = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType)); |
|
|
|
if (components == 1) |
|
return tcu::Vec4(positiveNormalizedValue.x(), 0.0f, 0.0f, 1.0f); |
|
else if (components == 2) |
|
return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), 0.0f, 1.0f); |
|
else if (components == 3) |
|
return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), positiveNormalizedValue.z(), 1.0f); |
|
else if (components == 4) |
|
return tcu::Vec4((positiveNormalizedValue.x() + positiveNormalizedValue.z()) / 2.0f, (positiveNormalizedValue.y() + positiveNormalizedValue.z()) / 2.0f, positiveNormalizedValue.w(), 1.0f); |
|
else |
|
DE_ASSERT(DE_FALSE); |
|
|
|
return tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); |
|
} |
|
|
|
bool AttributeCase::verifyUnicoloredBuffer (const tcu::Surface& scene, const tcu::Vec4& refValue) |
|
{ |
|
tcu::Surface errorMask (RENDER_SIZE, RENDER_SIZE); |
|
const tcu::RGBA refColor (refValue); |
|
const int resultThreshold = 2; |
|
const tcu::RGBA colorThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold() * resultThreshold; |
|
bool error = false; |
|
|
|
tcu::RGBA exampleColor; |
|
tcu::IVec2 examplePos; |
|
|
|
tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec()); |
|
|
|
m_testCtx.getLog() << tcu::TestLog::Message << "Verifying rendered image. Expecting color " << refColor << ", threshold " << colorThreshold << tcu::TestLog::EndMessage; |
|
|
|
for (int y = 0; y < RENDER_SIZE; ++y) |
|
for (int x = 0; x < RENDER_SIZE; ++x) |
|
{ |
|
const tcu::RGBA color = scene.getPixel(x, y); |
|
|
|
if (de::abs(color.getRed() - refColor.getRed()) > colorThreshold.getRed() || |
|
de::abs(color.getGreen() - refColor.getGreen()) > colorThreshold.getGreen() || |
|
de::abs(color.getBlue() - refColor.getBlue()) > colorThreshold.getBlue()) |
|
{ |
|
// first error |
|
if (!error) |
|
{ |
|
exampleColor = color; |
|
examplePos = tcu::IVec2(x, y); |
|
} |
|
|
|
error = true; |
|
errorMask.setPixel(x, y, tcu::RGBA::red()); |
|
} |
|
} |
|
|
|
if (!error) |
|
m_testCtx.getLog() << tcu::TestLog::Message << "Rendered image is valid." << tcu::TestLog::EndMessage; |
|
else |
|
{ |
|
m_testCtx.getLog() << tcu::TestLog::Message |
|
<< "Found invalid pixel(s).\n" |
|
<< "Pixel at (" << examplePos.x() << ", " << examplePos.y() << ") color: " << exampleColor |
|
<< tcu::TestLog::EndMessage |
|
<< tcu::TestLog::ImageSet("Result", "Render result") |
|
<< tcu::TestLog::Image("Result", "Result", scene) |
|
<< tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask) |
|
<< tcu::TestLog::EndImageSet; |
|
} |
|
|
|
return !error; |
|
} |
|
|
|
} // anonymous |
|
|
|
DefaultVertexAttributeTests::DefaultVertexAttributeTests (Context& context) |
|
: TestCaseGroup(context, "default_vertex_attrib", "Test default vertex attributes") |
|
{ |
|
} |
|
|
|
DefaultVertexAttributeTests::~DefaultVertexAttributeTests (void) |
|
{ |
|
} |
|
|
|
void DefaultVertexAttributeTests::init (void) |
|
{ |
|
struct Target |
|
{ |
|
const char* name; |
|
glu::DataType dataType; |
|
bool reducedTestSets; // !< use reduced coverage |
|
}; |
|
|
|
static const Target floatTargets[] = |
|
{ |
|
{ "float", glu::TYPE_FLOAT, false }, |
|
{ "vec2", glu::TYPE_FLOAT_VEC2, true }, |
|
{ "vec3", glu::TYPE_FLOAT_VEC3, true }, |
|
{ "vec4", glu::TYPE_FLOAT_VEC4, false }, |
|
{ "mat2", glu::TYPE_FLOAT_MAT2, true }, |
|
{ "mat2x3", glu::TYPE_FLOAT_MAT2X3, true }, |
|
{ "mat2x4", glu::TYPE_FLOAT_MAT2X4, true }, |
|
{ "mat3", glu::TYPE_FLOAT_MAT3, true }, |
|
{ "mat3x2", glu::TYPE_FLOAT_MAT3X2, true }, |
|
{ "mat3x4", glu::TYPE_FLOAT_MAT3X4, true }, |
|
{ "mat4", glu::TYPE_FLOAT_MAT4, false }, |
|
{ "mat4x2", glu::TYPE_FLOAT_MAT4X2, true }, |
|
{ "mat4x3", glu::TYPE_FLOAT_MAT4X3, true }, |
|
}; |
|
|
|
static const Target intTargets[] = |
|
{ |
|
{ "int", glu::TYPE_INT, false }, |
|
{ "ivec2", glu::TYPE_INT_VEC2, true }, |
|
{ "ivec3", glu::TYPE_INT_VEC3, true }, |
|
{ "ivec4", glu::TYPE_INT_VEC4, false }, |
|
}; |
|
|
|
static const Target uintTargets[] = |
|
{ |
|
{ "uint", glu::TYPE_UINT, false }, |
|
{ "uvec2", glu::TYPE_UINT_VEC2, true }, |
|
{ "uvec3", glu::TYPE_UINT_VEC3, true }, |
|
{ "uvec4", glu::TYPE_UINT_VEC4, false }, |
|
}; |
|
|
|
// float targets |
|
|
|
for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(floatTargets); ++targetNdx) |
|
{ |
|
tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, floatTargets[targetNdx].name, (std::string("test with ") + floatTargets[targetNdx].name).c_str()); |
|
const bool fullSet = !floatTargets[targetNdx].reducedTestSets; |
|
|
|
#define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, floatTargets[targetNdx].dataType)) |
|
#define ADD_REDUCED_CASE(X) if (fullSet) ADD_CASE(X) |
|
|
|
ADD_CASE (LoaderVertexAttrib1f); |
|
ADD_REDUCED_CASE(LoaderVertexAttrib2f); |
|
ADD_REDUCED_CASE(LoaderVertexAttrib3f); |
|
ADD_CASE (LoaderVertexAttrib4f); |
|
|
|
ADD_CASE (LoaderVertexAttrib1fv); |
|
ADD_REDUCED_CASE(LoaderVertexAttrib2fv); |
|
ADD_REDUCED_CASE(LoaderVertexAttrib3fv); |
|
ADD_CASE (LoaderVertexAttrib4fv); |
|
|
|
#undef ADD_CASE |
|
#undef ADD_REDUCED_CASE |
|
|
|
addChild(group); |
|
} |
|
|
|
// int targets |
|
|
|
for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(intTargets); ++targetNdx) |
|
{ |
|
tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, intTargets[targetNdx].name, (std::string("test with ") + intTargets[targetNdx].name).c_str()); |
|
|
|
#define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, intTargets[targetNdx].dataType)) |
|
|
|
ADD_CASE (LoaderVertexAttribI4i); |
|
ADD_CASE (LoaderVertexAttribI4iv); |
|
|
|
#undef ADD_CASE |
|
|
|
addChild(group); |
|
} |
|
|
|
// uint targets |
|
|
|
for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(uintTargets); ++targetNdx) |
|
{ |
|
tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, uintTargets[targetNdx].name, (std::string("test with ") + uintTargets[targetNdx].name).c_str()); |
|
|
|
#define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, uintTargets[targetNdx].dataType)) |
|
|
|
ADD_CASE (LoaderVertexAttribI4ui); |
|
ADD_CASE (LoaderVertexAttribI4uiv); |
|
|
|
#undef ADD_CASE |
|
|
|
addChild(group); |
|
} |
|
} |
|
|
|
} // Functional |
|
} // gles3 |
|
} // deqp
|
|
|