blob: aea72011355fcfcaf53259bd800096c8e855b43d [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2015-2016 The Khronos Group Inc.
*
* 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
*/ /*-------------------------------------------------------------------*/
/**
*/ /*!
* \file gl4cDirectStateAccessTexturesTests.cpp
* \brief Conformance tests for the Direct State Access feature functionality (Texture access part).
*/ /*-----------------------------------------------------------------------------------------------------------*/
/* Uncomment this if SubImageErrorsTest crashes during negative test of TextureSubImage (negative value width/height/depth passed to the function). */
/* #define TURN_OFF_SUB_IMAGE_ERRORS_TEST_OF_NEGATIVE_WIDTH_HEIGHT_OR_DEPTH */
/* Includes. */
#include "gl4cDirectStateAccessTests.hpp"
#include "deSharedPtr.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluPixelTransfer.hpp"
#include "gluStrUtil.hpp"
#include "tcuFuzzyImageCompare.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuSurface.hpp"
#include "tcuTestLog.hpp"
#include "glw.h"
#include "glwFunctions.hpp"
#include <algorithm>
#include <climits>
#include <set>
#include <sstream>
#include <stack>
#include <string>
namespace gl4cts
{
namespace DirectStateAccess
{
namespace Textures
{
/******************************** Creation Test Implementation ********************************/
/** @brief Creation Test constructor.
*
* @param [in] context OpenGL context.
*/
CreationTest::CreationTest(deqp::Context& context)
: deqp::TestCase(context, "textures_creation", "Texture Objects Creation Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Creation Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult CreationTest::iterate()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get context setup. */
bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
return STOP;
}
/* Running tests. */
bool is_ok = true;
bool is_error = false;
/* Textures' objects */
static const glw::GLenum texture_targets[] = { GL_TEXTURE_1D,
GL_TEXTURE_2D,
GL_TEXTURE_3D,
GL_TEXTURE_1D_ARRAY,
GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_RECTANGLE,
GL_TEXTURE_CUBE_MAP,
GL_TEXTURE_CUBE_MAP_ARRAY,
GL_TEXTURE_BUFFER,
GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_2D_MULTISAMPLE_ARRAY };
static const glw::GLuint texture_targets_count = sizeof(texture_targets) / sizeof(texture_targets[0]);
static const glw::GLuint textures_count = 2;
glw::GLuint textures_legacy[textures_count] = {};
glw::GLuint textures_dsa[texture_targets_count][textures_count] = {};
try
{
/* Check legacy state creation. */
gl.genTextures(textures_count, textures_legacy);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed");
for (glw::GLuint i = 0; i < textures_count; ++i)
{
if (gl.isTexture(textures_legacy[i]))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "GenTextures has created default objects, but it should create only a names."
<< tcu::TestLog::EndMessage;
}
}
/* Check direct state creation. */
for (glw::GLuint j = 0; j < texture_targets_count; ++j)
{
gl.createTextures(texture_targets[j], textures_count, textures_dsa[j]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTextures has failed");
for (glw::GLuint i = 0; i < textures_count; ++i)
{
if (!gl.isTexture(textures_dsa[j][i]))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "CreateTextures has not created default objects for target "
<< glu::getTextureTargetStr(texture_targets[j]) << "." << tcu::TestLog::EndMessage;
}
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
for (glw::GLuint i = 0; i < textures_count; ++i)
{
if (textures_legacy[i])
{
gl.deleteTextures(1, &textures_legacy[i]);
textures_legacy[i] = 0;
}
for (glw::GLuint j = 0; j < texture_targets_count; ++j)
{
if (textures_dsa[j][i])
{
gl.deleteTextures(1, &textures_dsa[j][i]);
textures_dsa[j][i] = 0;
}
}
}
/* Errors clean up. */
while (gl.getError())
;
/* Result's setup. */
if (is_ok)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (is_error)
{
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
/******************************** Reference Data Implementation *****************************/
/** @brief Internal Format selector.
*
* @tparam T Type.
* @tparam S Size (# of components).
* @tparam N Is normalized.
*
* @return Internal format.
*/
template <>
glw::GLenum Reference::InternalFormat<glw::GLbyte, 1, false>()
{
return GL_R8I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLbyte, 2, false>()
{
return GL_RG8I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLbyte, 3, false>()
{
return GL_RGB8I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLbyte, 4, false>()
{
return GL_RGBA8I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 1, false>()
{
return GL_R8UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 2, false>()
{
return GL_RG8UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 3, false>()
{
return GL_RGB8UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 4, false>()
{
return GL_RGBA8UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLshort, 1, false>()
{
return GL_R16I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLshort, 2, false>()
{
return GL_RG16I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLshort, 3, false>()
{
return GL_RGB16I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLshort, 4, false>()
{
return GL_RGBA16I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 1, false>()
{
return GL_R16UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 2, false>()
{
return GL_RG16UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 3, false>()
{
return GL_RGB16UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 4, false>()
{
return GL_RGBA16UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLint, 1, false>()
{
return GL_R32I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLint, 2, false>()
{
return GL_RG32I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLint, 3, false>()
{
return GL_RGB32I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLint, 4, false>()
{
return GL_RGBA32I;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLuint, 1, false>()
{
return GL_R32UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLuint, 2, false>()
{
return GL_RG32UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLuint, 3, false>()
{
return GL_RGB32UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLuint, 4, false>()
{
return GL_RGBA32UI;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 1, true>()
{
return GL_R8;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 2, true>()
{
return GL_RG8;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 3, true>()
{
return GL_RGB8;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLubyte, 4, true>()
{
return GL_RGBA8;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 1, true>()
{
return GL_R16;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 2, true>()
{
return GL_RG16;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 3, true>()
{
return GL_RGB16;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLushort, 4, true>()
{
return GL_RGBA16;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLfloat, 1, true>()
{
return GL_R32F;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLfloat, 2, true>()
{
return GL_RG32F;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLfloat, 3, true>()
{
return GL_RGB32F;
}
template <>
glw::GLenum Reference::InternalFormat<glw::GLfloat, 4, true>()
{
return GL_RGBA32F;
}
/** @brief Format selector.
*
* @tparam S Size (# of components).
* @tparam N Is normalized.
*
* @return format.
*/
template <>
glw::GLenum Reference::Format<1, false>()
{
return GL_RED_INTEGER;
}
template <>
glw::GLenum Reference::Format<2, false>()
{
return GL_RG_INTEGER;
}
template <>
glw::GLenum Reference::Format<3, false>()
{
return GL_RGB_INTEGER;
}
template <>
glw::GLenum Reference::Format<4, false>()
{
return GL_RGBA_INTEGER;
}
template <>
glw::GLenum Reference::Format<1, true>()
{
return GL_RED;
}
template <>
glw::GLenum Reference::Format<2, true>()
{
return GL_RG;
}
template <>
glw::GLenum Reference::Format<3, true>()
{
return GL_RGB;
}
template <>
glw::GLenum Reference::Format<4, true>()
{
return GL_RGBA;
}
/** @brief Type selector.
*
* @tparam T Type.
*
* @return Type.
*/
template <>
glw::GLenum Reference::Type<glw::GLbyte>()
{
return GL_BYTE;
}
template <>
glw::GLenum Reference::Type<glw::GLubyte>()
{
return GL_UNSIGNED_BYTE;
}
template <>
glw::GLenum Reference::Type<glw::GLshort>()
{
return GL_SHORT;
}
template <>
glw::GLenum Reference::Type<glw::GLushort>()
{
return GL_UNSIGNED_SHORT;
}
template <>
glw::GLenum Reference::Type<glw::GLint>()
{
return GL_INT;
}
template <>
glw::GLenum Reference::Type<glw::GLuint>()
{
return GL_UNSIGNED_INT;
}
template <>
glw::GLenum Reference::Type<glw::GLfloat>()
{
return GL_FLOAT;
}
/** @brief Reference data selector.
*
* @tparam T Type.
* @tparam N Is normalized.
*
* @return Reference data.
*/
/* RGBA8I */
template <>
const glw::GLbyte* Reference::ReferenceData<glw::GLbyte, false>()
{
static const glw::GLbyte reference[s_reference_count] = {
0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20, -21, 22, -23,
24, -25, 26, -27, 28, -29, 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44, -45, 46, -47,
48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59, 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71,
72, -73, 74, -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89, 90, -91, 92, -93, 94, -95
};
return reference;
}
/* RGBA8UI */
template <>
const glw::GLubyte* Reference::ReferenceData<glw::GLubyte, false>()
{
static const glw::GLubyte reference[s_reference_count] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
};
return reference;
}
/* RGBA16I */
template <>
const glw::GLshort* Reference::ReferenceData<glw::GLshort, false>()
{
static const glw::GLshort reference[s_reference_count] = {
0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20, -21, 22, -23,
24, -25, 26, -27, 28, -29, 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44, -45, 46, -47,
48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59, 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71,
72, -73, 74, -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89, 90, -91, 92, -93, 94, -95
};
return reference;
}
/* RGBA16UI */
template <>
const glw::GLushort* Reference::ReferenceData<glw::GLushort, false>()
{
static const glw::GLushort reference[s_reference_count] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
};
return reference;
}
/* RGBA32I */
template <>
const glw::GLint* Reference::ReferenceData<glw::GLint, false>()
{
static const glw::GLint reference[s_reference_count] = {
0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20, -21, 22, -23,
24, -25, 26, -27, 28, -29, 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44, -45, 46, -47,
48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59, 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71,
72, -73, 74, -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89, 90, -91, 92, -93, 94, -95
};
return reference;
}
/* RGBA32UI */
template <>
const glw::GLuint* Reference::ReferenceData<glw::GLuint, false>()
{
static const glw::GLuint reference[s_reference_count] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
};
return reference;
}
/* RGBA8 */
template <>
const glw::GLubyte* Reference::ReferenceData<glw::GLubyte, true>()
{
static const glw::GLubyte reference[s_reference_count] = {
0, 2, 5, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 34, 37, 40, 42, 45, 48, 51,
53, 56, 59, 61, 64, 67, 69, 72, 75, 77, 80, 83, 85, 88, 91, 93, 96, 99, 102, 104,
107, 110, 112, 115, 118, 120, 123, 126, 128, 131, 134, 136, 139, 142, 144, 147, 150, 153, 155, 158,
161, 163, 166, 169, 171, 174, 177, 179, 182, 185, 187, 190, 193, 195, 198, 201, 204, 206, 209, 212,
214, 217, 220, 222, 225, 228, 230, 233, 236, 238, 241, 244, 246, 249, 252, 255
};
return reference;
}
/* RGBA16 */
template <>
const glw::GLushort* Reference::ReferenceData<glw::GLushort, true>()
{
static const glw::GLushort reference[s_reference_count] = {
0, 689, 1379, 2069, 2759, 3449, 4139, 4828, 5518, 6208, 6898, 7588, 8278, 8967, 9657, 10347,
11037, 11727, 12417, 13107, 13796, 14486, 15176, 15866, 16556, 17246, 17935, 18625, 19315, 20005, 20695, 21385,
22074, 22764, 23454, 24144, 24834, 25524, 26214, 26903, 27593, 28283, 28973, 29663, 30353, 31042, 31732, 32422,
33112, 33802, 34492, 35181, 35871, 36561, 37251, 37941, 38631, 39321, 40010, 40700, 41390, 42080, 42770, 43460,
44149, 44839, 45529, 46219, 46909, 47599, 48288, 48978, 49668, 50358, 51048, 51738, 52428, 53117, 53807, 54497,
55187, 55877, 56567, 57256, 57946, 58636, 59326, 60016, 60706, 61395, 62085, 62775, 63465, 64155, 64845, 65535
};
return reference;
}
/* RGBA32F */
template <>
const glw::GLfloat* Reference::ReferenceData<glw::GLfloat, true>()
{
static const glw::GLfloat reference[s_reference_count] = {
0.f, 0.0105263158f, 0.0210526316f, 0.0315789474f, 0.0421052632f, 0.0526315789f,
0.0631578947f, 0.0736842105f, 0.0842105263f, 0.0947368421f, 0.1052631579f, 0.1157894737f,
0.1263157895f, 0.1368421053f, 0.1473684211f, 0.1578947368f, 0.1684210526f, 0.1789473684f,
0.1894736842f, 0.2f, 0.2105263158f, 0.2210526316f, 0.2315789474f, 0.2421052632f,
0.2526315789f, 0.2631578947f, 0.2736842105f, 0.2842105263f, 0.2947368421f, 0.3052631579f,
0.3157894737f, 0.3263157895f, 0.3368421053f, 0.3473684211f, 0.3578947368f, 0.3684210526f,
0.3789473684f, 0.3894736842f, 0.4f, 0.4105263158f, 0.4210526316f, 0.4315789474f,
0.4421052632f, 0.4526315789f, 0.4631578947f, 0.4736842105f, 0.4842105263f, 0.4947368421f,
0.5052631579f, 0.5157894737f, 0.5263157895f, 0.5368421053f, 0.5473684211f, 0.5578947368f,
0.5684210526f, 0.5789473684f, 0.5894736842f, 0.6f, 0.6105263158f, 0.6210526316f,
0.6315789474f, 0.6421052632f, 0.6526315789f, 0.6631578947f, 0.6736842105f, 0.6842105263f,
0.6947368421f, 0.7052631579f, 0.7157894737f, 0.7263157895f, 0.7368421053f, 0.7473684211f,
0.7578947368f, 0.7684210526f, 0.7789473684f, 0.7894736842f, 0.8f, 0.8105263158f,
0.8210526316f, 0.8315789474f, 0.8421052632f, 0.8526315789f, 0.8631578947f, 0.8736842105f,
0.8842105263f, 0.8947368421f, 0.9052631579f, 0.9157894737f, 0.9263157895f, 0.9368421053f,
0.9473684211f, 0.9578947368f, 0.9684210526f, 0.9789473684f, 0.9894736842f, 1.f
};
return reference;
}
/* Total number of reference components. */
glw::GLuint Reference::ReferenceDataCount()
{
return s_reference_count;
}
/* Total number of reference size in basic machine units. */
template <typename T>
glw::GLuint Reference::ReferenceDataSize()
{
return Reference::ReferenceDataCount() * sizeof(T);
}
/** @brief Comparison function (for floats).
*
* @param [in] a First element.
* @param [in] b Second element.
*
* @return Comparison result.
*/
template <>
bool Reference::Compare<glw::GLfloat>(const glw::GLfloat a, const glw::GLfloat b)
{
if (de::abs(a - b) < 1.f / 256.f)
{
return true;
}
return false;
}
/** @brief Comparison function (integer).
*
* @param [in] a First element.
* @param [in] b Second element.
*
* @return Comparison result.
*/
template <typename T>
bool Reference::Compare(const T a, const T b)
{
return a == b;
}
/******************************** Buffer Test Implementation ********************************/
/** @brief Buffer Test constructor.
*
* @tparam T Type.
* @tparam S Size.
* @tparam N Is normalized.
*
* @param [in] context OpenGL context.
* @param [in] name Name of the test.
*/
template <typename T, glw::GLint S, bool N>
BufferTest<T, S, N>::BufferTest(deqp::Context& context, const char* name)
: deqp::TestCase(context, name, "Texture Buffer Objects Test")
, m_fbo(0)
, m_rbo(0)
, m_po(0)
, m_to(0)
, m_bo(0)
, m_vao(0)
{
/* Intentionally left blank. */
}
/** @brief Count of reference data to be teted.
*
* @return Count.
*/
template <typename T, glw::GLint S, bool N>
glw::GLuint BufferTest<T, S, N>::TestReferenceDataCount()
{
return s_fbo_size_x * S;
}
/** @brief Size of reference data to be teted..
*
* @return Size.
*/
template <typename T, glw::GLint S, bool N>
glw::GLuint BufferTest<T, S, N>::TestReferenceDataSize()
{
return static_cast<glw::GLint>(TestReferenceDataCount() * sizeof(T));
}
/** @brief Create buffer textuew.
*
* @param [in] use_range_version Uses TextureBufferRange instead TextureBuffer.
*
* @return True if succeded, false otherwise.
*/
template <typename T, glw::GLint S, bool N>
bool BufferTest<T, S, N>::CreateBufferTexture(bool use_range_version)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Objects creation. */
gl.genTextures(1, &m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed");
gl.bindTexture(GL_TEXTURE_BUFFER, m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed");
gl.genBuffers(1, &m_bo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers has failed");
gl.bindBuffer(GL_TEXTURE_BUFFER, m_bo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer has failed");
/* Data setup. */
if (use_range_version)
{
glw::GLint alignment = 1;
gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &alignment);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
const glw::GLuint b_offset = alignment;
const glw::GLuint b_size = TestReferenceDataSize() + b_offset;
gl.bufferData(GL_TEXTURE_BUFFER, b_size, NULL, GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData has failed");
gl.bufferSubData(GL_TEXTURE_BUFFER, b_offset, TestReferenceDataSize(), ReferenceData<T, N>());
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubdata has failed");
gl.textureBufferRange(m_to, InternalFormat<T, S, N>(), m_bo, b_offset, TestReferenceDataSize());
}
else
{
gl.bufferData(GL_TEXTURE_BUFFER, TestReferenceDataSize(), ReferenceData<T, N>(), GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData has failed");
gl.textureBuffer(m_to, InternalFormat<T, S, N>(), m_bo);
}
/* Error checking. */
glw::GLenum error;
if (GL_NO_ERROR != (error = gl.getError()))
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << (use_range_version ? ("glTextureBufferRange") : ("glTextureBuffer"))
<< " unexpectedly generated error " << glu::getErrorStr(error) << " during test of internal format "
<< glu::getTextureFormatStr(InternalFormat<T, S, N>()) << "." << tcu::TestLog::EndMessage;
CleanBufferTexture();
return false;
}
return true;
}
/** @brief Function prepares framebuffer with internal format color attachment.
* Viewport is set up. Content of the framebuffer is cleared.
*
* @note The function may throw if unexpected error has occured.
*
* @return if the framebuffer returned is supported
*/
template <typename T, glw::GLint S, bool N>
bool BufferTest<T, S, N>::PrepareFramebuffer(const glw::GLenum internal_format)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Prepare framebuffer. */
gl.genFramebuffers(1, &m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
gl.genRenderbuffers(1, &m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
gl.renderbufferStorage(GL_RENDERBUFFER, internal_format, s_fbo_size_x, s_fbo_size_y);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_UNSUPPORTED)
throw tcu::NotSupportedError("unsupported framebuffer configuration");
else
throw 0;
}
gl.viewport(0, 0, s_fbo_size_x, s_fbo_size_y);
GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
/* Clear framebuffer's content. */
gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
return true;
}
/** @brief Create program.
*
* @param [in] variable_declaration Choose variable declaration of the fragment shader.
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::PrepareProgram(const glw::GLchar* variable_declaration)
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
struct Shader
{
glw::GLchar const* source[3];
glw::GLsizei const count;
glw::GLenum const type;
glw::GLuint id;
} shader[] = {
{ { s_vertex_shader, NULL, NULL }, 1, GL_VERTEX_SHADER, 0 },
{ { s_fragment_shader_head, variable_declaration, s_fragment_shader_tail }, 3, GL_FRAGMENT_SHADER, 0 }
};
glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
try
{
/* Create program. */
m_po = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
/* Shader compilation. */
for (glw::GLuint i = 0; i < shader_count; ++i)
{
{
shader[i].id = gl.createShader(shader[i].type);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
gl.attachShader(m_po, shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
gl.shaderSource(shader[i].id, shader[i].count, shader[i].source, NULL);
GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
gl.compileShader(shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
glw::GLint status = GL_FALSE;
gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
if (GL_FALSE == status)
{
glw::GLint log_size = 0;
gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
glw::GLchar* log_text = new glw::GLchar[log_size];
gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Shader compilation has failed.\n"
<< "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
<< "Shader compilation error log:\n"
<< log_text << "\n"
<< "Shader source code:\n"
<< shader[i].source[0] << (shader[i].source[1] ? shader[i].source[1] : "")
<< (shader[i].source[2] ? shader[i].source[2] : "") << "\n"
<< tcu::TestLog::EndMessage;
delete[] log_text;
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
throw 0;
}
}
}
/* Link. */
gl.linkProgram(m_po);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
glw::GLint status = GL_FALSE;
gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
if (GL_TRUE == status)
{
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (shader[i].id)
{
gl.detachShader(m_po, shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
}
}
}
else
{
glw::GLint log_size = 0;
gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
glw::GLchar* log_text = new glw::GLchar[log_size];
gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
<< log_text << "\n"
<< tcu::TestLog::EndMessage;
delete[] log_text;
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
throw 0;
}
}
catch (...)
{
if (m_po)
{
gl.deleteProgram(m_po);
m_po = 0;
}
}
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (0 != shader[i].id)
{
gl.deleteShader(shader[i].id);
shader[i].id = 0;
}
}
if (0 == m_po)
{
throw 0;
}
}
/** @brief Create VAO.
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::PrepareVertexArray()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.genVertexArrays(1, &m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays has failed");
gl.bindVertexArray(m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray has failed");
}
/** @brief Test's draw function.
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::Draw()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.useProgram(m_po);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram has failed");
gl.activeTexture(GL_TEXTURE0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture has failed");
gl.bindTextureUnit(0, m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture has failed");
gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays has failed");
}
/** @brief Compre results with the reference.
*
* @return True if equal, false otherwise.
*/
template <typename T, glw::GLint S, bool N>
bool BufferTest<T, S, N>::Check()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Fetching data. */
std::vector<T> result(TestReferenceDataCount());
gl.pixelStorei(GL_UNPACK_ALIGNMENT, sizeof(T));
GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei has failed");
gl.pixelStorei(GL_PACK_ALIGNMENT, sizeof(T));
GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei has failed");
gl.readnPixels(0, 0, s_fbo_size_x, s_fbo_size_y, Format<S, N>(), Type<T>(), TestReferenceDataSize(),
(glw::GLvoid*)(&result[0]));
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
/* Comparison. */
bool is_ok = true;
for (glw::GLuint i = 0; i < TestReferenceDataCount(); ++i)
{
if (!Compare<T>(result[i], ReferenceData<T, N>()[i]))
{
is_ok = false;
break;
}
}
return is_ok;
}
/** @brief Test function.
*
* @param [in] use_range_version Uses TextureBufferRange instead TextureBuffer.
*
* @return True if succeeded, false otherwise.
*/
template <typename T, glw::GLint S, bool N>
bool BufferTest<T, S, N>::Test(bool use_range_version)
{
/* Setup. */
if (!PrepareFramebuffer(InternalFormat<T, S, N>()))
{
/**
* If the framebuffer it not supported, means that the
* tested combination is unsupported for this driver,
* but allowed to be unsupported by OpenGL spec, so we
* just skip.
*/
CleanFramebuffer();
CleanErrors();
return true;
}
if (!CreateBufferTexture(use_range_version))
{
CleanFramebuffer();
CleanErrors();
return false;
}
/* Action. */
Draw();
/* Compare results with reference. */
bool result = Check();
/* Cleanup. */
CleanFramebuffer();
CleanBufferTexture();
CleanErrors();
/* Pass result. */
return result;
}
/** @brief Clean GL objects
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::CleanBufferTexture()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Texture. */
if (m_to)
{
gl.deleteTextures(1, &m_to);
m_to = 0;
}
/* Texture buffer. */
if (m_bo)
{
gl.deleteBuffers(1, &m_bo);
m_bo = 0;
}
}
/** @brief Clean GL objects
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::CleanFramebuffer()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Framebuffer. */
if (m_fbo)
{
gl.deleteFramebuffers(1, &m_fbo);
m_fbo = 0;
}
/* Renderbuffer. */
if (m_rbo)
{
gl.deleteRenderbuffers(1, &m_rbo);
m_rbo = 0;
}
}
/** @brief Clean GL objects
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::CleanProgram()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Program. */
if (m_po)
{
gl.useProgram(0);
gl.deleteProgram(m_po);
m_po = 0;
}
}
/** @brief Clean errors.
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::CleanErrors()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Query all errors until GL_NO_ERROR occure. */
while (GL_NO_ERROR != gl.getError())
;
}
/** @brief Clean GL objects
*/
template <typename T, glw::GLint S, bool N>
void BufferTest<T, S, N>::CleanVertexArray()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
if (m_vao)
{
gl.bindVertexArray(0);
gl.deleteVertexArrays(1, &m_vao);
m_vao = 0;
}
}
/** @brief Iterate Buffer Test cases.
*
* @return Iteration result.
*/
template <typename T, glw::GLint S, bool N>
tcu::TestNode::IterateResult BufferTest<T, S, N>::iterate()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get context setup. */
bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
return STOP;
}
/* Running tests. */
bool is_ok = true;
bool is_error = false;
try
{
PrepareVertexArray();
PrepareProgram(FragmentShaderDeclaration());
for (glw::GLuint i = 0; i < 2; ++i)
{
bool use_range = (i == 1);
is_ok &= Test(use_range);
CleanErrors();
}
CleanProgram();
}
catch (tcu::NotSupportedError& e)
{
throw e;
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
CleanBufferTexture();
CleanFramebuffer();
CleanProgram();
CleanErrors();
CleanVertexArray();
/* Errors clean up. */
while (gl.getError())
;
/* Result's setup. */
if (is_ok)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (is_error)
{
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
/* Vertex shader source code. */
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_vertex_shader = "#version 450\n"
"\n"
"void main()\n"
"{\n"
" switch(gl_VertexID)\n"
" {\n"
" case 0:\n"
" gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
" break;\n"
" case 1:\n"
" gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
" break;\n"
" case 2:\n"
" gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
" break;\n"
" case 3:\n"
" gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
" break;\n"
" }\n"
"}\n";
/* Fragment shader source program. */
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_head = "#version 450\n"
"\n"
"layout(pixel_center_integer) in vec4 gl_FragCoord;\n"
"\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_fdecl_lowp = "uniform samplerBuffer texture_input;\n"
"out vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_idecl_lowp = "uniform isamplerBuffer texture_input;\n"
"out ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_udecl_lowp = "uniform usamplerBuffer texture_input;\n"
"out uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_fdecl_mediump = "uniform samplerBuffer texture_input;\n"
"out vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_idecl_mediump = "uniform isamplerBuffer texture_input;\n"
"out ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_udecl_mediump = "uniform usamplerBuffer texture_input;\n"
"out uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_fdecl_highp = "uniform samplerBuffer texture_input;\n"
"out vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_idecl_highp = "uniform isamplerBuffer texture_input;\n"
"out ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_udecl_highp = "uniform usamplerBuffer texture_input;\n"
"out uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N>
const glw::GLchar* BufferTest<T, S, N>::s_fragment_shader_tail =
"\n"
"void main()\n"
"{\n"
" texture_output = texelFetch(texture_input, int(gl_FragCoord.x));\n"
"}\n";
template class BufferTest<glw::GLbyte, 1, false>;
template class BufferTest<glw::GLbyte, 2, false>;
template class BufferTest<glw::GLbyte, 4, false>;
template class BufferTest<glw::GLubyte, 1, false>;
template class BufferTest<glw::GLubyte, 2, false>;
template class BufferTest<glw::GLubyte, 4, false>;
template class BufferTest<glw::GLubyte, 1, true>;
template class BufferTest<glw::GLubyte, 2, true>;
template class BufferTest<glw::GLubyte, 4, true>;
template class BufferTest<glw::GLshort, 1, false>;
template class BufferTest<glw::GLshort, 2, false>;
template class BufferTest<glw::GLshort, 4, false>;
template class BufferTest<glw::GLushort, 1, false>;
template class BufferTest<glw::GLushort, 2, false>;
template class BufferTest<glw::GLushort, 4, false>;
template class BufferTest<glw::GLushort, 1, true>;
template class BufferTest<glw::GLushort, 2, true>;
template class BufferTest<glw::GLushort, 4, true>;
template class BufferTest<glw::GLint, 1, false>;
template class BufferTest<glw::GLint, 2, false>;
template class BufferTest<glw::GLint, 3, false>;
template class BufferTest<glw::GLint, 4, false>;
template class BufferTest<glw::GLuint, 1, false>;
template class BufferTest<glw::GLuint, 2, false>;
template class BufferTest<glw::GLuint, 3, false>;
template class BufferTest<glw::GLuint, 4, false>;
template class BufferTest<glw::GLfloat, 1, true>;
template class BufferTest<glw::GLfloat, 2, true>;
template class BufferTest<glw::GLfloat, 3, true>;
template class BufferTest<glw::GLfloat, 4, true>;
/******************************** Storage and SubImage Test Implementation ********************************/
/** @brief Storage Test constructor.
*
* @tparam T Type.
* @tparam S Size.
* @tparam N Is normalized.
* @tparam D Texture dimension.
* @tparam I Choose between SubImage and Storage tests.
*
* @param [in] context OpenGL context.
* @param [in] name Name of the test.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
StorageAndSubImageTest<T, S, N, D, I>::StorageAndSubImageTest(deqp::Context& context, const char* name)
: deqp::TestCase(context, name, "Texture Storage and SubImage Test")
, m_fbo(0)
, m_rbo(0)
, m_po(0)
, m_to(0)
, m_vao(0)
{
/* Intentionally left blank. */
}
/** @brief Count of reference data to be teted.
*
* @return Count.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
glw::GLuint StorageAndSubImageTest<T, S, N, D, I>::TestReferenceDataCount()
{
return 2 /* 1D */ * ((D > 1) ? 3 : 1) /* 2D */ * ((D > 2) ? 4 : 1) /* 3D */ * S /* components */;
}
/** @brief Size of reference data to be teted.
*
* @tparam T Type.
* @tparam S Size (# of components).
* @tparam D Texture dimenisons.
*
* @return Size.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
glw::GLuint StorageAndSubImageTest<T, S, N, D, I>::TestReferenceDataSize()
{
return static_cast<glw::GLint>(TestReferenceDataCount() * sizeof(T));
}
/** @brief Height, width or depth of reference data to be teted.
*
* @return Height, width or depth.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
glw::GLuint StorageAndSubImageTest<T, S, N, D, I>::TestReferenceDataHeight()
{
switch (D)
{
case 2:
case 3:
return 3;
default:
return 1;
}
}
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
glw::GLuint StorageAndSubImageTest<T, S, N, D, I>::TestReferenceDataDepth()
{
switch (D)
{
case 3:
return 4;
default:
return 1;
}
}
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
glw::GLuint StorageAndSubImageTest<T, S, N, D, I>::TestReferenceDataWidth()
{
return 2;
}
/** @brief Fragment shader declaration selector.
*
* @return Frgment shader source code part.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::FragmentShaderDeclaration()
{
if (typeid(T) == typeid(glw::GLbyte))
{
switch (D)
{
case 1:
return s_fragment_shader_1D_idecl_lowp;
case 2:
return s_fragment_shader_2D_idecl_lowp;
case 3:
return s_fragment_shader_3D_idecl_lowp;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
if (typeid(T) == typeid(glw::GLubyte))
{
if (N)
{
switch (D)
{
case 1:
return s_fragment_shader_1D_fdecl_lowp;
case 2:
return s_fragment_shader_2D_fdecl_lowp;
case 3:
return s_fragment_shader_3D_fdecl_lowp;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
else
{
switch (D)
{
case 1:
return s_fragment_shader_1D_udecl_lowp;
case 2:
return s_fragment_shader_2D_udecl_lowp;
case 3:
return s_fragment_shader_3D_udecl_lowp;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
}
if (typeid(T) == typeid(glw::GLshort))
{
switch (D)
{
case 1:
return s_fragment_shader_1D_idecl_mediump;
case 2:
return s_fragment_shader_2D_idecl_mediump;
case 3:
return s_fragment_shader_3D_idecl_mediump;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
if (typeid(T) == typeid(glw::GLushort))
{
if (N)
{
switch (D)
{
case 1:
return s_fragment_shader_1D_fdecl_mediump;
case 2:
return s_fragment_shader_2D_fdecl_mediump;
case 3:
return s_fragment_shader_3D_fdecl_mediump;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
else
{
switch (D)
{
case 1:
return s_fragment_shader_1D_udecl_mediump;
case 2:
return s_fragment_shader_2D_udecl_mediump;
case 3:
return s_fragment_shader_3D_udecl_mediump;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
}
if (typeid(T) == typeid(glw::GLint))
{
switch (D)
{
case 1:
return s_fragment_shader_1D_idecl_highp;
case 2:
return s_fragment_shader_2D_idecl_highp;
case 3:
return s_fragment_shader_3D_idecl_highp;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
if (typeid(T) == typeid(glw::GLuint))
{
switch (D)
{
case 1:
return s_fragment_shader_1D_udecl_highp;
case 2:
return s_fragment_shader_2D_udecl_highp;
case 3:
return s_fragment_shader_3D_udecl_highp;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
switch (D)
{
case 1:
return s_fragment_shader_1D_fdecl_highp;
case 2:
return s_fragment_shader_2D_fdecl_highp;
case 3:
return s_fragment_shader_3D_fdecl_highp;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
/** @brief Fragment shader tail selector.
*
* @tparam D Texture dimenisons.
*
* @return Frgment shader source code part.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::FragmentShaderTail()
{
switch (D)
{
case 1:
return s_fragment_shader_1D_tail;
case 2:
return s_fragment_shader_2D_tail;
case 3:
return s_fragment_shader_3D_tail;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
/** @brief Texture target selector.
*
* @tparam D Texture dimenisons.
*
* @return Texture target.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
glw::GLenum StorageAndSubImageTest<T, S, N, D, I>::TextureTarget()
{
switch (D)
{
case 1:
return GL_TEXTURE_1D;
case 2:
return GL_TEXTURE_2D;
case 3:
return GL_TEXTURE_3D;
default:
DE_FATAL("invalid texture dimension");
return DE_NULL;
}
}
/** @brief TextureStorage* wrapper.
*
* @return true if succeed (in legacy always or throw), false otherwise.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
bool StorageAndSubImageTest<T, S, N, D, I>::TextureStorage(glw::GLenum target, glw::GLuint texture, glw::GLsizei levels,
glw::GLenum internalformat, glw::GLsizei width,
glw::GLsizei height, glw::GLsizei depth)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
if (I)
{
switch (D)
{
case 1:
gl.texStorage1D(target, levels, internalformat, width);
break;
case 2:
gl.texStorage2D(target, levels, internalformat, width, height);
break;
case 3:
gl.texStorage3D(target, levels, internalformat, width, height, depth);
break;
default:
DE_FATAL("invalid texture dimension");
}
/* TextureSubImage* (not TextureStorage*) is tested */
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage*() has failed");
return true;
}
else
{
switch (D)
{
case 1:
gl.textureStorage1D(texture, levels, internalformat, width);
break;
case 2:
gl.textureStorage2D(texture, levels, internalformat, width, height);
break;
case 3:
gl.textureStorage3D(texture, levels, internalformat, width, height, depth);
break;
default:
DE_FATAL("invalid texture dimension");
}
glw::GLenum error;
if (GL_NO_ERROR != (error = gl.getError()))
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glTextureStorage" << D << "D unexpectedly generated error " << glu::getErrorStr(error)
<< " during test with levels " << levels << ", internal format " << internalformat
<< " width=" << width << " height=" << height << " depth=" << depth
<< "." << tcu::TestLog::EndMessage;
CleanTexture();
CleanErrors();
return false;
}
return true;
}
}
/** @brief TextureSubImage* wrapper.
*
* @return true if suuceed (in legacy always or throw), false otherwise.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
bool StorageAndSubImageTest<T, S, N, D, I>::TextureSubImage(glw::GLenum target, glw::GLuint texture, glw::GLint level,
glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth,
glw::GLenum format, glw::GLenum type, const glw::GLvoid* data)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
if (I)
{
switch (D)
{
case 1:
gl.textureSubImage1D(texture, level, 0, width, format, type, data);
break;
case 2:
gl.textureSubImage2D(texture, level, 0, 0, width, height, format, type, data);
break;
case 3:
gl.textureSubImage3D(texture, level, 0, 0, 0, width, height, depth, format, type, data);
break;
default:
DE_FATAL("invalid texture dimension");
}
glw::GLenum error;
if (GL_NO_ERROR != (error = gl.getError()))
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glTextureSubImage" << D << "D unexpectedly generated error " << glu::getErrorStr(error)
<< " during test with level " << level << ", width=" << width << ", height=" << height << ", depth=" << depth
<< " format " << glu::getTextureFormatStr(format) << " and type " << glu::getTypeStr(type) << "."
<< tcu::TestLog::EndMessage;
CleanTexture();
CleanErrors();
return false;
}
return true;
}
else
{
switch (D)
{
case 1:
gl.texSubImage1D(target, level, 0, width, format, type, data);
break;
case 2:
gl.texSubImage2D(target, level, 0, 0, width, height, format, type, data);
break;
case 3:
gl.texSubImage3D(target, level, 0, 0, 0, width, height, depth, format, type, data);
break;
default:
DE_FATAL("invalid texture dimension");
}
/* TextureStorage* (not TextureSubImage) is tested */
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage*() has failed");
return true;
}
}
/** @brief Create texture.
*
* @tparam T Type.
* @tparam S Size (# of components).
* @tparam N Is normalized.
* @tparam D Dimmensions.
* @tparam I Test SubImage or Storage.
*
* @return True if succeded, false otherwise.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
bool StorageAndSubImageTest<T, S, N, D, I>::CreateTexture()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Objects creation. */
gl.genTextures(1, &m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed");
gl.bindTexture(TextureTarget(), m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed");
/* Storage creation. */
if (TextureStorage(TextureTarget(), m_to, 1, InternalFormat<T, S, N>(), TestReferenceDataWidth(),
TestReferenceDataHeight(), TestReferenceDataDepth()))
{
/* Data setup. */
if (TextureSubImage(TextureTarget(), m_to, 0, TestReferenceDataWidth(), TestReferenceDataHeight(), TestReferenceDataDepth(),
Format<S, N>(), Type<T>(), ReferenceData<T, N>()))
{
glTexParameteri(TextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(TextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return true;
}
}
CleanTexture();
return false;
}
/** @brief Compre results with the reference.
*
* @return True if equal, false otherwise.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
bool StorageAndSubImageTest<T, S, N, D, I>::Check()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Fetching data. */
std::vector<T> result(TestReferenceDataCount());
glw::GLuint fbo_size_x = 0;
switch (D)
{
case 1:
fbo_size_x = 2;
break;
case 2:
fbo_size_x = 2 * 3;
break;
case 3:
fbo_size_x = 2 * 3 * 4;
break;
default:
throw 0;
}
gl.readnPixels(0, 0, fbo_size_x, 1, Format<S, N>(), Type<T>(), TestReferenceDataSize(),
(glw::GLvoid*)(&result[0]));
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
/* Comparison. */
for (glw::GLuint i = 0; i < TestReferenceDataCount(); ++i)
{
if (!Compare<T>(result[i], ReferenceData<T, N>()[i]))
{
return false;
}
}
return true;
}
/** @brief Test case function.
*
* @return True if test succeeded, false otherwise.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
bool StorageAndSubImageTest<T, S, N, D, I>::Test()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.pixelStorei(GL_UNPACK_ALIGNMENT, sizeof(T));
GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei has failed");
gl.pixelStorei(GL_PACK_ALIGNMENT, sizeof(T));
GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei has failed");
/* Setup. */
PrepareFramebuffer(InternalFormat<T, S, N>());
if (!CreateTexture())
{
return false;
}
/* Action. */
Draw();
/* Compare results with reference. */
bool result = Check();
/* Cleanup. */
CleanTexture();
CleanFramebuffer();
CleanErrors();
/* Pass result. */
return result;
}
/** @brief Function prepares framebuffer with internal format color attachment.
* Viewport is set up. Content of the framebuffer is cleared.
*
* @note The function may throw if unexpected error has occured.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::PrepareFramebuffer(const glw::GLenum internal_format)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Prepare framebuffer. */
gl.genFramebuffers(1, &m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
gl.genRenderbuffers(1, &m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
glw::GLuint fbo_size_x = 0;
switch (D)
{
case 1:
fbo_size_x = 2;
break;
case 2:
fbo_size_x = 2 * 3;
break;
case 3:
fbo_size_x = 2 * 3 * 4;
break;
default:
throw 0;
}
gl.renderbufferStorage(GL_RENDERBUFFER, internal_format, fbo_size_x, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_UNSUPPORTED)
throw tcu::NotSupportedError("unsupported framebuffer configuration");
else
throw 0;
}
gl.viewport(0, 0, fbo_size_x, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
/* Clear framebuffer's content. */
gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
}
/** @brief Prepare program
*
* @param [in] variable_declaration Variables declaration part of fragment shader source code.
* @param [in] tail Tail part of fragment shader source code.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::PrepareProgram(const glw::GLchar* variable_declaration, const glw::GLchar* tail)
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
struct Shader
{
glw::GLchar const* source[3];
glw::GLsizei const count;
glw::GLenum const type;
glw::GLuint id;
} shader[] = { { { s_vertex_shader, NULL, NULL }, 1, GL_VERTEX_SHADER, 0 },
{ { s_fragment_shader_head, variable_declaration, tail }, 3, GL_FRAGMENT_SHADER, 0 } };
glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
try
{
/* Create program. */
m_po = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
/* Shader compilation. */
for (glw::GLuint i = 0; i < shader_count; ++i)
{
{
shader[i].id = gl.createShader(shader[i].type);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
gl.attachShader(m_po, shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
gl.shaderSource(shader[i].id, shader[i].count, shader[i].source, NULL);
GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
gl.compileShader(shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
glw::GLint status = GL_FALSE;
gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
if (GL_FALSE == status)
{
glw::GLint log_size = 0;
gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
glw::GLchar* log_text = new glw::GLchar[log_size];
gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Shader compilation has failed.\n"
<< "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
<< "Shader compilation error log:\n"
<< log_text << "\n"
<< "Shader source code:\n"
<< shader[i].source[0] << (shader[i].source[1] ? shader[i].source[1] : "")
<< (shader[i].source[2] ? shader[i].source[2] : "") << "\n"
<< tcu::TestLog::EndMessage;
delete[] log_text;
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
throw 0;
}
}
}
/* Link. */
gl.linkProgram(m_po);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
glw::GLint status = GL_FALSE;
gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
if (GL_TRUE == status)
{
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (shader[i].id)
{
gl.detachShader(m_po, shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
}
}
}
else
{
glw::GLint log_size = 0;
gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
glw::GLchar* log_text = new glw::GLchar[log_size];
gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
<< log_text << "\n"
<< tcu::TestLog::EndMessage;
delete[] log_text;
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
throw 0;
}
}
catch (...)
{
if (m_po)
{
gl.deleteProgram(m_po);
m_po = 0;
}
}
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (0 != shader[i].id)
{
gl.deleteShader(shader[i].id);
shader[i].id = 0;
}
}
if (0 == m_po)
{
throw 0;
}
}
/** @brief Prepare VAO.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::PrepareVertexArray()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.genVertexArrays(1, &m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays has failed");
gl.bindVertexArray(m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray has failed");
}
/** @brief Test's draw call.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::Draw()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.useProgram(m_po);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram has failed");
gl.activeTexture(GL_TEXTURE0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture has failed");
gl.bindTextureUnit(0, m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture has failed");
gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays has failed");
}
/** @brief Clean GL objects, test variables and GL errors.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::CleanTexture()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Texture. */
if (m_to)
{
gl.deleteTextures(1, &m_to);
m_to = 0;
}
}
/** @brief Clean GL objects, test variables and GL errors.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::CleanFramebuffer()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Framebuffer. */
if (m_fbo)
{
gl.deleteFramebuffers(1, &m_fbo);
m_fbo = 0;
}
/* Renderbuffer. */
if (m_rbo)
{
gl.deleteRenderbuffers(1, &m_rbo);
m_rbo = 0;
}
}
/** @brief Clean GL objects, test variables and GL errors.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::CleanProgram()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Program. */
if (m_po)
{
gl.useProgram(0);
gl.deleteProgram(m_po);
m_po = 0;
}
}
/** @brief Clean GL objects, test variables and GL errors.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::CleanErrors()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Query all errors until GL_NO_ERROR occure. */
while (GL_NO_ERROR != gl.getError())
;
}
/** @brief Clean GL objects, test variables and GL errors.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
void StorageAndSubImageTest<T, S, N, D, I>::CleanVertexArray()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
if (m_vao)
{
gl.bindVertexArray(0);
gl.deleteVertexArrays(1, &m_vao);
m_vao = 0;
}
}
/** @brief Iterate Storage Test cases.
*
* @return Iteration result.
*/
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
tcu::TestNode::IterateResult StorageAndSubImageTest<T, S, N, D, I>::iterate()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get context setup. */
bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
return STOP;
}
/* Running tests. */
bool is_ok = true;
bool is_error = false;
try
{
PrepareVertexArray();
PrepareProgram(FragmentShaderDeclaration(), FragmentShaderTail());
is_ok = Test();
}
catch (tcu::NotSupportedError& e)
{
throw e;
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
CleanTexture();
CleanFramebuffer();
CleanProgram();
CleanErrors();
CleanVertexArray();
/* Errors clean up. */
while (gl.getError())
;
/* Result's setup. */
if (is_ok)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (is_error)
{
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
/* Vertex shader source code. */
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_vertex_shader =
"#version 450\n"
"\n"
"void main()\n"
"{\n"
" switch(gl_VertexID)\n"
" {\n"
" case 0:\n"
" gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
" break;\n"
" case 1:\n"
" gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
" break;\n"
" case 2:\n"
" gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
" break;\n"
" case 3:\n"
" gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
" break;\n"
" }\n"
"}\n";
/* Fragment shader source program. */
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_head =
"#version 450\n"
"\n"
"layout(pixel_center_integer) in vec4 gl_FragCoord;\n"
"\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_fdecl_lowp =
"uniform sampler1D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_idecl_lowp =
"uniform isampler1D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_udecl_lowp =
"uniform usampler1D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_fdecl_mediump =
"uniform sampler1D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_idecl_mediump =
"uniform isampler1D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_udecl_mediump =
"uniform usampler1D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_fdecl_highp =
"uniform sampler1D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_idecl_highp =
"uniform isampler1D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_udecl_highp =
"uniform usampler1D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_fdecl_lowp =
"uniform sampler2D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_idecl_lowp =
"uniform isampler2D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_udecl_lowp =
"uniform usampler2D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_fdecl_mediump =
"uniform sampler2D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_idecl_mediump =
"uniform isampler2D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_udecl_mediump =
"uniform usampler2D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_fdecl_highp =
"uniform sampler2D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_idecl_highp =
"uniform isampler2D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_udecl_highp =
"uniform usampler2D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_fdecl_lowp =
"uniform sampler3D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_idecl_lowp =
"uniform isampler3D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_udecl_lowp =
"uniform usampler3D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_fdecl_mediump =
"uniform sampler3D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_idecl_mediump =
"uniform isampler3D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_udecl_mediump =
"uniform usampler3D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_fdecl_highp =
"uniform sampler3D texture_input;\nout vec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_idecl_highp =
"uniform isampler3D texture_input;\nout ivec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_udecl_highp =
"uniform usampler3D texture_input;\nout uvec4 texture_output;\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_1D_tail =
"\n"
"void main()\n"
"{\n"
" texture_output = texelFetch(texture_input, int(gl_FragCoord.x), 0);\n"
"}\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_2D_tail =
"\n"
"void main()\n"
"{\n"
" texture_output = texelFetch(texture_input, ivec2(int(gl_FragCoord.x) % 2, int(floor(gl_FragCoord.x / 2))), "
"0);\n"
"}\n";
template <typename T, glw::GLint S, bool N, glw::GLuint D, bool I>
const glw::GLchar* StorageAndSubImageTest<T, S, N, D, I>::s_fragment_shader_3D_tail =
"\n"
"void main()\n"
"{\n"
" texture_output = texelFetch(texture_input, ivec3(int(gl_FragCoord.x) % 2, int(floor(gl_FragCoord.x / 2)) % 3, "
"int(floor(gl_FragCoord.x / 2 / 3))), 0);\n"
"}\n";
template class StorageAndSubImageTest<glw::GLbyte, 1, false, 1, false>;
template class StorageAndSubImageTest<glw::GLbyte, 2, false, 1, false>;
template class StorageAndSubImageTest<glw::GLbyte, 4, false, 1, false>;
template class StorageAndSubImageTest<glw::GLbyte, 1, false, 2, false>;
template class StorageAndSubImageTest<glw::GLbyte, 2, false, 2, false>;
template class StorageAndSubImageTest<glw::GLbyte, 4, false, 2, false>;
template class StorageAndSubImageTest<glw::GLbyte, 1, false, 3, false>;
template class StorageAndSubImageTest<glw::GLbyte, 2, false, 3, false>;
template class StorageAndSubImageTest<glw::GLbyte, 4, false, 3, false>;
template class StorageAndSubImageTest<glw::GLubyte, 1, false, 1, false>;
template class StorageAndSubImageTest<glw::GLubyte, 2, false, 1, false>;
template class StorageAndSubImageTest<glw::GLubyte, 4, false, 1, false>;
template class StorageAndSubImageTest<glw::GLubyte, 1, false, 2, false>;
template class StorageAndSubImageTest<glw::GLubyte, 2, false, 2, false>;
template class StorageAndSubImageTest<glw::GLubyte, 4, false, 2, false>;
template class StorageAndSubImageTest<glw::GLubyte, 1, false, 3, false>;
template class StorageAndSubImageTest<glw::GLubyte, 2, false, 3, false>;
template class StorageAndSubImageTest<glw::GLubyte, 4, false, 3, false>;
template class StorageAndSubImageTest<glw::GLubyte, 1, true, 1, false>;
template class StorageAndSubImageTest<glw::GLubyte, 2, true, 1, false>;
template class StorageAndSubImageTest<glw::GLubyte, 4, true, 1, false>;
template class StorageAndSubImageTest<glw::GLubyte, 1, true, 2, false>;
template class StorageAndSubImageTest<glw::GLubyte, 2, true, 2, false>;
template class StorageAndSubImageTest<glw::GLubyte, 4, true, 2, false>;
template class StorageAndSubImageTest<glw::GLubyte, 1, true, 3, false>;
template class StorageAndSubImageTest<glw::GLubyte, 2, true, 3, false>;
template class StorageAndSubImageTest<glw::GLubyte, 4, true, 3, false>;
template class StorageAndSubImageTest<glw::GLshort, 1, false, 1, false>;
template class StorageAndSubImageTest<glw::GLshort, 2, false, 1, false>;
template class StorageAndSubImageTest<glw::GLshort, 4, false, 1, false>;
template class StorageAndSubImageTest<glw::GLshort, 1, false, 2, false>;
template class StorageAndSubImageTest<glw::GLshort, 2, false, 2, false>;
template class StorageAndSubImageTest<glw::GLshort, 4, false, 2, false>;
template class StorageAndSubImageTest<glw::GLshort, 1, false, 3, false>;
template class StorageAndSubImageTest<glw::GLshort, 2, false, 3, false>;
template class StorageAndSubImageTest<glw::GLshort, 4, false, 3, false>;
template class StorageAndSubImageTest<glw::GLushort, 1, false, 1, false>;
template class StorageAndSubImageTest<glw::GLushort, 2, false, 1, false>;
template class StorageAndSubImageTest<glw::GLushort, 4, false, 1, false>;
template class StorageAndSubImageTest<glw::GLushort, 1, false, 2, false>;
template class StorageAndSubImageTest<glw::GLushort, 2, false, 2, false>;
template class StorageAndSubImageTest<glw::GLushort, 4, false, 2, false>;
template class StorageAndSubImageTest<glw::GLushort, 1, false, 3, false>;
template class StorageAndSubImageTest<glw::GLushort, 2, false, 3, false>;
template class StorageAndSubImageTest<glw::GLushort, 4, false, 3, false>;
template class StorageAndSubImageTest<glw::GLushort, 1, true, 1, false>;
template class StorageAndSubImageTest<glw::GLushort, 2, true, 1, false>;
template class StorageAndSubImageTest<glw::GLushort, 4, true, 1, false>;
template class StorageAndSubImageTest<glw::GLushort, 1, true, 2, false>;
template class StorageAndSubImageTest<glw::GLushort, 2, true, 2, false>;
template class StorageAndSubImageTest<glw::GLushort, 4, true, 2, false>;
template class StorageAndSubImageTest<glw::GLushort, 1, true, 3, false>;
template class StorageAndSubImageTest<glw::GLushort, 2, true, 3, false>;
template class StorageAndSubImageTest<glw::GLushort, 4, true, 3, false>;
template class StorageAndSubImageTest<glw::GLint, 1, false, 1, false>;
template class StorageAndSubImageTest<glw::GLint, 2, false, 1, false>;
template class StorageAndSubImageTest<glw::GLint, 3, false, 1, false>;
template class StorageAndSubImageTest<glw::GLint, 4, false, 1, false>;
template class StorageAndSubImageTest<glw::GLint, 1, false, 2, false>;
template class StorageAndSubImageTest<glw::GLint, 2, false, 2, false>;
template class StorageAndSubImageTest<glw::GLint, 3, false, 2, false>;
template class StorageAndSubImageTest<glw::GLint, 4, false, 2, false>;
template class StorageAndSubImageTest<glw::GLint, 1, false, 3, false>;
template class StorageAndSubImageTest<glw::GLint, 2, false, 3, false>;
template class StorageAndSubImageTest<glw::GLint, 3, false, 3, false>;
template class StorageAndSubImageTest<glw::GLint, 4, false, 3, false>;
template class StorageAndSubImageTest<glw::GLuint, 1, false, 1, false>;
template class StorageAndSubImageTest<glw::GLuint, 2, false, 1, false>;
template class StorageAndSubImageTest<glw::GLuint, 3, false, 1, false>;
template class StorageAndSubImageTest<glw::GLuint, 4, false, 1, false>;
template class StorageAndSubImageTest<glw::GLuint, 1, false, 2, false>;
template class StorageAndSubImageTest<glw::GLuint, 2, false, 2, false>;
template class StorageAndSubImageTest<glw::GLuint, 3, false, 2, false>;
template class StorageAndSubImageTest<glw::GLuint, 4, false, 2, false>;
template class StorageAndSubImageTest<glw::GLuint, 1, false, 3, false>;
template class StorageAndSubImageTest<glw::GLuint, 2, false, 3, false>;
template class StorageAndSubImageTest<glw::GLuint, 3, false, 3, false>;
template class StorageAndSubImageTest<glw::GLuint, 4, false, 3, false>;
template class StorageAndSubImageTest<glw::GLfloat, 1, true, 1, false>;
template class StorageAndSubImageTest<glw::GLfloat, 2, true, 1, false>;
template class StorageAndSubImageTest<glw::GLfloat, 3, true, 1, false>;
template class StorageAndSubImageTest<glw::GLfloat, 4, true, 1, false>;
template class StorageAndSubImageTest<glw::GLfloat, 1, true, 2, false>;
template class StorageAndSubImageTest<glw::GLfloat, 2, true, 2, false>;
template class StorageAndSubImageTest<glw::GLfloat, 3, true, 2, false>;
template class StorageAndSubImageTest<glw::GLfloat, 4, true, 2, false>;
template class StorageAndSubImageTest<glw::GLfloat, 1, true, 3, false>;
template class StorageAndSubImageTest<glw::GLfloat, 2, true, 3, false>;
template class StorageAndSubImageTest<glw::GLfloat, 3, true, 3, false>;
template class StorageAndSubImageTest<glw::GLfloat, 4, true, 3, false>;
template class StorageAndSubImageTest<glw::GLbyte, 1, false, 1, true>;
template class StorageAndSubImageTest<glw::GLbyte, 2, false, 1, true>;
template class StorageAndSubImageTest<glw::GLbyte, 4, false, 1, true>;
template class StorageAndSubImageTest<glw::GLbyte, 1, false, 2, true>;
template class StorageAndSubImageTest<glw::GLbyte, 2, false, 2, true>;
template class StorageAndSubImageTest<glw::GLbyte, 4, false, 2, true>;
template class StorageAndSubImageTest<glw::GLbyte, 1, false, 3, true>;
template class StorageAndSubImageTest<glw::GLbyte, 2, false, 3, true>;
template class StorageAndSubImageTest<glw::GLbyte, 4, false, 3, true>;
template class StorageAndSubImageTest<glw::GLubyte, 1, false, 1, true>;
template class StorageAndSubImageTest<glw::GLubyte, 2, false, 1, true>;
template