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.
3711 lines
121 KiB
3711 lines
121 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 Rbo state query tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es3fShaderStateQueryTests.hpp"
|
|
#include "glsStateQueryUtil.hpp"
|
|
#include "es3fApiCase.hpp"
|
|
#include "gluRenderContext.hpp"
|
|
#include "glwEnums.hpp"
|
|
#include "glwFunctions.hpp"
|
|
#include "deRandom.hpp"
|
|
#include "deMath.h"
|
|
#include "deString.h"
|
|
|
|
using namespace glw; // GLint and other GL types
|
|
using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles3
|
|
{
|
|
namespace Functional
|
|
{
|
|
namespace
|
|
{
|
|
|
|
static const char* commonTestVertSource = "#version 300 es\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(0.0);\n"
|
|
"}\n\0";
|
|
static const char* commonTestFragSource = "#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n\0";
|
|
|
|
static const char* brokenShader = "#version 300 es\n"
|
|
"broken, this should not compile!\n"
|
|
"\n\0";
|
|
|
|
// rounds x.1 to x+1
|
|
template <typename T>
|
|
T roundGLfloatToNearestIntegerUp (GLfloat val)
|
|
{
|
|
return (T)(ceil(val));
|
|
}
|
|
|
|
// rounds x.9 to x
|
|
template <typename T>
|
|
T roundGLfloatToNearestIntegerDown (GLfloat val)
|
|
{
|
|
return (T)(floor(val));
|
|
}
|
|
|
|
bool checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
if (got != expected)
|
|
{
|
|
testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void checkPointerEquals (tcu::TestContext& testCtx, const void* got, const void* expected)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
if (got != expected)
|
|
{
|
|
testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
|
|
}
|
|
}
|
|
|
|
void verifyShaderParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint shader, GLenum pname, GLenum reference)
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> state;
|
|
gl.glGetShaderiv(shader, pname, &state);
|
|
|
|
if (state.verifyValidity(testCtx))
|
|
checkIntEquals(testCtx, state, reference);
|
|
}
|
|
|
|
bool verifyProgramParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLenum pname, GLenum reference)
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> state;
|
|
gl.glGetProgramiv(program, pname, &state);
|
|
|
|
return state.verifyValidity(testCtx) && checkIntEquals(testCtx, state, reference);
|
|
}
|
|
|
|
void verifyActiveUniformParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLuint index, GLenum pname, GLenum reference)
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> state;
|
|
gl.glGetActiveUniformsiv(program, 1, &index, pname, &state);
|
|
|
|
if (state.verifyValidity(testCtx))
|
|
checkIntEquals(testCtx, state, reference);
|
|
}
|
|
|
|
void verifyActiveUniformBlockParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLuint blockIndex, GLenum pname, GLenum reference)
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> state;
|
|
gl.glGetActiveUniformBlockiv(program, blockIndex, pname, &state);
|
|
|
|
if (state.verifyValidity(testCtx))
|
|
checkIntEquals(testCtx, state, reference);
|
|
}
|
|
|
|
void verifyCurrentVertexAttribf (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
|
|
gl.glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
|
|
|
|
attribValue.verifyValidity(testCtx);
|
|
|
|
if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
|
|
<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
|
|
<< TestLog::EndMessage;
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
|
|
}
|
|
}
|
|
|
|
void verifyCurrentVertexAttribIi (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLint x, GLint y, GLint z, GLint w)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLint[4]> attribValue;
|
|
gl.glGetVertexAttribIiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
|
|
|
|
attribValue.verifyValidity(testCtx);
|
|
|
|
if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
|
|
<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
|
|
<< TestLog::EndMessage;
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
|
|
}
|
|
}
|
|
|
|
void verifyCurrentVertexAttribIui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLuint x, GLuint y, GLuint z, GLuint w)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLuint[4]> attribValue;
|
|
gl.glGetVertexAttribIuiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
|
|
|
|
attribValue.verifyValidity(testCtx);
|
|
|
|
if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
|
|
<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
|
|
<< TestLog::EndMessage;
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
|
|
}
|
|
}
|
|
|
|
void verifyCurrentVertexAttribConversion (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLint[4]> attribValue;
|
|
gl.glGetVertexAttribiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
|
|
|
|
attribValue.verifyValidity(testCtx);
|
|
|
|
const GLint referenceAsGLintMin[] =
|
|
{
|
|
roundGLfloatToNearestIntegerDown<GLint>(x),
|
|
roundGLfloatToNearestIntegerDown<GLint>(y),
|
|
roundGLfloatToNearestIntegerDown<GLint>(z),
|
|
roundGLfloatToNearestIntegerDown<GLint>(w)
|
|
};
|
|
const GLint referenceAsGLintMax[] =
|
|
{
|
|
roundGLfloatToNearestIntegerUp<GLint>(x),
|
|
roundGLfloatToNearestIntegerUp<GLint>(y),
|
|
roundGLfloatToNearestIntegerUp<GLint>(z),
|
|
roundGLfloatToNearestIntegerUp<GLint>(w)
|
|
};
|
|
|
|
if (attribValue[0] < referenceAsGLintMin[0] || attribValue[0] > referenceAsGLintMax[0] ||
|
|
attribValue[1] < referenceAsGLintMin[1] || attribValue[1] > referenceAsGLintMax[1] ||
|
|
attribValue[2] < referenceAsGLintMin[2] || attribValue[2] > referenceAsGLintMax[2] ||
|
|
attribValue[3] < referenceAsGLintMin[3] || attribValue[3] > referenceAsGLintMax[3])
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected in range "
|
|
<< "[" << referenceAsGLintMin[0] << " " << referenceAsGLintMax[0] << "], "
|
|
<< "[" << referenceAsGLintMin[1] << " " << referenceAsGLintMax[1] << "], "
|
|
<< "[" << referenceAsGLintMin[2] << " " << referenceAsGLintMax[2] << "], "
|
|
<< "[" << referenceAsGLintMin[3] << " " << referenceAsGLintMax[3] << "]"
|
|
<< "; got "
|
|
<< attribValue[0] << ", "
|
|
<< attribValue[1] << ", "
|
|
<< attribValue[2] << ", "
|
|
<< attribValue[3] << " "
|
|
<< "; Input="
|
|
<< x << "; "
|
|
<< y << "; "
|
|
<< z << "; "
|
|
<< w << " " << TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid attribute value");
|
|
}
|
|
}
|
|
|
|
void verifyVertexAttrib (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLenum pname, GLenum reference)
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> state;
|
|
gl.glGetVertexAttribIiv(index, pname, &state);
|
|
|
|
if (state.verifyValidity(testCtx))
|
|
checkIntEquals(testCtx, state, reference);
|
|
}
|
|
|
|
void verifyUniformValue1f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLfloat[1]> state;
|
|
gl.glGetUniformfv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x
|
|
<< "]; got ["
|
|
<< state[0]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue2f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLfloat[2]> state;
|
|
gl.glGetUniformfv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue3f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y, float z)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLfloat[3]> state;
|
|
gl.glGetUniformfv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y ||
|
|
state[2] != z)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y << ", "
|
|
<< z
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1] << ", "
|
|
<< state[2]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue4f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y, float z, float w)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLfloat[4]> state;
|
|
gl.glGetUniformfv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y ||
|
|
state[2] != z ||
|
|
state[3] != w)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y << ", "
|
|
<< z << ", "
|
|
<< w
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1] << ", "
|
|
<< state[2] << ", "
|
|
<< state[3]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue1i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLint[1]> state;
|
|
gl.glGetUniformiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x
|
|
<< "]; got ["
|
|
<< state[0]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue2i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLint[2]> state;
|
|
gl.glGetUniformiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue3i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y, GLint z)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLint[3]> state;
|
|
gl.glGetUniformiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y ||
|
|
state[2] != z)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y << ", "
|
|
<< z
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1] << ", "
|
|
<< state[2]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue4i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLint[4]> state;
|
|
gl.glGetUniformiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y ||
|
|
state[2] != z ||
|
|
state[3] != w)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y << ", "
|
|
<< z << ", "
|
|
<< w
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1] << ", "
|
|
<< state[2] << ", "
|
|
<< state[3]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue1ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLuint[1]> state;
|
|
gl.glGetUniformuiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x
|
|
<< "]; got ["
|
|
<< state[0]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue2ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x, GLuint y)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLuint[2]> state;
|
|
gl.glGetUniformuiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue3ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x, GLuint y, GLuint z)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLuint[3]> state;
|
|
gl.glGetUniformuiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y ||
|
|
state[2] != z)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y << ", "
|
|
<< z
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1] << ", "
|
|
<< state[2]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
void verifyUniformValue4ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLuint[4]> state;
|
|
gl.glGetUniformuiv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
if (state[0] != x ||
|
|
state[1] != y ||
|
|
state[2] != z ||
|
|
state[3] != w)
|
|
{
|
|
testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: expected ["
|
|
<< x << ", "
|
|
<< y << ", "
|
|
<< z << ", "
|
|
<< w
|
|
<< "]; got ["
|
|
<< state[0] << ", "
|
|
<< state[1] << ", "
|
|
<< state[2] << ", "
|
|
<< state[3]
|
|
<< "]"
|
|
<< TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
|
|
template <int Count>
|
|
void verifyUniformValues (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, const GLfloat* values)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLfloat[Count]> state;
|
|
gl.glGetUniformfv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
for (int ndx = 0; ndx < Count; ++ndx)
|
|
{
|
|
if (values[ndx] != state[ndx])
|
|
{
|
|
testCtx.getLog() << TestLog::Message << "// ERROR: at index " << ndx << " expected " << values[ndx] << "; got " << state[ndx] << TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
}
|
|
|
|
template <int N>
|
|
void verifyUniformMatrixValues (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, const GLfloat* values, bool transpose)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
StateQueryMemoryWriteGuard<GLfloat[N*N]> state;
|
|
gl.glGetUniformfv(program, location, state);
|
|
|
|
if (!state.verifyValidity(testCtx))
|
|
return;
|
|
|
|
for (int y = 0; y < N; ++y)
|
|
for (int x = 0; x < N; ++x)
|
|
{
|
|
const int refIndex = y*N + x;
|
|
const int stateIndex = transpose ? (x*N + y) : (y*N + x);
|
|
|
|
if (values[refIndex] != state[stateIndex])
|
|
{
|
|
testCtx.getLog() << TestLog::Message << "// ERROR: at index [" << y << "][" << x << "] expected " << values[refIndex] << "; got " << state[stateIndex] << TestLog::EndMessage;
|
|
|
|
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
|
|
}
|
|
}
|
|
}
|
|
|
|
class ShaderTypeCase : public ApiCase
|
|
{
|
|
public:
|
|
ShaderTypeCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
const GLenum shaderTypes[] = {GL_VERTEX_SHADER, GL_FRAGMENT_SHADER};
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
|
|
{
|
|
const GLuint shader = glCreateShader(shaderTypes[ndx]);
|
|
verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_TYPE, shaderTypes[ndx]);
|
|
glDeleteShader(shader);
|
|
}
|
|
}
|
|
};
|
|
|
|
class ShaderCompileStatusCase : public ApiCase
|
|
{
|
|
public:
|
|
ShaderCompileStatusCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_FALSE);
|
|
verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
|
|
|
|
glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class ShaderInfoLogCase : public ApiCase
|
|
{
|
|
public:
|
|
ShaderInfoLogCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
// INFO_LOG_LENGTH is 0 by default and it includes null-terminator
|
|
const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
|
|
verifyShaderParam(m_testCtx, *this, shader, GL_INFO_LOG_LENGTH, 0);
|
|
|
|
glShaderSource(shader, 1, &brokenShader, DE_NULL);
|
|
glCompileShader(shader);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// check the log length
|
|
StateQueryMemoryWriteGuard<GLint> logLength;
|
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
|
|
if (!logLength.verifyValidity(m_testCtx))
|
|
{
|
|
glDeleteShader(shader);
|
|
return;
|
|
}
|
|
if (logLength == 0)
|
|
{
|
|
glDeleteShader(shader);
|
|
return;
|
|
}
|
|
|
|
// check normal case
|
|
{
|
|
char buffer[2048] = {'x'}; // non-zero initialization
|
|
|
|
GLint written = 0; // written does not include null terminator
|
|
glGetShaderInfoLog(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
|
|
|
|
// check lengths are consistent
|
|
if (logLength <= DE_LENGTH_OF_ARRAY(buffer))
|
|
{
|
|
if (written != logLength-1)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << logLength-1 << "; got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
|
|
}
|
|
}
|
|
|
|
// check null-terminator, either at end of buffer or at buffer[written]
|
|
const char* terminator = &buffer[DE_LENGTH_OF_ARRAY(buffer) - 1];
|
|
if (logLength < DE_LENGTH_OF_ARRAY(buffer))
|
|
terminator = &buffer[written];
|
|
|
|
if (*terminator != '\0')
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)*terminator << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
|
|
}
|
|
}
|
|
|
|
// check with too small buffer
|
|
{
|
|
char buffer[2048] = {'x'}; // non-zero initialization
|
|
|
|
// check string always ends with \0, even with small buffers
|
|
GLint written = 0;
|
|
glGetShaderInfoLog(shader, 1, &written, buffer);
|
|
if (written != 0)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length 0; got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
|
|
}
|
|
if (buffer[0] != '\0')
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)buffer[0] << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
|
|
}
|
|
}
|
|
|
|
glDeleteShader(shader);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class ShaderSourceCase : public ApiCase
|
|
{
|
|
public:
|
|
ShaderSourceCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
// SHADER_SOURCE_LENGTH does include 0-terminator
|
|
const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
|
|
verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_SOURCE_LENGTH, 0);
|
|
|
|
// check the SHADER_SOURCE_LENGTH
|
|
{
|
|
glShaderSource(shader, 1, &brokenShader, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
StateQueryMemoryWriteGuard<GLint> sourceLength;
|
|
glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
|
|
|
|
sourceLength.verifyValidity(m_testCtx);
|
|
|
|
const GLint referenceLength = (GLint)std::string(brokenShader).length() + 1; // including the null terminator
|
|
if (sourceLength != referenceLength)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got " << sourceLength << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
|
|
}
|
|
}
|
|
|
|
// check the concat source SHADER_SOURCE_LENGTH
|
|
{
|
|
const char* shaders[] = {brokenShader, brokenShader};
|
|
glShaderSource(shader, 2, shaders, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
StateQueryMemoryWriteGuard<GLint> sourceLength;
|
|
glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
|
|
|
|
sourceLength.verifyValidity(m_testCtx);
|
|
|
|
const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length() + 1; // including the null terminator
|
|
if (sourceLength != referenceLength)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got " << sourceLength << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
|
|
}
|
|
}
|
|
|
|
// check the string length
|
|
{
|
|
char buffer[2048] = {'x'};
|
|
DE_ASSERT(DE_LENGTH_OF_ARRAY(buffer) > 2 * (int)std::string(brokenShader).length());
|
|
|
|
GLint written = 0; // not inluding null-terminator
|
|
glGetShaderSource(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
|
|
|
|
const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length();
|
|
if (written != referenceLength)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length " << referenceLength << "; got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
|
|
}
|
|
// check null pointer at
|
|
else
|
|
{
|
|
if (buffer[referenceLength] != '\0')
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at " << referenceLength << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "did not get a null terminator");
|
|
}
|
|
}
|
|
}
|
|
|
|
// check with small buffer
|
|
{
|
|
char buffer[2048] = {'x'};
|
|
|
|
GLint written = 0;
|
|
glGetShaderSource(shader, 1, &written, buffer);
|
|
|
|
if (written != 0)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
|
|
}
|
|
if (buffer[0] != '\0')
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator; got=" << int(buffer[0]) << ", char=" << buffer[0] << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid terminator");
|
|
}
|
|
}
|
|
|
|
glDeleteShader(shader);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class DeleteStatusCase : public ApiCase
|
|
{
|
|
public:
|
|
DeleteStatusCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
|
|
|
|
GLuint shaderProg = glCreateProgram();
|
|
glAttachShader(shaderProg, shaderVert);
|
|
glAttachShader(shaderProg, shaderFrag);
|
|
glLinkProgram(shaderProg);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyProgramParam (m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
|
|
|
|
verifyShaderParam (m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_FALSE);
|
|
verifyShaderParam (m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_FALSE);
|
|
verifyProgramParam (m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_FALSE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glUseProgram(shaderProg);
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(shaderProg);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyShaderParam (m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_TRUE);
|
|
verifyShaderParam (m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_TRUE);
|
|
verifyProgramParam (m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_TRUE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glUseProgram(0);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class CurrentVertexAttribInitialCase : public ApiCase
|
|
{
|
|
public:
|
|
CurrentVertexAttribInitialCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
int attribute_count = 16;
|
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
|
|
|
|
// initial
|
|
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
|
|
glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
|
|
attribValue.verifyValidity(m_testCtx);
|
|
|
|
if (attribValue[0] != 0.0f || attribValue[1] != 0.0f || attribValue[2] != 0.0f || attribValue[3] != 1.0f)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: Expected [0, 0, 0, 1];"
|
|
<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
|
|
<< TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
class CurrentVertexAttribFloatCase : public ApiCase
|
|
{
|
|
public:
|
|
CurrentVertexAttribFloatCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
de::Random rnd(0xabcdef);
|
|
|
|
int attribute_count = 16;
|
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
|
|
|
|
// test write float/read float
|
|
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = rnd.getFloat(-64000, 64000);
|
|
const GLfloat z = rnd.getFloat(-64000, 64000);
|
|
const GLfloat w = rnd.getFloat(-64000, 64000);
|
|
|
|
glVertexAttrib4f(index, x, y, z, w);
|
|
verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = rnd.getFloat(-64000, 64000);
|
|
const GLfloat z = rnd.getFloat(-64000, 64000);
|
|
const GLfloat w = 1.0f;
|
|
|
|
glVertexAttrib3f(index, x, y, z);
|
|
verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = rnd.getFloat(-64000, 64000);
|
|
const GLfloat z = 0.0f;
|
|
const GLfloat w = 1.0f;
|
|
|
|
glVertexAttrib2f(index, x, y);
|
|
verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = 0.0f;
|
|
const GLfloat z = 0.0f;
|
|
const GLfloat w = 1.0f;
|
|
|
|
glVertexAttrib1f(index, x);
|
|
verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
}
|
|
};
|
|
|
|
class CurrentVertexAttribIntCase : public ApiCase
|
|
{
|
|
public:
|
|
CurrentVertexAttribIntCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
de::Random rnd(0xabcdef);
|
|
|
|
int attribute_count = 16;
|
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
|
|
|
|
// test write float/read float
|
|
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLint x = rnd.getInt(-64000, 64000);
|
|
const GLint y = rnd.getInt(-64000, 64000);
|
|
const GLint z = rnd.getInt(-64000, 64000);
|
|
const GLint w = rnd.getInt(-64000, 64000);
|
|
|
|
glVertexAttribI4i(index, x, y, z, w);
|
|
verifyCurrentVertexAttribIi(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
}
|
|
};
|
|
|
|
class CurrentVertexAttribUintCase : public ApiCase
|
|
{
|
|
public:
|
|
CurrentVertexAttribUintCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
de::Random rnd(0xabcdef);
|
|
|
|
int attribute_count = 16;
|
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
|
|
|
|
// test write float/read float
|
|
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLuint x = rnd.getInt(0, 64000);
|
|
const GLuint y = rnd.getInt(0, 64000);
|
|
const GLuint z = rnd.getInt(0, 64000);
|
|
const GLuint w = rnd.getInt(0, 64000);
|
|
|
|
glVertexAttribI4ui(index, x, y, z, w);
|
|
verifyCurrentVertexAttribIui(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
}
|
|
};
|
|
|
|
class CurrentVertexAttribConversionCase : public ApiCase
|
|
{
|
|
public:
|
|
CurrentVertexAttribConversionCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
de::Random rnd(0xabcdef);
|
|
|
|
int attribute_count = 16;
|
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
|
|
|
|
// test write float/read float
|
|
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = rnd.getFloat(-64000, 64000);
|
|
const GLfloat z = rnd.getFloat(-64000, 64000);
|
|
const GLfloat w = rnd.getFloat(-64000, 64000);
|
|
|
|
glVertexAttrib4f(index, x, y, z, w);
|
|
verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = rnd.getFloat(-64000, 64000);
|
|
const GLfloat z = rnd.getFloat(-64000, 64000);
|
|
const GLfloat w = 1.0f;
|
|
|
|
glVertexAttrib3f(index, x, y, z);
|
|
verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = rnd.getFloat(-64000, 64000);
|
|
const GLfloat z = 0.0f;
|
|
const GLfloat w = 1.0f;
|
|
|
|
glVertexAttrib2f(index, x, y);
|
|
verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
for (int index = 0; index < attribute_count; ++index)
|
|
{
|
|
const GLfloat x = rnd.getFloat(-64000, 64000);
|
|
const GLfloat y = 0.0f;
|
|
const GLfloat z = 0.0f;
|
|
const GLfloat w = 1.0f;
|
|
|
|
glVertexAttrib1f(index, x);
|
|
verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
|
|
}
|
|
}
|
|
};
|
|
|
|
class ProgramInfoLogCase : public ApiCase
|
|
{
|
|
public:
|
|
enum BuildErrorType
|
|
{
|
|
BUILDERROR_COMPILE = 0,
|
|
BUILDERROR_LINK
|
|
};
|
|
|
|
ProgramInfoLogCase (Context& context, const char* name, const char* description, BuildErrorType buildErrorType)
|
|
: ApiCase (context, name, description)
|
|
, m_buildErrorType (buildErrorType)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
enum
|
|
{
|
|
BUF_SIZE = 2048
|
|
};
|
|
|
|
static const char* const linkErrorVtxSource = "#version 300 es\n"
|
|
"in highp vec4 a_pos;\n"
|
|
"uniform highp vec4 u_uniform;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
" gl_Position = a_pos + u_uniform;\n"
|
|
"}\n";
|
|
static const char* const linkErrorFrgSource = "#version 300 es\n"
|
|
"in highp vec4 v_missingVar;\n"
|
|
"uniform highp int u_uniform;\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
" fragColor = v_missingVar + vec4(float(u_uniform));\n"
|
|
"}\n";
|
|
|
|
const char* vtxSource = (m_buildErrorType == BUILDERROR_COMPILE) ? (brokenShader) : (linkErrorVtxSource);
|
|
const char* frgSource = (m_buildErrorType == BUILDERROR_COMPILE) ? (brokenShader) : (linkErrorFrgSource);
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &vtxSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &frgSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
|
|
StateQueryMemoryWriteGuard<GLint> logLength;
|
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
|
logLength.verifyValidity(m_testCtx);
|
|
|
|
// check INFO_LOG_LENGTH == GetProgramInfoLog len
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "QueryLarge", "Query to large buffer");
|
|
char buffer[BUF_SIZE] = {'x'};
|
|
GLint written = 0;
|
|
|
|
glGetProgramInfoLog(program, BUF_SIZE, &written, buffer);
|
|
|
|
if (logLength != 0 && written+1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written+1 << "; got " << logLength << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
|
|
}
|
|
else if (logLength != 0 && buffer[written] != '\0')
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at index " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing null terminator");
|
|
}
|
|
}
|
|
|
|
// check query to just correct sized buffer
|
|
if (BUF_SIZE > logLength)
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "QueryAll", "Query all to exactly right sized buffer");
|
|
char buffer[BUF_SIZE] = {'x'};
|
|
GLint written = 0;
|
|
|
|
glGetProgramInfoLog(program, logLength, &written, buffer);
|
|
|
|
if (logLength != 0 && written+1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written+1 << "; got " << logLength << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
|
|
}
|
|
else if (logLength != 0 && buffer[written] != '\0')
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at index " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing null terminator");
|
|
}
|
|
}
|
|
|
|
// check GetProgramInfoLog works with too small buffer
|
|
{
|
|
const tcu::ScopedLogSection section (m_testCtx.getLog(), "QueryNone", "Query none");
|
|
char buffer[BUF_SIZE] = {'x'};
|
|
GLint written = 0;
|
|
|
|
glGetProgramInfoLog(program, 1, &written, buffer);
|
|
|
|
if (written != 0)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
|
|
}
|
|
}
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
|
|
const BuildErrorType m_buildErrorType;
|
|
};
|
|
|
|
class ProgramValidateStatusCase : public ApiCase
|
|
{
|
|
public:
|
|
ProgramValidateStatusCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// test validate ok
|
|
{
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyShaderParam (m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyShaderParam (m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyProgramParam (m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE);
|
|
|
|
glValidateProgram(program);
|
|
verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_TRUE);
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
|
|
// test with broken shader
|
|
{
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &brokenShader, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyShaderParam (m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyShaderParam (m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
|
|
verifyProgramParam (m_testCtx, *this, program, GL_LINK_STATUS, GL_FALSE);
|
|
|
|
glValidateProgram(program);
|
|
verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_FALSE);
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class ProgramAttachedShadersCase : public ApiCase
|
|
{
|
|
public:
|
|
ProgramAttachedShadersCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// check ATTACHED_SHADERS
|
|
|
|
GLuint program = glCreateProgram();
|
|
verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 0);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glAttachShader(program, shaderVert);
|
|
verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 1);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glAttachShader(program, shaderFrag);
|
|
verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 2);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// check GetAttachedShaders
|
|
{
|
|
GLuint shaders[2] = {0, 0};
|
|
GLint count = 0;
|
|
glGetAttachedShaders(program, DE_LENGTH_OF_ARRAY(shaders), &count, shaders);
|
|
|
|
if (count != 2)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 2; got " << count << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
|
|
}
|
|
// shaders are the attached shaders?
|
|
if (!((shaders[0] == shaderVert && shaders[1] == shaderFrag) ||
|
|
(shaders[0] == shaderFrag && shaders[1] == shaderVert)))
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected {" << shaderVert << ", " << shaderFrag << "}; got {" << shaders[0] << ", " << shaders[1] << "}" << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
|
|
}
|
|
}
|
|
|
|
// check GetAttachedShaders with too small buffer
|
|
{
|
|
GLuint shaders[2] = {0, 0};
|
|
GLint count = 0;
|
|
|
|
glGetAttachedShaders(program, 0, &count, shaders);
|
|
if (count != 0)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << count << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
|
|
}
|
|
|
|
count = 0;
|
|
glGetAttachedShaders(program, 1, &count, shaders);
|
|
if (count != 1)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 1; got " << count << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
|
|
}
|
|
}
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class ProgramActiveUniformNameCase : public ApiCase
|
|
{
|
|
public:
|
|
ProgramActiveUniformNameCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform highp float uniformNameWithLength23;\n"
|
|
"uniform highp vec2 uniformVec2;\n"
|
|
"uniform highp mat4 uniformMat4;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(0.0) + vec4(uniformNameWithLength23) + vec4(uniformVec2.x) + vec4(uniformMat4[2][3]);\n"
|
|
"}\n\0";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n\0";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORMS, 3);
|
|
verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, (GLint)std::string("uniformNameWithLength23").length() + 1); // including a null terminator
|
|
expectError(GL_NO_ERROR);
|
|
|
|
const char* uniformNames[] =
|
|
{
|
|
"uniformNameWithLength23",
|
|
"uniformVec2",
|
|
"uniformMat4"
|
|
};
|
|
StateQueryMemoryWriteGuard<GLuint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformIndices;
|
|
glGetUniformIndices(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformNames, uniformIndices);
|
|
uniformIndices.verifyValidity(m_testCtx);
|
|
|
|
// check name lengths
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
|
|
{
|
|
const GLuint uniformIndex = uniformIndices[ndx];
|
|
|
|
StateQueryMemoryWriteGuard<GLint> uniformNameLen;
|
|
glGetActiveUniformsiv(program, 1, &uniformIndex, GL_UNIFORM_NAME_LENGTH, &uniformNameLen);
|
|
|
|
uniformNameLen.verifyValidity(m_testCtx);
|
|
|
|
const GLint referenceLength = (GLint)std::string(uniformNames[ndx]).length() + 1;
|
|
if (referenceLength != uniformNameLen) // uniformNameLen is with null terminator
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceLength << "got " << uniformNameLen << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
|
|
}
|
|
}
|
|
|
|
// check names
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
|
|
{
|
|
char buffer[2048] = {'x'};
|
|
|
|
const GLuint uniformIndex = uniformIndices[ndx];
|
|
|
|
GLint written = 0; // null terminator not included
|
|
GLint size = 0;
|
|
GLenum type = 0;
|
|
glGetActiveUniform(program, uniformIndex, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
|
|
|
|
const GLint referenceLength = (GLint)std::string(uniformNames[ndx]).length();
|
|
if (referenceLength != written)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceLength << "got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
|
|
}
|
|
|
|
// and with too small buffer
|
|
written = 0;
|
|
glGetActiveUniform(program, uniformIndex, 1, &written, &size, &type, buffer);
|
|
|
|
if (written != 0)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0 got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
|
|
}
|
|
}
|
|
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class ProgramUniformCase : public ApiCase
|
|
{
|
|
public:
|
|
ProgramUniformCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
const struct UniformType
|
|
{
|
|
const char* declaration;
|
|
const char* postDeclaration;
|
|
const char* precision;
|
|
const char* layout;
|
|
const char* getter;
|
|
GLenum type;
|
|
GLint size;
|
|
GLint isRowMajor;
|
|
} uniformTypes[] =
|
|
{
|
|
{ "float", "", "highp", "", "uniformValue", GL_FLOAT, 1, GL_FALSE },
|
|
{ "float[2]", "", "highp", "", "uniformValue[1]", GL_FLOAT, 2, GL_FALSE },
|
|
{ "vec2", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC2, 1, GL_FALSE },
|
|
{ "vec3", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC3, 1, GL_FALSE },
|
|
{ "vec4", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC4, 1, GL_FALSE },
|
|
{ "int", "", "highp", "", "float(uniformValue)", GL_INT, 1, GL_FALSE },
|
|
{ "ivec2", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC2, 1, GL_FALSE },
|
|
{ "ivec3", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC3, 1, GL_FALSE },
|
|
{ "ivec4", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC4, 1, GL_FALSE },
|
|
{ "uint", "", "highp", "", "float(uniformValue)", GL_UNSIGNED_INT, 1, GL_FALSE },
|
|
{ "uvec2", "", "highp", "", "float(uniformValue.x)", GL_UNSIGNED_INT_VEC2, 1, GL_FALSE },
|
|
{ "uvec3", "", "highp", "", "float(uniformValue.x)", GL_UNSIGNED_INT_VEC3, 1, GL_FALSE },
|
|
{ "uvec4", "", "highp", "", "float(uniformValue.x)", GL_UNSIGNED_INT_VEC4, 1, GL_FALSE },
|
|
{ "bool", "", "", "", "float(uniformValue)", GL_BOOL, 1, GL_FALSE },
|
|
{ "bvec2", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC2, 1, GL_FALSE },
|
|
{ "bvec3", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC3, 1, GL_FALSE },
|
|
{ "bvec4", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC4, 1, GL_FALSE },
|
|
{ "mat2", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT2, 1, GL_FALSE },
|
|
{ "mat3", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT3, 1, GL_FALSE },
|
|
{ "mat4", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT4, 1, GL_FALSE },
|
|
{ "mat2x3", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT2x3, 1, GL_FALSE },
|
|
{ "mat2x4", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT2x4, 1, GL_FALSE },
|
|
{ "mat3x2", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT3x2, 1, GL_FALSE },
|
|
{ "mat3x4", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT3x4, 1, GL_FALSE },
|
|
{ "mat4x2", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT4x2, 1, GL_FALSE },
|
|
{ "mat4x3", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT4x3, 1, GL_FALSE },
|
|
{ "sampler2D", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_SAMPLER_2D, 1, GL_FALSE },
|
|
{ "sampler3D", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_SAMPLER_3D, 1, GL_FALSE },
|
|
{ "samplerCube", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_SAMPLER_CUBE, 1, GL_FALSE },
|
|
{ "sampler2DShadow", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_SAMPLER_2D_SHADOW, 1, GL_FALSE },
|
|
{ "sampler2DArray", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_SAMPLER_2D_ARRAY, 1, GL_FALSE },
|
|
{ "sampler2DArrayShadow", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_SAMPLER_2D_ARRAY_SHADOW, 1, GL_FALSE },
|
|
{ "samplerCubeShadow", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_SAMPLER_CUBE_SHADOW, 1, GL_FALSE },
|
|
{ "isampler2D", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_INT_SAMPLER_2D, 1, GL_FALSE },
|
|
{ "isampler3D", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_INT_SAMPLER_3D, 1, GL_FALSE },
|
|
{ "isamplerCube", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_INT_SAMPLER_CUBE, 1, GL_FALSE },
|
|
{ "isampler2DArray", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_INT_SAMPLER_2D_ARRAY, 1, GL_FALSE },
|
|
{ "usampler2D", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_UNSIGNED_INT_SAMPLER_2D, 1, GL_FALSE },
|
|
{ "usampler3D", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_UNSIGNED_INT_SAMPLER_3D, 1, GL_FALSE },
|
|
{ "usamplerCube", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_UNSIGNED_INT_SAMPLER_CUBE, 1, GL_FALSE },
|
|
{ "usampler2DArray", "", "highp", "", "float(textureSize(uniformValue,0).r)", GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, 1, GL_FALSE },
|
|
};
|
|
|
|
static const char* vertSource =
|
|
"#version 300 es\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(0.0);\n"
|
|
"}\n\0";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
GLuint program = glCreateProgram();
|
|
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
|
|
glShaderSource(shaderVert, 1, &vertSource, DE_NULL);
|
|
glCompileShader(shaderVert);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformTypes); ++ndx)
|
|
{
|
|
tcu::ScopedLogSection(m_log, uniformTypes[ndx].declaration, std::string("Verify type of ") + uniformTypes[ndx].declaration + " variable" + uniformTypes[ndx].postDeclaration );
|
|
|
|
// gen fragment shader
|
|
|
|
std::ostringstream frag;
|
|
frag << "#version 300 es\n";
|
|
frag << uniformTypes[ndx].layout << "uniform " << uniformTypes[ndx].precision << " " << uniformTypes[ndx].declaration << " uniformValue" << uniformTypes[ndx].postDeclaration << ";\n";
|
|
frag << "layout(location = 0) out mediump vec4 fragColor;\n";
|
|
frag << "void main (void)\n";
|
|
frag << "{\n";
|
|
frag << " fragColor = vec4(" << uniformTypes[ndx].getter << ");\n";
|
|
frag << "}\n";
|
|
|
|
{
|
|
std::string fragmentSource = frag.str();
|
|
const char* fragmentSourceCStr = fragmentSource.c_str();
|
|
glShaderSource(shaderFrag, 1, &fragmentSourceCStr, DE_NULL);
|
|
}
|
|
|
|
// compile & link
|
|
|
|
glCompileShader(shaderFrag);
|
|
glLinkProgram(program);
|
|
|
|
// test
|
|
if (verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE))
|
|
{
|
|
const char* uniformNames[] = {"uniformValue"};
|
|
StateQueryMemoryWriteGuard<GLuint> uniformIndex;
|
|
glGetUniformIndices(program, 1, uniformNames, &uniformIndex);
|
|
uniformIndex.verifyValidity(m_testCtx);
|
|
|
|
verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_TYPE, uniformTypes[ndx].type);
|
|
verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_SIZE, uniformTypes[ndx].size);
|
|
verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_IS_ROW_MAJOR, uniformTypes[ndx].isRowMajor);
|
|
}
|
|
}
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class ProgramActiveUniformBlocksCase : public ApiCase
|
|
{
|
|
public:
|
|
ProgramActiveUniformBlocksCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n"
|
|
"uniform shortUniformBlockName {highp vec2 vector2;highp vec4 vector4;} shortUniformInstanceName;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = shortUniformInstanceName.vector4 + vec4(longlongUniformInstanceName.vector2.x) + vec4(shortUniformInstanceName.vector2.x);\n"
|
|
"}\n\0";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(longlongUniformInstanceName.vector2.y);\n"
|
|
"}\n\0";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyShaderParam (m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyShaderParam (m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyProgramParam (m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE);
|
|
|
|
verifyProgramParam (m_testCtx, *this, program, GL_ACTIVE_UNIFORM_BLOCKS, 2);
|
|
verifyProgramParam (m_testCtx, *this, program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, (GLint)std::string("longlongUniformBlockName").length() + 1); // including a null terminator
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint longlongUniformBlockIndex = glGetUniformBlockIndex(program, "longlongUniformBlockName");
|
|
GLint shortUniformBlockIndex = glGetUniformBlockIndex(program, "shortUniformBlockName");
|
|
|
|
const char* uniformNames[] =
|
|
{
|
|
"longlongUniformBlockName.vector2",
|
|
"shortUniformBlockName.vector2",
|
|
"shortUniformBlockName.vector4"
|
|
};
|
|
|
|
// test UNIFORM_BLOCK_INDEX
|
|
|
|
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(uniformNames) == 3);
|
|
|
|
StateQueryMemoryWriteGuard<GLuint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformIndices;
|
|
StateQueryMemoryWriteGuard<GLint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformsBlockIndices;
|
|
|
|
glGetUniformIndices(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformNames, uniformIndices);
|
|
uniformIndices.verifyValidity(m_testCtx);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glGetActiveUniformsiv(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformIndices, GL_UNIFORM_BLOCK_INDEX, uniformsBlockIndices);
|
|
uniformsBlockIndices.verifyValidity(m_testCtx);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
if (uniformsBlockIndices[0] != longlongUniformBlockIndex ||
|
|
uniformsBlockIndices[1] != shortUniformBlockIndex ||
|
|
uniformsBlockIndices[2] != shortUniformBlockIndex)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: Expected [" << longlongUniformBlockIndex << ", " << shortUniformBlockIndex << ", " << shortUniformBlockIndex << "];"
|
|
<< "got [" << uniformsBlockIndices[0] << ", " << uniformsBlockIndices[1] << ", " << uniformsBlockIndices[2] << "]" << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform block index");
|
|
}
|
|
|
|
// test UNIFORM_BLOCK_NAME_LENGTH
|
|
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_NAME_LENGTH, (GLint)std::string("longlongUniformBlockName").length() + 1); // including null-terminator
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex, GL_UNIFORM_BLOCK_NAME_LENGTH, (GLint)std::string("shortUniformBlockName").length() + 1); // including null-terminator
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// test UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER & UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
|
|
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, GL_TRUE);
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, GL_TRUE);
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, GL_TRUE);
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, GL_FALSE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// test UNIFORM_BLOCK_ACTIVE_UNIFORMS
|
|
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, 1);
|
|
verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, 2);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// test UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
|
|
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> longlongUniformBlockUniforms;
|
|
glGetActiveUniformBlockiv(program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &longlongUniformBlockUniforms);
|
|
longlongUniformBlockUniforms.verifyValidity(m_testCtx);
|
|
|
|
if (longlongUniformBlockUniforms == 2)
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint[2]> longlongUniformBlockUniformIndices;
|
|
glGetActiveUniformBlockiv(program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, longlongUniformBlockUniformIndices);
|
|
longlongUniformBlockUniformIndices.verifyValidity(m_testCtx);
|
|
|
|
if ((GLuint(longlongUniformBlockUniformIndices[0]) != uniformIndices[0] || GLuint(longlongUniformBlockUniformIndices[1]) != uniformIndices[1]) &&
|
|
(GLuint(longlongUniformBlockUniformIndices[1]) != uniformIndices[0] || GLuint(longlongUniformBlockUniformIndices[0]) != uniformIndices[1]))
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message
|
|
<< "// ERROR: Expected {" << uniformIndices[0] << ", " << uniformIndices[1] << "};"
|
|
<< "got {" << longlongUniformBlockUniformIndices[0] << ", " << longlongUniformBlockUniformIndices[1] << "}" << TestLog::EndMessage;
|
|
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform indices");
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// check block names
|
|
|
|
{
|
|
char buffer[2048] = {'x'};
|
|
GLint written = 0;
|
|
glGetActiveUniformBlockName(program, longlongUniformBlockIndex, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
|
|
checkIntEquals(m_testCtx, written, (GLint)std::string("longlongUniformBlockName").length());
|
|
|
|
written = 0;
|
|
glGetActiveUniformBlockName(program, shortUniformBlockIndex, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
|
|
checkIntEquals(m_testCtx, written, (GLint)std::string("shortUniformBlockName").length());
|
|
|
|
// and one with too small buffer
|
|
written = 0;
|
|
glGetActiveUniformBlockName(program, longlongUniformBlockIndex, 1, &written, buffer);
|
|
checkIntEquals(m_testCtx, written, 0);
|
|
}
|
|
|
|
expectError(GL_NO_ERROR);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class ProgramBinaryCase : public ApiCase
|
|
{
|
|
public:
|
|
ProgramBinaryCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// test PROGRAM_BINARY_RETRIEVABLE_HINT
|
|
verifyProgramParam(m_testCtx, *this, program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_FALSE);
|
|
|
|
glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glLinkProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyProgramParam(m_testCtx, *this, program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
|
|
|
// test PROGRAM_BINARY_LENGTH does something
|
|
|
|
StateQueryMemoryWriteGuard<GLint> programLength;
|
|
glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &programLength);
|
|
expectError(GL_NO_ERROR);
|
|
programLength.verifyValidity(m_testCtx);
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class TransformFeedbackCase : public ApiCase
|
|
{
|
|
public:
|
|
TransformFeedbackCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
static const char* transformFeedbackTestVertSource =
|
|
"#version 300 es\n"
|
|
"out highp vec4 tfOutput2withLongName;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(0.0);\n"
|
|
" tfOutput2withLongName = vec4(0.0);\n"
|
|
"}\n";
|
|
static const char* transformFeedbackTestFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out highp vec4 fragColor;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
GLuint shaderProg = glCreateProgram();
|
|
|
|
verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, GL_INTERLEAVED_ATTRIBS);
|
|
|
|
glShaderSource(shaderVert, 1, &transformFeedbackTestVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &transformFeedbackTestFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
|
|
verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
|
|
verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
|
|
|
|
glAttachShader(shaderProg, shaderVert);
|
|
glAttachShader(shaderProg, shaderFrag);
|
|
|
|
// check TRANSFORM_FEEDBACK_BUFFER_MODE
|
|
|
|
const char* transform_feedback_outputs[] = {"gl_Position", "tfOutput2withLongName"};
|
|
const char* longest_output = transform_feedback_outputs[1];
|
|
const GLenum bufferModes[] = {GL_SEPARATE_ATTRIBS, GL_INTERLEAVED_ATTRIBS};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bufferModes); ++ndx)
|
|
{
|
|
glTransformFeedbackVaryings(shaderProg, DE_LENGTH_OF_ARRAY(transform_feedback_outputs), transform_feedback_outputs, bufferModes[ndx]);
|
|
glLinkProgram(shaderProg);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyProgramParam(m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
|
|
verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, bufferModes[ndx]);
|
|
}
|
|
|
|
// TRANSFORM_FEEDBACK_VARYINGS
|
|
verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_VARYINGS, 2);
|
|
|
|
// TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> maxOutputLen;
|
|
glGetProgramiv(shaderProg, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxOutputLen);
|
|
|
|
maxOutputLen.verifyValidity(m_testCtx);
|
|
|
|
const GLint referenceLength = (GLint)std::string(longest_output).length() + 1;
|
|
checkIntEquals(m_testCtx, maxOutputLen, referenceLength);
|
|
}
|
|
|
|
// check varyings
|
|
{
|
|
StateQueryMemoryWriteGuard<GLint> varyings;
|
|
glGetProgramiv(shaderProg, GL_TRANSFORM_FEEDBACK_VARYINGS, &varyings);
|
|
|
|
if (!varyings.isUndefined())
|
|
for (int index = 0; index < varyings; ++index)
|
|
{
|
|
char buffer[2048] = {'x'};
|
|
|
|
GLint written = 0;
|
|
GLint size = 0;
|
|
GLenum type = 0;
|
|
glGetTransformFeedbackVarying(shaderProg, index, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
|
|
|
|
if (written < DE_LENGTH_OF_ARRAY(buffer) && buffer[written] != '\0')
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator" << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid string terminator");
|
|
}
|
|
|
|
// check with too small buffer
|
|
written = 0;
|
|
glGetTransformFeedbackVarying(shaderProg, index, 1, &written, &size, &type, buffer);
|
|
if (written != 0)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << written << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid write length");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(shaderProg);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class ActiveAttributesCase : public ApiCase
|
|
{
|
|
public:
|
|
ActiveAttributesCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
using tcu::TestLog;
|
|
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"in highp vec2 longInputAttributeName;\n"
|
|
"in highp vec2 shortName;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = longInputAttributeName.yxxy + shortName.xyxy;\n"
|
|
"}\n\0";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n\0";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTES, 2);
|
|
verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, (GLint)std::string("longInputAttributeName").length() + 1); // does include null-terminator
|
|
|
|
// check names
|
|
for (int attributeNdx = 0; attributeNdx < 2; ++attributeNdx)
|
|
{
|
|
char buffer[2048] = {'x'};
|
|
|
|
GLint written = 0;
|
|
GLint size = 0;
|
|
GLenum type = 0;
|
|
glGetActiveAttrib(program, attributeNdx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
if (deStringBeginsWith(buffer, "longInputAttributeName"))
|
|
{
|
|
checkIntEquals(m_testCtx, written, (GLint)std::string("longInputAttributeName").length()); // does NOT include null-terminator
|
|
}
|
|
else if (deStringBeginsWith(buffer, "shortName"))
|
|
{
|
|
checkIntEquals(m_testCtx, written, (GLint)std::string("shortName").length()); // does NOT include null-terminator
|
|
}
|
|
else
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unexpected attribute name." << TestLog::EndMessage;
|
|
if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected name");
|
|
}
|
|
}
|
|
|
|
// and with too short buffer
|
|
{
|
|
char buffer[2048] = {'x'};
|
|
|
|
GLint written = 0;
|
|
GLint size = 0;
|
|
GLenum type = 0;
|
|
|
|
glGetActiveAttrib(program, 0, 1, &written, &size, &type, buffer);
|
|
expectError(GL_NO_ERROR);
|
|
checkIntEquals(m_testCtx, written, 0);
|
|
}
|
|
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
struct PointerData
|
|
{
|
|
GLint size;
|
|
GLenum type;
|
|
GLint stride;
|
|
GLboolean normalized;
|
|
const void* pointer;
|
|
};
|
|
|
|
class VertexAttributeSizeCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeSizeCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
GLfloat vertexData[4] = {0.0f}; // never accessed
|
|
|
|
const PointerData pointers[] =
|
|
{
|
|
// size test
|
|
{ 4, GL_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 3, GL_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 2, GL_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 4, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 3, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 2, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_INT, 0, GL_FALSE, vertexData },
|
|
};
|
|
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx].size);
|
|
}
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint buf = 0;
|
|
GLuint vaos[2] = {0};
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
glGenBuffers(1, &buf);
|
|
glBindBuffer(GL_ARRAY_BUFFER, buf);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// initial
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, 4);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glVertexAttribPointer(0, pointers[0].size, pointers[0].type, pointers[0].normalized, pointers[0].stride, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glVertexAttribPointer(0, pointers[1].size, pointers[1].type, pointers[1].normalized, pointers[1].stride, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[1].size);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[0].size);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
glDeleteBuffers(1, &buf);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributeTypeCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeTypeCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
const GLfloat vertexData[4] = {0.0f}; // never accessed
|
|
|
|
// test VertexAttribPointer
|
|
{
|
|
const PointerData pointers[] =
|
|
{
|
|
{ 1, GL_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_FIXED, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_HALF_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_INT, 0, GL_FALSE, vertexData },
|
|
{ 4, GL_INT_2_10_10_10_REV, 0, GL_FALSE, vertexData },
|
|
{ 4, GL_UNSIGNED_INT_2_10_10_10_REV, 0, GL_FALSE, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
|
|
}
|
|
}
|
|
|
|
// test glVertexAttribIPointer
|
|
{
|
|
const PointerData pointers[] =
|
|
{
|
|
{ 1, GL_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_INT, 0, GL_FALSE, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint buf = 0;
|
|
GLuint vaos[2] = {0};
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
glGenBuffers(1, &buf);
|
|
glBindBuffer(GL_ARRAY_BUFFER, buf);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// initial
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_SHORT);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
glDeleteBuffers(1, &buf);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributeStrideCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeStrideCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
const GLfloat vertexData[4] = {0.0f}; // never accessed
|
|
|
|
struct StridePointerData
|
|
{
|
|
GLint size;
|
|
GLenum type;
|
|
GLint stride;
|
|
const void* pointer;
|
|
};
|
|
|
|
// test VertexAttribPointer
|
|
{
|
|
const StridePointerData pointers[] =
|
|
{
|
|
{ 1, GL_FLOAT, 0, vertexData },
|
|
{ 1, GL_FLOAT, 1, vertexData },
|
|
{ 1, GL_FLOAT, 4, vertexData },
|
|
{ 1, GL_HALF_FLOAT, 0, vertexData },
|
|
{ 1, GL_HALF_FLOAT, 1, vertexData },
|
|
{ 1, GL_HALF_FLOAT, 4, vertexData },
|
|
{ 1, GL_FIXED, 0, vertexData },
|
|
{ 1, GL_FIXED, 1, vertexData },
|
|
{ 1, GL_FIXED, 4, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, GL_FALSE, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
|
|
}
|
|
}
|
|
|
|
// test glVertexAttribIPointer
|
|
{
|
|
const StridePointerData pointers[] =
|
|
{
|
|
{ 1, GL_INT, 0, vertexData },
|
|
{ 1, GL_INT, 1, vertexData },
|
|
{ 1, GL_INT, 4, vertexData },
|
|
{ 4, GL_UNSIGNED_BYTE, 0, vertexData },
|
|
{ 4, GL_UNSIGNED_BYTE, 1, vertexData },
|
|
{ 4, GL_UNSIGNED_BYTE, 4, vertexData },
|
|
{ 2, GL_SHORT, 0, vertexData },
|
|
{ 2, GL_SHORT, 1, vertexData },
|
|
{ 2, GL_SHORT, 4, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint buf = 0;
|
|
GLuint vaos[2] = {0};
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
glGenBuffers(1, &buf);
|
|
glBindBuffer(GL_ARRAY_BUFFER, buf);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// initial
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 0);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 4, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 8, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 8);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 4);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
glDeleteBuffers(1, &buf);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributeNormalizedCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeNormalizedCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
const GLfloat vertexData[4] = {0.0f}; // never accessed
|
|
|
|
// test VertexAttribPointer
|
|
{
|
|
const PointerData pointers[] =
|
|
{
|
|
{ 1, GL_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_INT, 0, GL_FALSE, vertexData },
|
|
{ 4, GL_INT_2_10_10_10_REV, 0, GL_FALSE, vertexData },
|
|
{ 4, GL_UNSIGNED_INT_2_10_10_10_REV, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_BYTE, 0, GL_TRUE, vertexData },
|
|
{ 1, GL_SHORT, 0, GL_TRUE, vertexData },
|
|
{ 1, GL_INT, 0, GL_TRUE, vertexData },
|
|
{ 1, GL_UNSIGNED_BYTE, 0, GL_TRUE, vertexData },
|
|
{ 1, GL_UNSIGNED_SHORT, 0, GL_TRUE, vertexData },
|
|
{ 1, GL_UNSIGNED_INT, 0, GL_TRUE, vertexData },
|
|
{ 4, GL_INT_2_10_10_10_REV, 0, GL_TRUE, vertexData },
|
|
{ 4, GL_UNSIGNED_INT_2_10_10_10_REV, 0, GL_TRUE, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx].normalized);
|
|
}
|
|
}
|
|
|
|
// test glVertexAttribIPointer
|
|
{
|
|
const PointerData pointers[] =
|
|
{
|
|
{ 1, GL_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_INT, 0, GL_FALSE, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint buf = 0;
|
|
GLuint vaos[2] = {0};
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
glGenBuffers(1, &buf);
|
|
glBindBuffer(GL_ARRAY_BUFFER, buf);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// initial
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glVertexAttribPointer(0, 1, GL_INT, GL_TRUE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_TRUE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
glDeleteBuffers(1, &buf);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributeIntegerCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeIntegerCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
const GLfloat vertexData[4] = {0.0f}; // never accessed
|
|
|
|
// test VertexAttribPointer
|
|
{
|
|
const PointerData pointers[] =
|
|
{
|
|
{ 1, GL_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_FIXED, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_HALF_FLOAT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_INT, 0, GL_FALSE, vertexData },
|
|
{ 4, GL_INT_2_10_10_10_REV, 0, GL_FALSE, vertexData },
|
|
{ 4, GL_UNSIGNED_INT_2_10_10_10_REV, 0, GL_FALSE, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
|
|
}
|
|
}
|
|
|
|
// test glVertexAttribIPointer
|
|
{
|
|
const PointerData pointers[] =
|
|
{
|
|
{ 1, GL_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_INT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData },
|
|
{ 1, GL_UNSIGNED_INT, 0, GL_FALSE, vertexData },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint buf = 0;
|
|
GLuint vaos[2] = {0};
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
glGenBuffers(1, &buf);
|
|
glBindBuffer(GL_ARRAY_BUFFER, buf);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// initial
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glVertexAttribIPointer(0, 1, GL_INT, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
glDeleteBuffers(1, &buf);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributeEnabledCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeEnabledCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// VERTEX_ATTRIB_ARRAY_ENABLED
|
|
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
|
|
glEnableVertexAttribArray(0);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
|
|
glDisableVertexAttribArray(0);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint vaos[2] = {0};
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glBindVertexArray(vaos[0]);
|
|
glEnableVertexAttribArray(0);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glDisableVertexAttribArray(0);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributeDivisorCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeDivisorCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 0);
|
|
glVertexAttribDivisor(0, 1);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 1);
|
|
glVertexAttribDivisor(0, 5);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 5);
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint vaos[2] = {0};
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glBindVertexArray(vaos[0]);
|
|
glVertexAttribDivisor(0, 1);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glVertexAttribDivisor(0, 5);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 5);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 1);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributeBufferBindingCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributeBufferBindingCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
// initial
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 0);
|
|
|
|
GLuint bufferID;
|
|
glGenBuffers(1, &bufferID);
|
|
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufferID);
|
|
|
|
glDeleteBuffers(1, &bufferID);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint vaos[2] = {0};
|
|
GLuint bufs[2] = {0};
|
|
|
|
glGenBuffers(2, bufs);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glBindVertexArray(vaos[0]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[1]);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[0]);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
glDeleteBuffers(2, bufs);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class VertexAttributePointerCase : public ApiCase
|
|
{
|
|
public:
|
|
VertexAttributePointerCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
// Test with default VAO
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
|
|
|
|
StateQueryMemoryWriteGuard<GLvoid*> initialState;
|
|
glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &initialState);
|
|
initialState.verifyValidity(m_testCtx);
|
|
checkPointerEquals(m_testCtx, initialState, 0);
|
|
|
|
const GLfloat vertexData[4] = {0.0f}; // never accessed
|
|
const PointerData pointers[] =
|
|
{
|
|
{ 1, GL_BYTE, 0, GL_FALSE, &vertexData[2] },
|
|
{ 1, GL_SHORT, 0, GL_FALSE, &vertexData[1] },
|
|
{ 1, GL_INT, 0, GL_FALSE, &vertexData[2] },
|
|
{ 1, GL_FIXED, 0, GL_FALSE, &vertexData[2] },
|
|
{ 1, GL_FIXED, 0, GL_FALSE, &vertexData[1] },
|
|
{ 1, GL_FLOAT, 0, GL_FALSE, &vertexData[0] },
|
|
{ 1, GL_FLOAT, 0, GL_FALSE, &vertexData[3] },
|
|
{ 1, GL_FLOAT, 0, GL_FALSE, &vertexData[2] },
|
|
{ 1, GL_HALF_FLOAT, 0, GL_FALSE, &vertexData[0] },
|
|
{ 4, GL_HALF_FLOAT, 0, GL_FALSE, &vertexData[1] },
|
|
{ 4, GL_HALF_FLOAT, 0, GL_FALSE, &vertexData[2] },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
|
|
{
|
|
glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
StateQueryMemoryWriteGuard<GLvoid*> state;
|
|
glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
|
|
state.verifyValidity(m_testCtx);
|
|
checkPointerEquals(m_testCtx, state, pointers[ndx].pointer);
|
|
}
|
|
}
|
|
|
|
// Test with multiple VAOs
|
|
{
|
|
const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
|
|
|
|
GLuint vaos[2] = {0};
|
|
GLuint bufs[2] = {0};
|
|
|
|
glGenBuffers(2, bufs);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glGenVertexArrays(2, vaos);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 0 to some value
|
|
glBindVertexArray(vaos[0]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, glu::BufferOffsetAsPointer(8));
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// set vao 1 to some other value
|
|
glBindVertexArray(vaos[1]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, glu::BufferOffsetAsPointer(4));
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 1 state
|
|
{
|
|
StateQueryMemoryWriteGuard<GLvoid*> state;
|
|
glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
|
|
state.verifyValidity(m_testCtx);
|
|
checkPointerEquals(m_testCtx, state, glu::BufferOffsetAsPointer(4));
|
|
}
|
|
expectError(GL_NO_ERROR);
|
|
|
|
// verify vao 0 state
|
|
glBindVertexArray(vaos[0]);
|
|
{
|
|
StateQueryMemoryWriteGuard<GLvoid*> state;
|
|
glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
|
|
state.verifyValidity(m_testCtx);
|
|
checkPointerEquals(m_testCtx, state, glu::BufferOffsetAsPointer(8));
|
|
}
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glDeleteVertexArrays(2, vaos);
|
|
glDeleteBuffers(2, bufs);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
}
|
|
};
|
|
|
|
class UniformValueFloatCase : public ApiCase
|
|
{
|
|
public:
|
|
UniformValueFloatCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform highp float floatUniform;\n"
|
|
"uniform highp vec2 float2Uniform;\n"
|
|
"uniform highp vec3 float3Uniform;\n"
|
|
"uniform highp vec4 float4Uniform;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n"
|
|
"}\n";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
glUseProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint location;
|
|
|
|
location = glGetUniformLocation(program,"floatUniform");
|
|
glUniform1f(location, 1.0f);
|
|
verifyUniformValue1f(m_testCtx, *this, program, location, 1.0f);
|
|
|
|
location = glGetUniformLocation(program,"float2Uniform");
|
|
glUniform2f(location, 1.0f, 2.0f);
|
|
verifyUniformValue2f(m_testCtx, *this, program, location, 1.0f, 2.0f);
|
|
|
|
location = glGetUniformLocation(program,"float3Uniform");
|
|
glUniform3f(location, 1.0f, 2.0f, 3.0f);
|
|
verifyUniformValue3f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f);
|
|
|
|
location = glGetUniformLocation(program,"float4Uniform");
|
|
glUniform4f(location, 1.0f, 2.0f, 3.0f, 4.0f);
|
|
verifyUniformValue4f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f, 4.0f);
|
|
|
|
glUseProgram(0);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class UniformValueIntCase : public ApiCase
|
|
{
|
|
public:
|
|
UniformValueIntCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform highp int intUniform;\n"
|
|
"uniform highp ivec2 int2Uniform;\n"
|
|
"uniform highp ivec3 int3Uniform;\n"
|
|
"uniform highp ivec4 int4Uniform;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n"
|
|
"}\n";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
glUseProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint location;
|
|
|
|
location = glGetUniformLocation(program,"intUniform");
|
|
glUniform1i(location, 1);
|
|
verifyUniformValue1i(m_testCtx, *this, program, location, 1);
|
|
|
|
location = glGetUniformLocation(program,"int2Uniform");
|
|
glUniform2i(location, 1, 2);
|
|
verifyUniformValue2i(m_testCtx, *this, program, location, 1, 2);
|
|
|
|
location = glGetUniformLocation(program,"int3Uniform");
|
|
glUniform3i(location, 1, 2, 3);
|
|
verifyUniformValue3i(m_testCtx, *this, program, location, 1, 2, 3);
|
|
|
|
location = glGetUniformLocation(program,"int4Uniform");
|
|
glUniform4i(location, 1, 2, 3, 4);
|
|
verifyUniformValue4i(m_testCtx, *this, program, location, 1, 2, 3, 4);
|
|
|
|
glUseProgram(0);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class UniformValueUintCase : public ApiCase
|
|
{
|
|
public:
|
|
UniformValueUintCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform highp uint uintUniform;\n"
|
|
"uniform highp uvec2 uint2Uniform;\n"
|
|
"uniform highp uvec3 uint3Uniform;\n"
|
|
"uniform highp uvec4 uint4Uniform;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(float(uintUniform + uint2Uniform.x + uint3Uniform.x + uint4Uniform.x));\n"
|
|
"}\n";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
glUseProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint location;
|
|
|
|
location = glGetUniformLocation(program,"uintUniform");
|
|
glUniform1ui(location, 1);
|
|
verifyUniformValue1ui(m_testCtx, *this, program, location, 1);
|
|
|
|
location = glGetUniformLocation(program,"uint2Uniform");
|
|
glUniform2ui(location, 1, 2);
|
|
verifyUniformValue2ui(m_testCtx, *this, program, location, 1, 2);
|
|
|
|
location = glGetUniformLocation(program,"uint3Uniform");
|
|
glUniform3ui(location, 1, 2, 3);
|
|
verifyUniformValue3ui(m_testCtx, *this, program, location, 1, 2, 3);
|
|
|
|
location = glGetUniformLocation(program,"uint4Uniform");
|
|
glUniform4ui(location, 1, 2, 3, 4);
|
|
verifyUniformValue4ui(m_testCtx, *this, program, location, 1, 2, 3, 4);
|
|
|
|
glUseProgram(0);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
|
|
class UniformValueBooleanCase : public ApiCase
|
|
{
|
|
public:
|
|
UniformValueBooleanCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform bool boolUniform;\n"
|
|
"uniform bvec2 bool2Uniform;\n"
|
|
"uniform bvec3 bool3Uniform;\n"
|
|
"uniform bvec4 bool4Uniform;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + float(bool3Uniform.x) + float(bool4Uniform.x));\n"
|
|
"}\n";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
glUseProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint location;
|
|
|
|
// int conversion
|
|
|
|
location = glGetUniformLocation(program,"boolUniform");
|
|
glUniform1i(location, 1);
|
|
verifyUniformValue1i(m_testCtx, *this, program, location, 1);
|
|
|
|
location = glGetUniformLocation(program,"bool2Uniform");
|
|
glUniform2i(location, 1, 2);
|
|
verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
|
|
|
|
location = glGetUniformLocation(program,"bool3Uniform");
|
|
glUniform3i(location, 0, 1, 2);
|
|
verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
|
|
|
|
location = glGetUniformLocation(program,"bool4Uniform");
|
|
glUniform4i(location, 1, 0, 1, -1);
|
|
verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
|
|
|
|
// float conversion
|
|
|
|
location = glGetUniformLocation(program,"boolUniform");
|
|
glUniform1f(location, 1.0f);
|
|
verifyUniformValue1i(m_testCtx, *this, program, location, 1);
|
|
|
|
location = glGetUniformLocation(program,"bool2Uniform");
|
|
glUniform2f(location, 1.0f, 0.1f);
|
|
verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
|
|
|
|
location = glGetUniformLocation(program,"bool3Uniform");
|
|
glUniform3f(location, 0.0f, 0.1f, -0.1f);
|
|
verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
|
|
|
|
location = glGetUniformLocation(program,"bool4Uniform");
|
|
glUniform4f(location, 1.0f, 0.0f, 0.1f, -0.9f);
|
|
verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
|
|
|
|
glUseProgram(0);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class UniformValueSamplerCase : public ApiCase
|
|
{
|
|
public:
|
|
UniformValueSamplerCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(0.0);\n"
|
|
"}\n";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"uniform highp sampler2D uniformSampler;\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(textureSize(uniformSampler, 0).x);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
glUseProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint location;
|
|
|
|
location = glGetUniformLocation(program,"uniformSampler");
|
|
glUniform1i(location, 1);
|
|
verifyUniformValue1i(m_testCtx, *this, program, location, 1);
|
|
|
|
glUseProgram(0);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class UniformValueArrayCase : public ApiCase
|
|
{
|
|
public:
|
|
UniformValueArrayCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform highp float arrayUniform[5];"
|
|
"uniform highp vec2 array2Uniform[5];"
|
|
"uniform highp vec3 array3Uniform[5];"
|
|
"uniform highp vec4 array4Uniform[5];"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = \n"
|
|
" + vec4(arrayUniform[0] + arrayUniform[1] + arrayUniform[2] + arrayUniform[3] + arrayUniform[4])\n"
|
|
" + vec4(array2Uniform[0].x + array2Uniform[1].x + array2Uniform[2].x + array2Uniform[3].x + array2Uniform[4].x)\n"
|
|
" + vec4(array3Uniform[0].x + array3Uniform[1].x + array3Uniform[2].x + array3Uniform[3].x + array3Uniform[4].x)\n"
|
|
" + vec4(array4Uniform[0].x + array4Uniform[1].x + array4Uniform[2].x + array4Uniform[3].x + array4Uniform[4].x);\n"
|
|
"}\n";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
glUseProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint location;
|
|
|
|
float uniformValue[5 * 4] =
|
|
{
|
|
-1.0f, 0.1f, 4.0f, 800.0f,
|
|
13.0f, 55.0f, 12.0f, 91.0f,
|
|
-55.1f, 1.1f, 98.0f, 19.0f,
|
|
41.0f, 65.0f, 4.0f, 12.2f,
|
|
95.0f, 77.0f, 32.0f, 48.0f
|
|
};
|
|
|
|
location = glGetUniformLocation(program,"arrayUniform");
|
|
glUniform1fv(location, 5, uniformValue);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[0]"), uniformValue[0]);
|
|
verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[1]"), uniformValue[1]);
|
|
verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[2]"), uniformValue[2]);
|
|
verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[3]"), uniformValue[3]);
|
|
verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[4]"), uniformValue[4]);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
location = glGetUniformLocation(program,"array2Uniform");
|
|
glUniform2fv(location, 5, uniformValue);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[0]"), uniformValue[2 * 0], uniformValue[(2 * 0) + 1]);
|
|
verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[1]"), uniformValue[2 * 1], uniformValue[(2 * 1) + 1]);
|
|
verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[2]"), uniformValue[2 * 2], uniformValue[(2 * 2) + 1]);
|
|
verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[3]"), uniformValue[2 * 3], uniformValue[(2 * 3) + 1]);
|
|
verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[4]"), uniformValue[2 * 4], uniformValue[(2 * 4) + 1]);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
location = glGetUniformLocation(program,"array3Uniform");
|
|
glUniform3fv(location, 5, uniformValue);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[0]"), uniformValue[3 * 0], uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]);
|
|
verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[1]"), uniformValue[3 * 1], uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]);
|
|
verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[2]"), uniformValue[3 * 2], uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]);
|
|
verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[3]"), uniformValue[3 * 3], uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]);
|
|
verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[4]"), uniformValue[3 * 4], uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
location = glGetUniformLocation(program,"array4Uniform");
|
|
glUniform4fv(location, 5, uniformValue);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[0]"), uniformValue[4 * 0], uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]);
|
|
verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[1]"), uniformValue[4 * 1], uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]);
|
|
verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[2]"), uniformValue[4 * 2], uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]);
|
|
verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[3]"), uniformValue[4 * 3], uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]);
|
|
verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[4]"), uniformValue[4 * 4], uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
glUseProgram(0);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class UniformValueMatrixCase : public ApiCase
|
|
{
|
|
public:
|
|
UniformValueMatrixCase (Context& context, const char* name, const char* description)
|
|
: ApiCase(context, name, description)
|
|
{
|
|
}
|
|
|
|
void test (void)
|
|
{
|
|
static const char* testVertSource =
|
|
"#version 300 es\n"
|
|
"uniform highp mat2 mat2Uniform;"
|
|
"uniform highp mat3 mat3Uniform;"
|
|
"uniform highp mat4 mat4Uniform;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n"
|
|
"}\n";
|
|
static const char* testFragSource =
|
|
"#version 300 es\n"
|
|
"layout(location = 0) out mediump vec4 fragColor;"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" fragColor = vec4(0.0);\n"
|
|
"}\n";
|
|
|
|
GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
|
|
glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
|
|
|
|
glCompileShader(shaderVert);
|
|
glCompileShader(shaderFrag);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLuint program = glCreateProgram();
|
|
glAttachShader(program, shaderVert);
|
|
glAttachShader(program, shaderFrag);
|
|
glLinkProgram(program);
|
|
glUseProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
GLint location;
|
|
|
|
float matrixValues[4 * 4] =
|
|
{
|
|
-1.0f, 0.1f, 4.0f, 800.0f,
|
|
13.0f, 55.0f, 12.0f, 91.0f,
|
|
-55.1f, 1.1f, 98.0f, 19.0f,
|
|
41.0f, 65.0f, 4.0f, 12.2f,
|
|
};
|
|
|
|
// the values of the matrix are returned in column major order but they can be given in either order
|
|
|
|
location = glGetUniformLocation(program,"mat2Uniform");
|
|
glUniformMatrix2fv(location, 1, GL_FALSE, matrixValues);
|
|
verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, false);
|
|
glUniformMatrix2fv(location, 1, GL_TRUE, matrixValues);
|
|
verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, true);
|
|
|
|
location = glGetUniformLocation(program,"mat3Uniform");
|
|
glUniformMatrix3fv(location, 1, GL_FALSE, matrixValues);
|
|
verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, false);
|
|
glUniformMatrix3fv(location, 1, GL_TRUE, matrixValues);
|
|
verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, true);
|
|
|
|
location = glGetUniformLocation(program,"mat4Uniform");
|
|
glUniformMatrix4fv(location, 1, GL_FALSE, matrixValues);
|
|
verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, false);
|
|
glUniformMatrix4fv(location, 1, GL_TRUE, matrixValues);
|
|
verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, true);
|
|
|
|
glUseProgram(0);
|
|
glDeleteShader(shaderVert);
|
|
glDeleteShader(shaderFrag);
|
|
glDeleteProgram(program);
|
|
expectError(GL_NO_ERROR);
|
|
}
|
|
};
|
|
|
|
class PrecisionFormatCase : public ApiCase
|
|
{
|
|
public:
|
|
struct RequiredFormat
|
|
{
|
|
int negativeRange;
|
|
int positiveRange;
|
|
int precision;
|
|
};
|
|
|
|
PrecisionFormatCase (Context& context, const char* name, const char* description, glw::GLenum shaderType, glw::GLenum precisionType)
|
|
: ApiCase (context, name, description)
|
|
, m_shaderType (shaderType)
|
|
, m_precisionType (precisionType)
|
|
{
|
|
}
|
|
|
|
private:
|
|
void test (void)
|
|
{
|
|
const RequiredFormat expected = getRequiredFormat();
|
|
bool error = false;
|
|
gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean> shaderCompiler;
|
|
gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[2]> range;
|
|
gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> precision;
|
|
|
|
// query values
|
|
glGetShaderPrecisionFormat(m_shaderType, m_precisionType, range, &precision);
|
|
expectError(GL_NO_ERROR);
|
|
|
|
if (!range.verifyValidity(m_testCtx))
|
|
return;
|
|
if (!precision.verifyValidity(m_testCtx))
|
|
return;
|
|
|
|
m_log
|
|
<< tcu::TestLog::Message
|
|
<< "range[0] = " << range[0] << "\n"
|
|
<< "range[1] = " << range[1] << "\n"
|
|
<< "precision = " << precision
|
|
<< tcu::TestLog::EndMessage;
|
|
|
|
// verify values
|
|
|
|
if (m_precisionType == GL_HIGH_FLOAT)
|
|
{
|
|
// highp float must be IEEE 754 single
|
|
|
|
if (range[0] != expected.negativeRange ||
|
|
range[1] != expected.positiveRange ||
|
|
precision != expected.precision)
|
|
{
|
|
m_log
|
|
<< tcu::TestLog::Message
|
|
<< "// ERROR: Invalid precision format, expected:\n"
|
|
<< "\trange[0] = " << expected.negativeRange << "\n"
|
|
<< "\trange[1] = " << expected.positiveRange << "\n"
|
|
<< "\tprecision = " << expected.precision
|
|
<< tcu::TestLog::EndMessage;
|
|
error = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (range[0] < expected.negativeRange)
|
|
{
|
|
m_log << tcu::TestLog::Message << "// ERROR: Invalid range[0], expected greater or equal to " << expected.negativeRange << tcu::TestLog::EndMessage;
|
|
error = true;
|
|
}
|
|
|
|
if (range[1] < expected.positiveRange)
|
|
{
|
|
m_log << tcu::TestLog::Message << "// ERROR: Invalid range[1], expected greater or equal to " << expected.positiveRange << tcu::TestLog::EndMessage;
|
|
error = true;
|
|
}
|
|
|
|
if (precision < expected.precision)
|
|
{
|
|
m_log << tcu::TestLog::Message << "// ERROR: Invalid precision, expected greater or equal to " << expected.precision << tcu::TestLog::EndMessage;
|
|
error = true;
|
|
}
|
|
}
|
|
|
|
if (error)
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid precision/range");
|
|
}
|
|
|
|
RequiredFormat getRequiredFormat (void) const
|
|
{
|
|
// Precisions for different types.
|
|
const RequiredFormat requirements[] =
|
|
{
|
|
{ 0, 0, 8 }, //!< lowp float
|
|
{ 13, 13, 10 }, //!< mediump float
|
|
{ 127, 127, 23 }, //!< highp float
|
|
{ 8, 7, 0 }, //!< lowp int
|
|
{ 15, 14, 0 }, //!< mediump int
|
|
{ 31, 30, 0 }, //!< highp int
|
|
};
|
|
const int ndx = (int)m_precisionType - (int)GL_LOW_FLOAT;
|
|
|
|
DE_ASSERT(ndx >= 0);
|
|
DE_ASSERT(ndx < DE_LENGTH_OF_ARRAY(requirements));
|
|
return requirements[ndx];
|
|
}
|
|
|
|
const glw::GLenum m_shaderType;
|
|
const glw::GLenum m_precisionType;
|
|
};
|
|
|
|
} // anonymous
|
|
|
|
|
|
ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
|
|
: TestCaseGroup(context, "shader", "Shader State Query tests")
|
|
{
|
|
}
|
|
|
|
void ShaderStateQueryTests::init (void)
|
|
{
|
|
// shader
|
|
addChild(new ShaderTypeCase (m_context, "shader_type", "SHADER_TYPE"));
|
|
addChild(new ShaderCompileStatusCase (m_context, "shader_compile_status", "COMPILE_STATUS"));
|
|
addChild(new ShaderInfoLogCase (m_context, "shader_info_log_length", "INFO_LOG_LENGTH"));
|
|
addChild(new ShaderSourceCase (m_context, "shader_source_length", "SHADER_SOURCE_LENGTH"));
|
|
|
|
// shader and program
|
|
addChild(new DeleteStatusCase (m_context, "delete_status", "DELETE_STATUS"));
|
|
|
|
// vertex-attrib
|
|
addChild(new CurrentVertexAttribInitialCase (m_context, "current_vertex_attrib_initial", "CURRENT_VERTEX_ATTRIB"));
|
|
addChild(new CurrentVertexAttribFloatCase (m_context, "current_vertex_attrib_float", "CURRENT_VERTEX_ATTRIB"));
|
|
addChild(new CurrentVertexAttribIntCase (m_context, "current_vertex_attrib_int", "CURRENT_VERTEX_ATTRIB"));
|
|
addChild(new CurrentVertexAttribUintCase (m_context, "current_vertex_attrib_uint", "CURRENT_VERTEX_ATTRIB"));
|
|
addChild(new CurrentVertexAttribConversionCase (m_context, "current_vertex_attrib_float_to_int", "CURRENT_VERTEX_ATTRIB"));
|
|
|
|
// program
|
|
addChild(new ProgramInfoLogCase (m_context, "program_info_log_length", "INFO_LOG_LENGTH", ProgramInfoLogCase::BUILDERROR_COMPILE));
|
|
addChild(new ProgramInfoLogCase (m_context, "program_info_log_length_link_error", "INFO_LOG_LENGTH", ProgramInfoLogCase::BUILDERROR_LINK));
|
|
addChild(new ProgramValidateStatusCase (m_context, "program_validate_status", "VALIDATE_STATUS"));
|
|
addChild(new ProgramAttachedShadersCase (m_context, "program_attached_shaders", "ATTACHED_SHADERS"));
|
|
|
|
addChild(new ProgramActiveUniformNameCase (m_context, "program_active_uniform_name", "ACTIVE_UNIFORMS and ACTIVE_UNIFORM_MAX_LENGTH"));
|
|
addChild(new ProgramUniformCase (m_context, "program_active_uniform_types", "UNIFORM_TYPE, UNIFORM_SIZE, and UNIFORM_IS_ROW_MAJOR"));
|
|
addChild(new ProgramActiveUniformBlocksCase (m_context, "program_active_uniform_blocks", "ACTIVE_UNIFORM_BLOCK_x"));
|
|
addChild(new ProgramBinaryCase (m_context, "program_binary", "PROGRAM_BINARY_LENGTH and PROGRAM_BINARY_RETRIEVABLE_HINT"));
|
|
|
|
// transform feedback
|
|
addChild(new TransformFeedbackCase (m_context, "transform_feedback", "TRANSFORM_FEEDBACK_BUFFER_MODE, TRANSFORM_FEEDBACK_VARYINGS, TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"));
|
|
|
|
// attribute related
|
|
addChild(new ActiveAttributesCase (m_context, "active_attributes", "ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH"));
|
|
addChild(new VertexAttributeSizeCase (m_context, "vertex_attrib_size", "VERTEX_ATTRIB_ARRAY_SIZE"));
|
|
addChild(new VertexAttributeTypeCase (m_context, "vertex_attrib_type", "VERTEX_ATTRIB_ARRAY_TYPE"));
|
|
addChild(new VertexAttributeStrideCase (m_context, "vertex_attrib_stride", "VERTEX_ATTRIB_ARRAY_STRIDE"));
|
|
addChild(new VertexAttributeNormalizedCase (m_context, "vertex_attrib_normalized", "VERTEX_ATTRIB_ARRAY_NORMALIZED"));
|
|
addChild(new VertexAttributeIntegerCase (m_context, "vertex_attrib_integer", "VERTEX_ATTRIB_ARRAY_INTEGER"));
|
|
addChild(new VertexAttributeEnabledCase (m_context, "vertex_attrib_array_enabled", "VERTEX_ATTRIB_ARRAY_ENABLED"));
|
|
addChild(new VertexAttributeDivisorCase (m_context, "vertex_attrib_array_divisor", "VERTEX_ATTRIB_ARRAY_DIVISOR"));
|
|
addChild(new VertexAttributeBufferBindingCase (m_context, "vertex_attrib_array_buffer_binding", "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"));
|
|
addChild(new VertexAttributePointerCase (m_context, "vertex_attrib_pointerv", "GetVertexAttribPointerv"));
|
|
|
|
// uniform values
|
|
addChild(new UniformValueFloatCase (m_context, "uniform_value_float", "GetUniform*"));
|
|
addChild(new UniformValueIntCase (m_context, "uniform_value_int", "GetUniform*"));
|
|
addChild(new UniformValueUintCase (m_context, "uniform_value_uint", "GetUniform*"));
|
|
addChild(new UniformValueBooleanCase (m_context, "uniform_value_boolean", "GetUniform*"));
|
|
addChild(new UniformValueSamplerCase (m_context, "uniform_value_sampler", "GetUniform*"));
|
|
addChild(new UniformValueArrayCase (m_context, "uniform_value_array", "GetUniform*"));
|
|
addChild(new UniformValueMatrixCase (m_context, "uniform_value_matrix", "GetUniform*"));
|
|
|
|
// precision format query
|
|
addChild(new PrecisionFormatCase (m_context, "precision_vertex_lowp_float", "GetShaderPrecisionFormat", GL_VERTEX_SHADER, GL_LOW_FLOAT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_vertex_mediump_float", "GetShaderPrecisionFormat", GL_VERTEX_SHADER, GL_MEDIUM_FLOAT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_vertex_highp_float", "GetShaderPrecisionFormat", GL_VERTEX_SHADER, GL_HIGH_FLOAT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_vertex_lowp_int", "GetShaderPrecisionFormat", GL_VERTEX_SHADER, GL_LOW_INT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_vertex_mediump_int", "GetShaderPrecisionFormat", GL_VERTEX_SHADER, GL_MEDIUM_INT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_vertex_highp_int", "GetShaderPrecisionFormat", GL_VERTEX_SHADER, GL_HIGH_INT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_fragment_lowp_float", "GetShaderPrecisionFormat", GL_FRAGMENT_SHADER, GL_LOW_FLOAT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_fragment_mediump_float", "GetShaderPrecisionFormat", GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_fragment_highp_float", "GetShaderPrecisionFormat", GL_FRAGMENT_SHADER, GL_HIGH_FLOAT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_fragment_lowp_int", "GetShaderPrecisionFormat", GL_FRAGMENT_SHADER, GL_LOW_INT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_fragment_mediump_int", "GetShaderPrecisionFormat", GL_FRAGMENT_SHADER, GL_MEDIUM_INT));
|
|
addChild(new PrecisionFormatCase (m_context, "precision_fragment_highp_int", "GetShaderPrecisionFormat", GL_FRAGMENT_SHADER, GL_HIGH_INT));
|
|
}
|
|
|
|
} // Functional
|
|
} // gles3
|
|
} // deqp
|