blob: 7d1405e08a9a4f1a77fd18436f62b17e603de101 [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 gl4cDirectStateAccessBuffersTests.cpp
* \brief Conformance tests for the Direct State Access feature functionality (Buffer access part).
*/ /*-----------------------------------------------------------------------------------------------------------*/
/* 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 Buffers
{
/******************************** Creation Test Implementation ********************************/
/** @brief Creation Test constructor.
*
* @param [in] context OpenGL context.
*/
CreationTest::CreationTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_creation", "Buffer 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;
/* Buffers' objects */
static const glw::GLuint buffers_count = 2;
glw::GLuint buffers_legacy[buffers_count] = {};
glw::GLuint buffers_dsa[buffers_count] = {};
try
{
/* Check legacy state creation. */
gl.genBuffers(buffers_count, buffers_legacy);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
for (glw::GLuint i = 0; i < buffers_count; ++i)
{
if (gl.isBuffer(buffers_legacy[i]))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "GenBuffers has created default objects, but it should create only a names."
<< tcu::TestLog::EndMessage;
}
}
/* Check direct state creation. */
gl.createBuffers(buffers_count, buffers_dsa);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers have failed");
for (glw::GLuint i = 0; i < buffers_count; ++i)
{
if (!gl.isBuffer(buffers_dsa[i]))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message
<< "CreateBuffers has not created default objects."
<< tcu::TestLog::EndMessage;
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
for (glw::GLuint i = 0; i < buffers_count; ++i)
{
if (buffers_legacy[i])
{
gl.deleteBuffers(1, &buffers_legacy[i]);
buffers_legacy[i] = 0;
}
if (buffers_dsa[i])
{
gl.deleteBuffers(1, &buffers_dsa[i]);
buffers_dsa[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;
}
/******************************** Data Test Implementation ********************************/
/** @brief Data Test constructor.
*
* @param [in] context OpenGL context.
*/
DataTest::DataTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_data", "Buffer Objects Data Test")
, m_pNamedBufferData(DE_NULL)
, m_pNamedBufferSubData(DE_NULL)
, m_pNamedBufferStorage(DE_NULL)
, m_pCopyNamedBufferSubData(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Data Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult DataTest::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;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATA)gl.namedBufferSubData;
m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage;
m_pCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATA)gl.copyNamedBufferSubData;
try
{
if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pNamedBufferSubData) ||
(DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pCopyNamedBufferSubData))
{
throw 0;
}
/* BufferData tests */
static const glw::GLenum hints[] = { GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY,
GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY,
GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, GL_DYNAMIC_COPY };
static const glw::GLuint hints_count = sizeof(hints) / sizeof(hints[0]);
for (glw::GLuint i = 0; i < hints_count; ++i)
{
is_ok &= TestCase(&DataTest::UploadUsingNamedBufferData, hints[i]);
is_ok &= TestCase(&DataTest::UploadUsingNamedBufferSubData, hints[i]);
is_ok &= TestCase(&DataTest::UploadUsingCopyNamedBufferSubData, hints[i]);
}
/* BufferStorage Tests */
static const glw::GLenum bits[] = { GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT,
GL_MAP_READ_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT,
GL_MAP_READ_BIT | GL_CLIENT_STORAGE_BIT };
static const glw::GLuint bits_count = sizeof(bits) / sizeof(bits[0]);
for (glw::GLuint i = 0; i < bits_count; ++i)
{
is_ok &= TestCase(&DataTest::UploadUsingNamedBufferStorage, bits[i]);
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* 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;
}
/** @brief Data uploading test case function.
*
* @param [in] UploadDataFunction Function pointer to the tested data uploading function.
* @param [in] parameter Storage Parameter to be used with the function (function dependent).
*
* @return True if test case succeeded, false otherwise.
*/
bool DataTest::TestCase(void (DataTest::*UploadDataFunction)(glw::GLuint, glw::GLenum), glw::GLenum parameter)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLuint buffer = 0;
bool is_ok = true;
bool is_error = false;
try
{
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
(this->*UploadDataFunction)(buffer, parameter);
gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed.");
glw::GLuint* data = (glw::GLuint*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed.");
is_ok = compare(data, s_reference, s_reference_count);
if (!is_ok)
{
LogFail(UploadDataFunction, parameter, data, s_reference, s_reference_count);
}
gl.unmapBuffer(GL_ARRAY_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed.");
}
catch (...)
{
is_ok = false;
is_error = true;
LogError(UploadDataFunction, parameter);
}
if (buffer)
{
gl.deleteBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed.");
}
if (is_error)
{
throw 0;
}
return is_ok;
}
/** @brief NamedBufferData data upload function.
*
* @param [in] id Buffer id to be uploaded.
* @param [in] parameter Storage Parameter to be used with the function, one of:
* - GL_STREAM_DRAW,
* - GL_STREAM_READ,
* - GL_STREAM_COPY,
* - GL_STATIC_DRAW,
* - GL_STATIC_READ,
* - GL_STATIC_COPY,
* - GL_DYNAMIC_DRAW,
* - GL_DYNAMIC_READ and
* - GL_DYNAMIC_COPY.
*/
void DataTest::UploadUsingNamedBufferData(glw::GLuint id, glw::GLenum parameter)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
m_pNamedBufferData(id, s_reference_size, s_reference, parameter);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
}
/** @brief NamedBufferSubData data upload function.
*
* @param [in] id Buffer id to be uploaded.
* @param [in] parameter Storage parameter to be used with the NamedBufferData for
* the storage allocation (before call to NamedBufferSubData), one of:
* - GL_STREAM_DRAW,
* - GL_STREAM_READ,
* - GL_STREAM_COPY,
* - GL_STATIC_DRAW,
* - GL_STATIC_READ,
* - GL_STATIC_COPY,
* - GL_DYNAMIC_DRAW,
* - GL_DYNAMIC_READ and
* - GL_DYNAMIC_COPY.
*/
void DataTest::UploadUsingNamedBufferSubData(glw::GLuint id, glw::GLenum parameter)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
m_pNamedBufferData(id, s_reference_size, DE_NULL, parameter);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
m_pNamedBufferSubData(id, 0, s_reference_size, s_reference);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferSubData failed.");
}
/** @brief NamedBufferStorage data upload function.
*
* @param [in] id Buffer id to be uploaded.
* @param [in] parameter Storage Parameter to be used with the function, one of:
* - GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT,
* - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
* - GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT,
* - GL_MAP_READ_BIT | GL_MAP_COHERENT_BIT,
* - GL_MAP_READ_BIT | GL_CLIENT_STORAGE_BIT
*/
void DataTest::UploadUsingNamedBufferStorage(glw::GLuint id, glw::GLenum parameter)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
m_pNamedBufferStorage(id, s_reference_size, s_reference, parameter);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage failed.");
}
/** @brief CopyNamedBufferSubData data upload function (uses auxiliary buffer object).
*
* @param [in] id Buffer id to be uploaded.
* @param [in] parameter Storage parameter to be used with the NamedBufferData for
* the auxiliary buffer object storage allocation
* (before call to CopyNamedBufferSubData), one of:
* - GL_STREAM_DRAW,
* - GL_STREAM_READ,
* - GL_STREAM_COPY,
* - GL_STATIC_DRAW,
* - GL_STATIC_READ,
* - GL_STATIC_COPY,
* - GL_DYNAMIC_DRAW,
* - GL_DYNAMIC_READ and
* - GL_DYNAMIC_COPY.
*/
void DataTest::UploadUsingCopyNamedBufferSubData(glw::GLuint id, glw::GLenum parameter)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
m_pNamedBufferData(id, s_reference_size, DE_NULL, parameter);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
glw::GLuint auxiliary_buffer = 0;
bool auxiliary_buffer_is_ok = true;
try
{
gl.genBuffers(1, &auxiliary_buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers failed.");
gl.bindBuffer(GL_ARRAY_BUFFER, auxiliary_buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed.");
gl.bufferData(GL_ARRAY_BUFFER, s_reference_size, s_reference, parameter);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData failed.");
m_pCopyNamedBufferSubData(auxiliary_buffer, id, 0, 0, s_reference_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyNamedBufferSubData failed.");
}
catch (...)
{
auxiliary_buffer_is_ok = false;
}
if (auxiliary_buffer)
{
gl.deleteBuffers(1, &auxiliary_buffer);
}
if (!auxiliary_buffer_is_ok)
{
throw 0;
}
}
/** @brief Compare two unsigned integer arrays.
*
* @param [in] data Data to be compared.
* @param [in] reference Reference data to be compared to.
* @param [in] count Number of elements to be compared.
*
* @return True if count of data the elements are equal to reference counterparts, false otherwise.
*/
bool DataTest::compare(const glw::GLuint* data, const glw::GLuint* reference, const glw::GLsizei count)
{
for (glw::GLsizei i = 0; i < count; ++i)
{
if (data[i] != reference[i])
{
return false;
}
}
return true;
}
/** @brief Prepare error message and log it.
*
* @param [in] UploadDataFunction Upload function pointer which have failed, one of:
* - DataTest::UploadUsingNamedBufferData,
* - DataTest::UploadUsingNamedBufferSubData
* - DataTest::UploadUsingNamedBufferStorage and
* - DataTest::UploadUsingCopyNamedBufferSubData.
* @param [in] parameter Parameter which was passed to function.
* @param [in] data Data which was downloaded.
* @param [in] reference Reference data.
* @param [in] count Number of elements compared.
*/
void DataTest::LogFail(void (DataTest::*UploadDataFunction)(glw::GLuint, glw::GLenum), glw::GLenum parameter,
const glw::GLuint* data, const glw::GLuint* reference, const glw::GLsizei count)
{
std::string the_log = "The test of ";
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferData)
{
the_log.append("glNamedBufferData");
}
else
{
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferSubData)
{
the_log.append("glNamedBufferSubData");
}
else
{
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage)
{
the_log.append("glNamedBufferStorage");
}
else
{
if (UploadDataFunction == &DataTest::UploadUsingCopyNamedBufferSubData)
{
the_log.append("glCopyNamedBufferSubData");
}
else
{
the_log.append("uknown upload function");
}
}
}
}
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage)
{
the_log.append(" called with usage parameter ");
std::stringstream bitfield_string_stream;
bitfield_string_stream << glu::getBufferMapFlagsStr(parameter);
the_log.append(bitfield_string_stream.str());
}
else
{
the_log.append(" called with usage parameter ");
the_log.append(glu::getUsageName(parameter));
}
the_log.append(". Buffer data is equal to [");
for (glw::GLsizei i = 0; i < count; ++i)
{
std::stringstream number;
number << data[i];
the_log.append(number.str());
if (i != count - 1)
{
the_log.append(", ");
}
}
the_log.append("], but [");
for (glw::GLsizei i = 0; i < count; ++i)
{
std::stringstream number;
number << reference[i];
the_log.append(number.str());
if (i != count - 1)
{
the_log.append(", ");
}
}
the_log.append("] was expected.");
m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage;
}
void DataTest::LogError(void (DataTest::*UploadDataFunction)(glw::GLuint, glw::GLenum), glw::GLenum parameter)
{
std::string the_log = "Unexpected error occurred during the test of ";
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferData)
{
the_log.append("glNamedBufferData");
}
else
{
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferSubData)
{
the_log.append("glNamedBufferSubData");
}
else
{
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage)
{
the_log.append("glNamedBufferStorage");
}
else
{
if (UploadDataFunction == &DataTest::UploadUsingCopyNamedBufferSubData)
{
the_log.append("glCopyNamedBufferSubData");
}
else
{
the_log.append("uknown upload function");
}
}
}
}
if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage)
{
the_log.append(" called with usage parameter ");
std::stringstream bitfield_string_stream;
bitfield_string_stream << glu::getBufferMapFlagsStr(parameter);
the_log.append(bitfield_string_stream.str());
}
else
{
the_log.append(" called with usage parameter ");
the_log.append(glu::getUsageName(parameter));
}
the_log.append(".");
m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage;
}
const glw::GLuint DataTest::s_reference[] = {
0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096
}; //!< Reference data.
const glw::GLsizei DataTest::s_reference_size = sizeof(s_reference); //!< Size of the reference data.
const glw::GLsizei DataTest::s_reference_count =
s_reference_size / sizeof(s_reference[0]); //!< NUmber of elements of the reference data.
/******************************** Clear Test Implementation ********************************/
/** @brief Data Test constructor.
*
* @param [in] context OpenGL context.
*/
ClearTest::ClearTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_clear", "Buffer Objects Clear Test")
, m_pNamedBufferData(DE_NULL)
, m_pClearNamedBufferData(DE_NULL)
, m_pClearNamedBufferSubData(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief ClearNamedBufferData wrapper implementation.
*
* @note USE_SUB_DATA == false, so ClearNamedBufferData will be used.
*
* @param [in] buffer ID of the buffer to be cleared.
* @param [in] internalformat GL internal format for clearing, one of the listed in test class description.
* @param [in] size Size of the data.
* @param [in] format GL Format of the data.
* @param [in] type GL Type of the data element.
* @param [in] data Data to be cleared with.
*/
template <>
void ClearTest::ClearNamedBuffer<false>(glw::GLuint buffer, glw::GLenum internalformat, glw::GLsizei size,
glw::GLenum format, glw::GLenum type, glw::GLvoid* data)
{
(void)size;
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
m_pClearNamedBufferData(buffer, internalformat, format, type, data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearNamedBufferData failed.");
}
/** @brief ClearNamedBufferSubData wrapper implementation.
*
* @note USE_SUB_DATA == true, so ClearNamedBufferSubData will be used.
*
* @param [in] buffer ID of the buffer to be cleared.
* @param [in] internalformat GL internal format for clearing, one of the listed in test class description.
* @param [in] size Size of the data.
* @param [in] format GL Format of the data.
* @param [in] type GL Type of the data element.
* @param [in] data Data to be cleared with.
*/
template <>
void ClearTest::ClearNamedBuffer<true>(glw::GLuint buffer, glw::GLenum internalformat, glw::GLsizei size,
glw::GLenum format, glw::GLenum type, glw::GLvoid* data)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
m_pClearNamedBufferSubData(buffer, internalformat, 0, size, format, type, data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearNamedBufferData failed.");
}
/** @brief Compare two arrays with elements of type T == GLfloat (specialized).
*
* @param [in] data Data to be compared.
* @param [in] reference Reference data to be compared to.
* @param [in] count Number of elements to be compared.
*
* @return True if count of data the elements are equal to reference counterparts, false otherwise.
*/
template <>
bool ClearTest::Compare<glw::GLfloat>(const glw::GLfloat* data, const glw::GLfloat* reference, const glw::GLsizei count)
{
for (glw::GLsizei i = 0; i < count; ++i)
{
if (de::abs(data[i] - reference[i]) > 0.00001 /* Precision. */)
{
return false;
}
}
return true;
}
/** @brief Compare two arrays with elements of type T.
*
* @tparam T Type of data to be compared (anything which is not GLfloat.
* Floating point numbers have another specialized implementation,
* which accounts the precision issues.
*
* @param [in] data Data to be compared.
* @param [in] reference Reference data to be compared to.
* @param [in] count Number of elements to be compared.
*
* @return True if count of data the elements are equal to reference counterparts, false otherwise.
*/
template <typename T>
bool ClearTest::Compare(const T* data, const T* reference, const glw::GLsizei count)
{
for (glw::GLsizei i = 0; i < count; ++i)
{
if (data[i] != reference[i])
{
return false;
}
}
return true;
}
/** @brief Prepare error message and log it.
*
* @tparam T Type of data to which was tested.
*
* @param [in] internalformat Internal format used for clearing, one of the listed in test class description.
* @param [in] data Data which was used for clear test.
* @param [in] reference Reference data.
* @param [in] count Number of elements to be compared.
*/
template <typename T>
void ClearTest::LogFail(bool use_sub_data, glw::GLenum internalformat, const T* data, const T* reference,
const glw::GLsizei count)
{
(void)internalformat;
std::string the_log = "The test of ";
if (use_sub_data)
{
the_log.append("ClearNamedBufferSubData has failed for internalformat ");
}
else
{
the_log.append("ClearNamedBufferData has failed for internalformat ");
}
//the_log.append(glu::getPixelFormatName(internalformat));
the_log.append(". Cleared buffer data is equal to [");
for (glw::GLsizei i = 0; i < count; ++i)
{
std::stringstream number;
number << data[i];
the_log.append(number.str());
if (i != count - 1)
{
the_log.append(", ");
}
}
the_log.append("], but [");
for (glw::GLsizei i = 0; i < count; ++i)
{
std::stringstream number;
number << reference[i];
the_log.append(number.str());
if (i != count - 1)
{
the_log.append(", ");
}
}
the_log.append("] was expected.");
m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage;
}
void ClearTest::LogError(bool use_sub_data, glw::GLenum internalformat)
{
(void)internalformat;
std::string the_log = "Unexpected error occurred during Test of ";
if (use_sub_data)
{
the_log.append("ClearNamedBufferSubData with internalformat ");
}
else
{
the_log.append("ClearNamedBufferData with internalformat ");
}
//the_log.append(glu::getPixelFormatName(internalformat));
m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage;
}
/** @brief Run CLearing test case.
*
* @tparam T Type of data to which to be tested.
* @tparam USE_SUB_DATA If true ClearNamedBufferSubData will be used, ClearNamedBufferData otherwise.
*
* @param [in] internalformat Internal format used for clearing, one of the listed in test class description.
* @param [in] count Number of elements.
* @param [in] internalformat Data format to be used for clearing.
* @param [in] data Data to be used with clear test.
*
* @return True if test case succeeded, false otherwise.
*/
template <typename T, bool USE_SUB_DATA>
bool ClearTest::TestClearNamedBufferData(glw::GLenum internalformat, glw::GLsizei count, glw::GLenum format,
glw::GLenum type, T* data)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLuint buffer = 0;
bool is_ok = true;
bool is_error = false;
try
{
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
m_pNamedBufferData(buffer, static_cast<glw::GLsizei>(count * sizeof(T)), NULL, GL_DYNAMIC_COPY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
ClearNamedBuffer<USE_SUB_DATA>(buffer, internalformat, static_cast<glw::GLsizei>(count * sizeof(T)), format,
type, data);
gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed.");
T* _data = (T*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed.");
is_ok = Compare<T>(_data, data, count);
if (!is_ok)
{
/* Log. */
LogFail<T>(USE_SUB_DATA, internalformat, _data, data, count);
}
gl.unmapBuffer(GL_ARRAY_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed.");
}
catch (...)
{
is_ok = false;
is_error = true;
LogError(USE_SUB_DATA, internalformat);
}
if (buffer)
{
gl.deleteBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed.");
}
if (is_error)
{
throw 0;
}
return is_ok;
}
/** @brief Iterate Data Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult ClearTest::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;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATA)gl.clearNamedBufferData;
m_pClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATA)gl.clearNamedBufferSubData;
try
{
if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pClearNamedBufferData) ||
(DE_NULL == m_pClearNamedBufferSubData))
{
throw 0;
}
{
/* unsigned byte norm component ClearNamedBufferData tests */
glw::GLubyte reference[4] = { 5, 1, 2, 3 };
is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_R8, 1, GL_RED, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RG8, 2, GL_RG, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RGBA8, 4, GL_RGBA, GL_UNSIGNED_BYTE, reference);
/* unsigned byte norm component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_R8, 1, GL_RED, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RG8, 2, GL_RG, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RGBA8, 4, GL_RGBA, GL_UNSIGNED_BYTE, reference);
/* unsigned byte component ClearNamedBufferData tests */
is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_R8UI, 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RG8UI, 2, GL_RG_INTEGER, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RGBA8UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, reference);
/* unsigned byte component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_R8UI, 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RG8UI, 2, GL_RG_INTEGER, GL_UNSIGNED_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RGBA8UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, reference);
}
{
/* signed byte component ClearNamedBufferData tests */
glw::GLbyte reference[4] = { 5, 1, -2, 3 };
is_ok &= TestClearNamedBufferData<glw::GLbyte, false>(GL_R8I, 1, GL_RED_INTEGER, GL_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLbyte, false>(GL_RG8I, 2, GL_RG_INTEGER, GL_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLbyte, false>(GL_RGBA8I, 4, GL_RGBA_INTEGER, GL_BYTE, reference);
/* signed byte component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLbyte, true>(GL_R8I, 1, GL_RED_INTEGER, GL_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLbyte, true>(GL_RG8I, 2, GL_RG_INTEGER, GL_BYTE, reference);
is_ok &= TestClearNamedBufferData<glw::GLbyte, true>(GL_RGBA8I, 4, GL_RGBA_INTEGER, GL_BYTE, reference);
}
{
/* unsigned short norm component ClearNamedBufferData tests */
glw::GLushort reference[4] = { 5, 1, 2, 3 };
is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_R16, 1, GL_RED, GL_UNSIGNED_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_RG16, 2, GL_RG, GL_UNSIGNED_SHORT, reference);
is_ok &=
TestClearNamedBufferData<glw::GLushort, false>(GL_RGBA16, 4, GL_RGBA, GL_UNSIGNED_SHORT, reference);
/* unsigned short norm component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_R16, 1, GL_RED, GL_UNSIGNED_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_RG16, 2, GL_RG, GL_UNSIGNED_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_RGBA16, 4, GL_RGBA, GL_UNSIGNED_SHORT, reference);
/* unsigned short component ClearNamedBufferData tests */
is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_R16UI, 1, GL_RED_INTEGER, GL_UNSIGNED_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_RG16UI, 2, GL_RG_INTEGER, GL_UNSIGNED_SHORT, reference);
is_ok &=
TestClearNamedBufferData<glw::GLushort, false>(GL_RGBA16UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, reference);
/* unsigned short component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_R16UI, 1, GL_RED_INTEGER, GL_UNSIGNED_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_RG16UI, 2, GL_RG_INTEGER, GL_UNSIGNED_SHORT, reference);
is_ok &=
TestClearNamedBufferData<glw::GLushort, true>(GL_RGBA16UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, reference);
}
{
/* signed short component ClearNamedBufferData tests */
glw::GLshort reference[4] = { 5, 1, -2, 3 };
is_ok &= TestClearNamedBufferData<glw::GLshort, false>(GL_R16I, 1, GL_RED_INTEGER, GL_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLshort, false>(GL_RG16I, 2, GL_RG_INTEGER, GL_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLshort, false>(GL_RGBA16I, 4, GL_RGBA_INTEGER, GL_SHORT, reference);
/* signed short component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLshort, true>(GL_R16I, 1, GL_RED_INTEGER, GL_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLshort, true>(GL_RG16I, 2, GL_RG_INTEGER, GL_SHORT, reference);
is_ok &= TestClearNamedBufferData<glw::GLshort, true>(GL_RGBA16I, 4, GL_RGBA_INTEGER, GL_SHORT, reference);
}
{
/* unsigned int component ClearNamedBufferData tests */
glw::GLuint reference[4] = { 5, 1, 2, 3 };
is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_R32UI, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_RG32UI, 2, GL_RG_INTEGER, GL_UNSIGNED_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_RGB32UI, 3, GL_RGB_INTEGER, GL_UNSIGNED_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_RGBA32UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_INT, reference);
/* unsigned int component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_R32UI, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_RG32UI, 2, GL_RG_INTEGER, GL_UNSIGNED_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_RGB32UI, 3, GL_RGB_INTEGER, GL_UNSIGNED_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_RGBA32UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_INT, reference);
}
{
/* signed int component ClearNamedBufferData tests */
glw::GLint reference[4] = { 5, 1, -2, 3 };
is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_R32I, 1, GL_RED_INTEGER, GL_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_RG32I, 2, GL_RG_INTEGER, GL_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_RGB32I, 3, GL_RGB_INTEGER, GL_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_RGBA32I, 4, GL_RGBA_INTEGER, GL_INT, reference);
/* signed int component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_R32I, 1, GL_RED_INTEGER, GL_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_RG32I, 2, GL_RG_INTEGER, GL_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_RGB32I, 3, GL_RGB_INTEGER, GL_INT, reference);
is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_RGBA32I, 4, GL_RGBA_INTEGER, GL_INT, reference);
}
{
/* half float component ClearNamedBufferData tests */
glw::GLhalf reference[4] = { 0x3C00 /* 1.0hf */, 0x0000 /* 0.0hf */, 0xC000 /* -2.0hf */,
0x3555 /* 0.333333333hf */ };
is_ok &= TestClearNamedBufferData<glw::GLhalf, false>(GL_R16F, 1, GL_RED, GL_HALF_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLhalf, false>(GL_RG16F, 2, GL_RG, GL_HALF_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLhalf, false>(GL_RGBA16F, 4, GL_RGBA, GL_HALF_FLOAT, reference);
/* half float component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLhalf, true>(GL_R16F, 1, GL_RED, GL_HALF_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLhalf, true>(GL_RG16F, 2, GL_RG, GL_HALF_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLhalf, true>(GL_RGBA16F, 4, GL_RGBA, GL_HALF_FLOAT, reference);
}
{
/* float component ClearNamedBufferData tests */
glw::GLfloat reference[4] = { 1.f, 0.f, -2.f, 0.3333333333f };
is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_R32F, 1, GL_RED, GL_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_RG32F, 2, GL_RG, GL_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_RGB32F, 3, GL_RGB, GL_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_RGBA32F, 4, GL_RGBA, GL_FLOAT, reference);
/* float component ClearNamedBufferSubData tests */
is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_R32F, 1, GL_RED, GL_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_RG32F, 2, GL_RG, GL_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_RGB32F, 3, GL_RGB, GL_FLOAT, reference);
is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_RGBA32F, 4, GL_RGBA, GL_FLOAT, reference);
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* 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;
}
/******************************** Map Read Only Test Implementation ********************************/
/** @brief Map Read Only Test constructor.
*
* @param [in] context OpenGL context.
*/
MapReadOnlyTest::MapReadOnlyTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_map_read_only", "Buffer Objects Map Read Only Test")
, m_pNamedBufferData(DE_NULL)
, m_pMapNamedBuffer(DE_NULL)
, m_pUnmapNamedBuffer(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Map Read Only Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult MapReadOnlyTest::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;
glw::GLuint buffer = 0;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer;
m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer;
try
{
if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pUnmapNamedBuffer))
{
throw 0;
}
/* Buffer creation. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
/* Buffer's storage allocation and reference data upload. */
m_pNamedBufferData(buffer, s_reference_size, s_reference, GL_DYNAMIC_COPY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
/* Mapping with new named buffer map function. */
glw::GLuint* data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_READ_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
if (DE_NULL == data)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glMapNamedBuffer returned NULL pointer, but buffer's data was expected."
<< tcu::TestLog::EndMessage;
}
else
{
/* Comparison results with reference data. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
is_ok &= (data[i] == s_reference[i]);
}
if (!is_ok)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glMapNamedBuffer returned pointer to data which is not identical to reference data."
<< tcu::TestLog::EndMessage;
}
/* Unmapping with new named buffer unmap function. */
if (GL_TRUE != m_pUnmapNamedBuffer(buffer))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected."
<< tcu::TestLog::EndMessage;
}
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = false;
}
/* 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;
}
const glw::GLuint MapReadOnlyTest::s_reference[] = { 0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 };
const glw::GLsizei MapReadOnlyTest::s_reference_size = sizeof(s_reference);
const glw::GLsizei MapReadOnlyTest::s_reference_count = s_reference_size / sizeof(s_reference[0]);
/******************************** Map Read Write Test Implementation ********************************/
/** @brief Map Read Write Test constructor.
*
* @param [in] context OpenGL context.
*/
MapReadWriteTest::MapReadWriteTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_map_read_write", "Buffer Objects Map Read Write Test")
, m_pNamedBufferData(DE_NULL)
, m_pMapNamedBuffer(DE_NULL)
, m_pUnmapNamedBuffer(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Map Read Write Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult MapReadWriteTest::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;
glw::GLuint buffer = 0;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer;
m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer;
try
{
if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pUnmapNamedBuffer))
{
throw 0;
}
/* Buffer creation. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
/* Buffer's storage allocation and reference data upload. */
m_pNamedBufferData(buffer, s_reference_size, s_reference, GL_DYNAMIC_COPY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
/* Mapping with new named buffer map function. */
glw::GLuint* data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_READ_WRITE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
if (DE_NULL == data)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glMapNamedBuffer returned NULL pointer, but buffer's data was expected."
<< tcu::TestLog::EndMessage;
}
else
{
/* Comparison results with reference data. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
is_ok &= (data[i] == s_reference[i]);
}
if (!is_ok)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glMapNamedBuffer returned pointer to data which is not identical to reference data."
<< tcu::TestLog::EndMessage;
}
/* Writting inverted reference data. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
data[i] = s_reference[s_reference_count - i - 1];
}
/* Unmapping with new named buffer unmap function. */
if (GL_TRUE != m_pUnmapNamedBuffer(buffer))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected."
<< tcu::TestLog::EndMessage;
}
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
data = DE_NULL;
data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_READ_WRITE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
if (DE_NULL == data)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glMapNamedBuffer returned NULL pointer, but buffer's data was expected."
<< tcu::TestLog::EndMessage;
}
else
{
/* Comparison results with inverted reference data. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
is_ok &= (data[i] == s_reference[s_reference_count - i - 1]);
}
/* Unmapping with new named buffer unmap function. */
if (GL_TRUE != m_pUnmapNamedBuffer(buffer))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected."
<< tcu::TestLog::EndMessage;
}
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = false;
}
/* 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;
}
const glw::GLuint MapReadWriteTest::s_reference[] = {
0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096
}; //!< Reference data.
const glw::GLsizei MapReadWriteTest::s_reference_size = sizeof(s_reference); //!< Reference data size.
const glw::GLsizei MapReadWriteTest::s_reference_count =
s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count.
/******************************** Map Write Only Test Implementation ********************************/
/** @brief Map Write Only Test constructor.
*
* @param [in] context OpenGL context.
*/
MapWriteOnlyTest::MapWriteOnlyTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_map_write_only", "Buffer Objects Map Write Only Test")
, m_pNamedBufferData(DE_NULL)
, m_pMapNamedBuffer(DE_NULL)
, m_pUnmapNamedBuffer(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Map Write Only Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult MapWriteOnlyTest::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;
glw::GLuint buffer = 0;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer;
m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer;
try
{
if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pUnmapNamedBuffer))
{
throw 0;
}
/* Buffer creation. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
/* Buffer's storage allocation. */
m_pNamedBufferData(buffer, s_reference_size, NULL, GL_DYNAMIC_COPY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
/* Mapping with new named buffer map function. */
glw::GLuint* data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_WRITE_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
if (DE_NULL == data)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glMapNamedBuffer returned NULL pointer, but buffer's data was expected."
<< tcu::TestLog::EndMessage;
}
else
{
/* Reference data upload. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
data[i] = s_reference[i];
}
/* Unmapping with new named buffer unmap function. */
if (GL_TRUE != m_pUnmapNamedBuffer(buffer))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected."
<< tcu::TestLog::EndMessage;
}
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
/* Mapping data, the old way. */
gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed.");
data = DE_NULL;
data = (glw::GLuint*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed.");
/* Comparison results with reference data. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
is_ok &= (data[i] == s_reference[i]);
}
if (!is_ok)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glMapNamedBuffer, called with GL_WRITE_ONLY access flag, had not stored the reference data."
<< tcu::TestLog::EndMessage;
}
gl.unmapBuffer(GL_ARRAY_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed.");
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = false;
}
/* 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;
}
const glw::GLuint MapWriteOnlyTest::s_reference[] = {
0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096
}; //!< Reference data.
const glw::GLsizei MapWriteOnlyTest::s_reference_size = sizeof(s_reference); //!< Reference data size.
const glw::GLsizei MapWriteOnlyTest::s_reference_count =
s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count.
/******************************** Buffers Range Map Read Bit Test Implementation ********************************/
/** @brief Buffers Range Map Read Bit Test constructor.
*
* @param [in] context OpenGL context.
*/
MapRangeReadBitTest::MapRangeReadBitTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_map_range_read_bit", "Buffer Objects Map Range Read Bit Test")
, m_pNamedBufferStorage(DE_NULL)
, m_pMapNamedBufferRange(DE_NULL)
, m_pUnmapNamedBuffer(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Buffers Range Map Read Bit Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult MapRangeReadBitTest::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;
glw::GLuint buffer = 0;
m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage;
m_pMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGE)gl.mapNamedBufferRange;
m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer;
try
{
if ((DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pMapNamedBufferRange) ||
(DE_NULL == m_pUnmapNamedBuffer))
{
throw 0;
}
glw::GLbitfield access_flags[] = { GL_MAP_READ_BIT, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT,
GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT };
glw::GLuint access_flags_count = sizeof(access_flags) / sizeof(access_flags[0]);
for (glw::GLuint i = 0; i < access_flags_count; ++i)
{
/* Buffer creation. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
/* Buffer's storage allocation and reference data upload. */
m_pNamedBufferStorage(buffer, s_reference_size, s_reference, access_flags[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
/* Mapping with first half of named buffer. */
glw::GLuint* data = (glw::GLuint*)m_pMapNamedBufferRange(buffer, 0, s_reference_size / 2, access_flags[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed.");
/* Check with reference. */
is_ok &= CompareWithReference(data, 0, s_reference_size / 2);
/* Unmapping with new named buffer unmap function. */
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
/* Mapping with second half of named buffer. */
data = (glw::GLuint*)m_pMapNamedBufferRange(buffer, s_reference_size / 2, s_reference_size / 2,
access_flags[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed.");
/* Check with reference. */
is_ok &= CompareWithReference(data, s_reference_size / 2, s_reference_size / 2);
/* Unmapping with new named buffer unmap function. */
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = 0;
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = 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;
}
/** @brief Compare array of unsigned integers with subrange of reference values (s_reference).
*
* @param [in] data Data to be compared.
* @param [in] offset Offset in the reference data.
* @param [in] length Length of the data to be compared.
*
* @return True if comparison succeeded, false otherwise.
*/
bool MapRangeReadBitTest::CompareWithReference(glw::GLuint* data, glw::GLintptr offset, glw::GLsizei length)
{
if (DE_NULL == data)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glMapNamedBufferRange called with offset " << offset << " and length "
<< length << " returned NULL pointer, but buffer's data was expected." << tcu::TestLog::EndMessage;
}
else
{
glw::GLuint start = static_cast<glw::GLuint>((offset) / sizeof(s_reference[0]));
glw::GLuint end = static_cast<glw::GLuint>((offset + length) / sizeof(s_reference[0]));
/* Comparison results with reference data. */
for (glw::GLuint i = start; i < end; ++i)
{
#if (DE_COMPILER == DE_COMPILER_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
if (data[i - start] != s_reference[i])
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glMapNamedBufferRange called with offset " << offset << " and length "
<< length << " returned pointer to data which is not identical to reference data."
<< tcu::TestLog::EndMessage;
return false;
}
#if (DE_COMPILER == DE_COMPILER_GCC)
#pragma GCC diagnostic pop
#endif
}
}
return true;
}
const glw::GLuint MapRangeReadBitTest::s_reference[] = {
1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096
}; //!< Reference data.
const glw::GLsizei MapRangeReadBitTest::s_reference_size = sizeof(s_reference); //!< Reference data size.
const glw::GLsizei MapRangeReadBitTest::s_reference_count =
s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count.
/******************************** Buffers Range Map Write Bit Test Implementation ********************************/
/** @brief Buffers Range Map Write Bit Test constructor.
*
* @param [in] context OpenGL context.
*/
MapRangeWriteBitTest::MapRangeWriteBitTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_map_range_write_bit", "Buffer Objects Map Range Write Bit Test")
, m_pNamedBufferStorage(DE_NULL)
, m_pMapNamedBufferRange(DE_NULL)
, m_pUnmapNamedBuffer(DE_NULL)
, m_pFlushMappedNamedBufferRange(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Buffers Range Map Read Bit Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult MapRangeWriteBitTest::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;
glw::GLuint buffer = 0;
m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage;
m_pMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGE)gl.mapNamedBufferRange;
m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer;
m_pFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGE)gl.flushMappedNamedBufferRange;
try
{
if ((DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pMapNamedBufferRange) ||
(DE_NULL == m_pUnmapNamedBuffer) || (DE_NULL == m_pFlushMappedNamedBufferRange))
{
throw 0;
}
struct
{
glw::GLbitfield creation;
glw::GLbitfield first_mapping;
glw::GLbitfield second_mapping;
} access_flags[] = {
{ GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT },
{ GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT },
{ GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT, GL_MAP_WRITE_BIT },
{ GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT,
GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT },
{ GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT }
};
glw::GLuint access_flags_count = sizeof(access_flags) / sizeof(access_flags[0]);
for (glw::GLuint i = 0; i < access_flags_count; ++i)
{
/* Buffer creation. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
/* Buffer's storage allocation and reference data upload. */
m_pNamedBufferStorage(buffer, s_reference_size, DE_NULL, access_flags[i].creation);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage failed.");
/* Mapping with first half of named buffer. */
glw::GLuint* data =
(glw::GLuint*)m_pMapNamedBufferRange(buffer, 0, s_reference_size / 2, access_flags[i].first_mapping);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed.");
/* Write to mapped buffer. */
for (glw::GLsizei j = 0; j < s_reference_count / 2; ++j)
{
data[j] = s_reference[j];
}
/* Flush, if needed. */
glw::GLenum flush_error = GL_NO_ERROR;
if (GL_MAP_FLUSH_EXPLICIT_BIT & access_flags[i].first_mapping)
{
m_pFlushMappedNamedBufferRange(buffer, 0, s_reference_size / 2);
flush_error = gl.getError();
}
/* Unmapping with new named buffer unmap function. */
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(flush_error, "glFlushMappedNamedBufferRange failed.");
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
/* Mapping with second half of named buffer. */
data = (glw::GLuint*)m_pMapNamedBufferRange(buffer, s_reference_size / 2, s_reference_size / 2,
access_flags[i].second_mapping);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed.");
/* Write to mapped buffer. */
for (glw::GLsizei j = 0; j < s_reference_count / 2; ++j)
{
data[j] = s_reference[j + s_reference_count / 2];
}
/* Flush, if needed. */
flush_error = GL_NO_ERROR;
if (GL_MAP_FLUSH_EXPLICIT_BIT & access_flags[i].second_mapping)
{
m_pFlushMappedNamedBufferRange(buffer, 0, s_reference_size / 2);
flush_error = gl.getError();
}
/* Unmapping with new named buffer unmap function. */
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(flush_error, "glFlushMappedNamedBufferRange failed.");
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
/* Check that previous mappings correctly filled buffer with reference data. */
is_ok &= CompareWithReference(buffer, access_flags[i].first_mapping | access_flags[i].second_mapping);
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = 0;
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = 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;
}
/** @brief Compare buffer's content with the reference values (s_reference) and log possible failure.
*
* @param [in] buffer Buffer to be tested.
* @param [in] access_flag Access flag used during test's mapping (for failure logging purposes).
*
* @return True if comparison succeeded, false otherwise.
*/
bool MapRangeWriteBitTest::CompareWithReference(glw::GLuint buffer, glw::GLbitfield access_flag)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Map buffer with legacy API. */
gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed.");
glw::GLuint* data = (glw::GLuint*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed.");
/* Default return value. */
bool is_ok = true;
if (DE_NULL != data)
{
/* Comparison results with reference data. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
if (data[i] != s_reference[i])
{
std::string access_string = "GL_MAP_WRITE_BIT";
if (GL_MAP_INVALIDATE_RANGE_BIT & access_flag)
{
access_string = "(GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT)";
}
if (GL_MAP_INVALIDATE_BUFFER_BIT & access_flag)
{
access_string = "(GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)";
}
if (GL_MAP_FLUSH_EXPLICIT_BIT & access_flag)
{
access_string = "(GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT)";
}
if (GL_MAP_UNSYNCHRONIZED_BIT & access_flag)
{
access_string = "(GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT)";
}
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Test of glMapNamedBufferRange with access flag " << access_string
<< " failed to fill the buffer with reference data." << tcu::TestLog::EndMessage;
is_ok = false;
break;
}
}
}
/* Unmap buffer. */
gl.unmapBuffer(GL_ARRAY_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed.");
return is_ok;
}
const glw::GLuint MapRangeWriteBitTest::s_reference[] = {
1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096
}; //!< Reference data.
const glw::GLsizei MapRangeWriteBitTest::s_reference_size = sizeof(s_reference); //!< Reference data size.
const glw::GLsizei MapRangeWriteBitTest::s_reference_count =
s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count.
/******************************** Get Named Buffer SubData Query Test Implementation ********************************/
/** @brief Get Named Buffer SubData Query Test's static constants. */
const glw::GLuint SubDataQueryTest::s_reference[] = {
1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096
}; //!< Reference data.
const glw::GLsizei SubDataQueryTest::s_reference_size = sizeof(s_reference); //!< Reference data size.
const glw::GLsizei SubDataQueryTest::s_reference_count =
s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count.
/** @brief Get Named Buffer SubData Query Test constructor.
*
* @param [in] context OpenGL context.
*/
SubDataQueryTest::SubDataQueryTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_get_named_buffer_subdata", "Buffer Objects Get Named Buffer SubData Query Test")
, m_pNamedBufferData(DE_NULL)
, m_pGetNamedBufferSubData(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Get Named Buffer SubData Query Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult SubDataQueryTest::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;
glw::GLuint buffer = 0;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATA)gl.getNamedBufferSubData;
try
{
if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pGetNamedBufferSubData))
{
throw 0;
}
/* Buffer creation. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
/* Buffer's storage allocation and reference data upload. */
m_pNamedBufferData(buffer, s_reference_size, s_reference, GL_DYNAMIC_COPY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed.");
/* Mapping with new named buffer map function. */
glw::GLuint data[s_reference_count] = {};
m_pGetNamedBufferSubData(buffer, 0, s_reference_size / 2, data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedBufferSubData failed.");
m_pGetNamedBufferSubData(buffer, s_reference_size / 2, s_reference_size / 2, &data[s_reference_count / 2]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedBufferSubData failed.");
/* Comparison results with reference data. */
for (glw::GLsizei i = 0; i < s_reference_count; ++i)
{
is_ok &= (data[i] == s_reference[i]);
}
if (!is_ok)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "glGetNamedBufferSubData returned data which is not identical to reference data."
<< tcu::TestLog::EndMessage;
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = false;
}
/* 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;
}
/******************************** Defaults Test Implementation ********************************/
/** @brief Defaults Query Test constructor.
*
* @param [in] context OpenGL context.
*/
DefaultsTest::DefaultsTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_defaults", "Buffer Objects Defaults Test")
, m_pNamedBufferData(DE_NULL)
, m_pGetNamedBufferParameteri64v(DE_NULL)
, m_pGetNamedBufferParameteriv(DE_NULL)
, m_pGetNamedBufferPointerv(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Compare value with the reference.
*
* @param [in] value Value to be compared.
* @param [in] reference_value Reference value for comparison.
* @param [in] pname_string String of parameter name of the value (for logging).
* @param [in] function_string String of function which returned the value (for logging).
*
* @return True if value is equal to reference value, false otherwise. False solution is logged.
*/
template <typename T>
bool DefaultsTest::CheckValue(const T value, const T reference_value, const glw::GLchar* pname_string,
const glw::GLchar* function_string)
{
if (reference_value != value)
{
/* Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << function_string << " called with "
<< pname_string << " parameter name returned " << value << ", but "
<< reference_value << " was expected." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Iterate Defaults Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult DefaultsTest::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;
glw::GLuint buffer = 0;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64V)gl.getNamedBufferParameteri64v;
m_pGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIV)gl.getNamedBufferParameteriv;
m_pGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERV)gl.getNamedBufferPointerv;
try
{
if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pGetNamedBufferParameteri64v) ||
(DE_NULL == m_pGetNamedBufferParameteriv) || (DE_NULL == m_pGetNamedBufferPointerv))
{
throw 0;
}
/* Buffer creation. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
/* Test data for glGetNamedBufferParameteri*v. */
static const struct
{
glw::GLenum pname;
const glw::GLchar* pname_string;
glw::GLint expected_data;
} test_values[] = { { GL_BUFFER_SIZE, "GL_BUFFER_SIZE", 0 },
{ GL_BUFFER_USAGE, "GL_BUFFER_USAGE", GL_STATIC_DRAW },
{ GL_BUFFER_ACCESS, "GL_BUFFER_ACCESS", GL_READ_WRITE },
{ GL_BUFFER_ACCESS_FLAGS, "GL_BUFFER_ACCESS_FLAGS", 0 },
{ GL_BUFFER_IMMUTABLE_STORAGE, "GL_BUFFER_IMMUTABLE_STORAGE", GL_FALSE },
{ GL_BUFFER_MAPPED, "GL_BUFFER_MAPPED", GL_FALSE },
{ GL_BUFFER_MAP_OFFSET, "GL_BUFFER_MAP_OFFSET", 0 },
{ GL_BUFFER_MAP_LENGTH, "GL_BUFFER_MAP_LENGTH", 0 },
{ GL_BUFFER_STORAGE_FLAGS, "GL_BUFFER_STORAGE_FLAGS", 0 } };
static const glw::GLuint test_dictionary_count = sizeof(test_values) / sizeof(test_values[0]);
/* Test glGetNamedBufferParameteriv. */
for (glw::GLuint i = 0; i < test_dictionary_count; ++i)
{
glw::GLint data = -1;
m_pGetNamedBufferParameteriv(buffer, test_values[i].pname, &data);
is_ok &= CheckParameterError(test_values[i].pname_string, "glGetNamedBufferParameteriv");
is_ok &= CheckValue<glw::GLint>(data, test_values[i].expected_data, test_values[i].pname_string,
"glGetNamedBufferParameteriv");
}
/* Test glGetNamedBufferParameteri64v. */
for (glw::GLuint i = 0; i < test_dictionary_count; ++i)
{
glw::GLint64 data = -1;
m_pGetNamedBufferParameteri64v(buffer, test_values[i].pname, &data);
is_ok &= CheckParameterError(test_values[i].pname_string, "glGetNamedBufferParameteri64v");
is_ok &= CheckValue<glw::GLint64>(data, (glw::GLint64)test_values[i].expected_data,
test_values[i].pname_string, "glGetNamedBufferParameteri64v");
}
/* Test glGetNamedBufferPointerv. */
{
glw::GLvoid* data = (glw::GLvoid*)1;
m_pGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &data);
is_ok &= CheckParameterError("GL_BUFFER_MAP_POINTER", "glGetNamedBufferPointer");
is_ok &= CheckValue<glw::GLvoid*>(data, (glw::GLvoid*)DE_NULL, "GL_BUFFER_MAP_POINTER",
"glGetNamedBufferParameteriv");
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = 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;
}
/** @brief Check for GL error and log.
*
* @param [in] pname_string String of parameter name of the value (for logging).
* @param [in] function_string String of function which returned the value (for logging).
*
* @return True if error was generated, false otherwise. False solution is logged.
*/
bool DefaultsTest::CheckParameterError(const glw::GLchar* pname_string, const glw::GLchar* function_string)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Error check. */
if (glw::GLenum error = gl.getError())
{
/* Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << function_string << " called with "
<< pname_string << " parameter name unexpectedly returned "
<< glu::getErrorStr(error) << "error." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/******************************** Errors Test Implementation ********************************/
/** @brief Errors Query Test constructor.
*
* @param [in] context OpenGL context.
*/
ErrorsTest::ErrorsTest(deqp::Context& context)
: deqp::TestCase(context, "buffers_errors", "Buffer Objects Errors Test")
, m_pClearNamedBufferData(DE_NULL)
, m_pClearNamedBufferSubData(DE_NULL)
, m_pCopyNamedBufferSubData(DE_NULL)
, m_pFlushMappedNamedBufferRange(DE_NULL)
, m_pGetNamedBufferParameteri64v(DE_NULL)
, m_pGetNamedBufferParameteriv(DE_NULL)
, m_pGetNamedBufferPointerv(DE_NULL)
, m_pGetNamedBufferSubData(DE_NULL)
, m_pMapNamedBuffer(DE_NULL)
, m_pMapNamedBufferRange(DE_NULL)
, m_pNamedBufferData(DE_NULL)
, m_pNamedBufferStorage(DE_NULL)
, m_pNamedBufferSubData(DE_NULL)
, m_pUnmapNamedBuffer(DE_NULL)
{
/* Intentionally left blank. */
}
/** @brief Iterate Errors Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult ErrorsTest::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;
/* API function pointers setup. */
m_pClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATA)gl.clearNamedBufferData;
m_pClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATA)gl.clearNamedBufferSubData;
m_pCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATA)gl.copyNamedBufferSubData;
m_pFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGE)gl.flushMappedNamedBufferRange;
m_pGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64V)gl.getNamedBufferParameteri64v;
m_pGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIV)gl.getNamedBufferParameteriv;
m_pGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERV)gl.getNamedBufferPointerv;
m_pGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATA)gl.getNamedBufferSubData;
m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer;
m_pMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGE)gl.mapNamedBufferRange;
m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData;
m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage;
m_pNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATA)gl.namedBufferSubData;
m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer;
try
{
/* API function pointers check. */
if ((DE_NULL == m_pClearNamedBufferData) || (DE_NULL == m_pClearNamedBufferSubData) ||
(DE_NULL == m_pCopyNamedBufferSubData) || (DE_NULL == m_pFlushMappedNamedBufferRange) ||
(DE_NULL == m_pGetNamedBufferParameteri64v) || (DE_NULL == m_pGetNamedBufferParameteriv) ||
(DE_NULL == m_pGetNamedBufferPointerv) || (DE_NULL == m_pGetNamedBufferSubData) ||
(DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pMapNamedBufferRange) || (DE_NULL == m_pNamedBufferData) ||
(DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pNamedBufferSubData) ||
(DE_NULL == m_pUnmapNamedBuffer))
{
throw 0;
}
/* Running test cases. Cleaning errors. */
is_ok &= TestErrorsOfClearNamedBufferData();
while (gl.getError())
;
is_ok &= TestErrorsOfClearNamedBufferSubData();
while (gl.getError())
;
is_ok &= TestErrorsOfCopyNamedBufferSubData();
while (gl.getError())
;
is_ok &= TestErrorsOfCreateBuffers();
while (gl.getError())
;
is_ok &= TestErrorsOfFlushMappedNamedBufferRange();
while (gl.getError())
;
is_ok &= TestErrorsOfGetNamedBufferParameter();
while (gl.getError())
;
is_ok &= TestErrorsOfGetNamedBufferPointerv();
while (gl.getError())
;
is_ok &= TestErrorsOfGetNamedBufferSubData();
while (gl.getError())
;
is_ok &= TestErrorsOfMapNamedBuffer();
while (gl.getError())
;
is_ok &= TestErrorsOfMapNamedBufferRange();
while (gl.getError())
;
is_ok &= TestErrorsOfNamedBufferData();
while (gl.getError())
;
is_ok &= TestErrorsOfNamedBufferStorage();
while (gl.getError())
;
is_ok &= TestErrorsOfNamedBufferSubData();
while (gl.getError())
;
is_ok &= TestErrorsOfUnmapNamedBuffer();
while (gl.getError())
;
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* 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;
}
/** Check if error was generated and if it is equal to expected value. Log possible failure.
*
* @param [in] function_name Tested Function.
* @param [in] expected_error Expected error function.
* @param [in] when_shall_be_generated Description when shall the error occure.
*
* @return True if GL error is equal to the expected value, false otherwise.
*/
bool ErrorsTest::ErrorCheckAndLog(const glw::GLchar* function_name, const glw::GLenum expected_error,
const glw::GLchar* when_shall_be_generated)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Error value storage. */
glw::GLenum error = GL_NO_ERROR;
/* Error comparision. */
if (expected_error != (error = gl.getError()))
{
/* Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << function_name << " does not generate "
<< glu::getErrorStr(expected_error) << when_shall_be_generated
<< "The error value of " << glu::getErrorStr(error) << " was observed."
<< tcu::TestLog::EndMessage;
/* Error cleanup. */
while (gl.getError())
;
/* Check failed. */
return false;
}
/* Error was equal to expected. */
return true;
}
/** @brief Test Errors Of ClearNamedBufferData function.
*
* Check that INVALID_OPERATION is generated by ClearNamedBufferData if
* buffer is not the name of an existing buffer object.
*
* Check that INVALID_ENUM is generated by ClearNamedBufferData if
* internal format is not one of the valid sized internal formats listed in
* the table above.
*
* Check that INVALID_OPERATION is generated by ClearNamedBufferData if
* any part of the specified range of the buffer object is mapped with
* MapBufferRange or MapBuffer, unless it was mapped with the
* MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags.
*
* Check that INVALID_VALUE is generated by ClearNamedBufferData if
* format is not a valid format, or type is not a valid type.
*
* True if test case succeeded, false otherwise.
*/
bool ErrorsTest::TestErrorsOfClearNamedBufferData()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Return value. */
bool is_ok = true;
bool internal_error = false;
/* Common variables. */
glw::GLuint buffer = 0;
glw::GLbyte dummy_data = 0;
try
{
/* Common preparations. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage failed.");
/* Test invalid buffer name error behavior. */
{
/* Prepare for invalid buffer name error behavior verification. */
glw::GLuint not_a_buffer_name = 0;
while (gl.isBuffer(++not_a_buffer_name))
;
/* Test. */
m_pClearNamedBufferData(not_a_buffer_name, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_OPERATION,
" if buffer is not the name of an existing buffer object.");
}
/* Test invalid sized internal format error behavior. */
{
/* Prepare for invalid sized internal format error behavior verification. */
static const glw::GLenum valid_internal_formats[] = {
GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I,
GL_R8UI, GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F,
GL_RG8I, GL_RG16I, GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F,
GL_RGB32I, GL_RGB32UI, GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I,
GL_RGBA16I, GL_RGBA32I, GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI, GL_NONE
};
static const glw::GLenum valid_internal_formats_last =
sizeof(valid_internal_formats) / sizeof(valid_internal_formats[0]) - 1;
glw::GLenum invalid_internal_format = 0;
while (&valid_internal_formats[valid_internal_formats_last] !=
std::find(&valid_internal_formats[0], &valid_internal_formats[valid_internal_formats_last],
(++invalid_internal_format)))
;
/* Test. */
m_pClearNamedBufferData(buffer, invalid_internal_format, GL_RED, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_ENUM,
" if internal format is not one of the valid sized internal formats "
"(GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I, GL_R8UI,"
" GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F, GL_RG8I, GL_RG16I,"
" GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F, GL_RGB32I, GL_RGB32UI,"
" GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I, GL_RGBA16I, GL_RGBA32I,"
" GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI).");
}
/* Test of mapped buffer clear error behavior verification (glMapNamedBuffer version). */
{
(void)(glw::GLbyte*) m_pMapNamedBuffer(buffer, GL_READ_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
m_pClearNamedBufferData(buffer, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_OPERATION,
" if any part of the specified range of the buffer"
" object is mapped with MapBuffer, unless it was mapped with "
"the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags.");
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
}
/* Test of mapped buffer clear error behavior verification (glMapNamedBufferRange version). */
{
(void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
m_pClearNamedBufferData(buffer, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_OPERATION,
" if any part of the specified range of the buffer"
" object is mapped with MapBufferRange, unless it was mapped with "
"the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags.");
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
}
/* Test of persistently mapped buffer clear error with behavior verification (glMapNamedBufferRange version). */
{
(void)(glw::GLbyte*)
m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
m_pClearNamedBufferData(buffer, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_NO_ERROR,
" if any part of the specified range of the buffer"
" object is mapped with MapBuffer with the MAP_PERSISTENT_BIT"
" bit set in the MapBufferRange access flags.");
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
}
/* Test invalid format error behavior. */
{
/* Prepare for invalid format error behavior verification. */
static const glw::GLenum valid_formats[] = { GL_RED, GL_RG,
GL_RGB, GL_BGR,
GL_RGBA, GL_BGRA,
GL_RED_INTEGER, GL_RG_INTEGER,
GL_RGB_INTEGER, GL_BGR_INTEGER,
GL_RGBA_INTEGER, GL_BGRA_INTEGER,
GL_STENCIL_INDEX, GL_DEPTH_COMPONENT,
GL_DEPTH_STENCIL };
static const glw::GLenum valid_formats_last = sizeof(valid_formats) / sizeof(valid_formats[0]) - 1;
glw::GLenum invalid_format = 0;
while (&valid_formats[valid_formats_last] !=
std::find(&valid_formats[0], &valid_formats[valid_formats_last], (++invalid_format)))
;
/* Test. */
m_pClearNamedBufferData(buffer, GL_R8, invalid_format, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog(
"glClearNamedBufferData", GL_INVALID_VALUE,
" if format is not a valid format "
"(one of GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, "
"GL_RED_INTEGER, GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, GL_RGBA_INTEGER, GL_BGRA_INTEGER, "
"GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL).");
}
/* Test invalid type error behavior. */
{
/* Prepare for invalid type error behavior verification. */
static const glw::GLenum valid_types[] = { GL_RED, GL_RG,
GL_RGB, GL_BGR,
GL_RGBA, GL_BGRA,
GL_RED_INTEGER, GL_RG_INTEGER,
GL_RGB_INTEGER, GL_BGR_INTEGER,
GL_RGBA_INTEGER, GL_BGRA_INTEGER,
GL_STENCIL_INDEX, GL_DEPTH_COMPONENT,
GL_DEPTH_STENCIL };
static const glw::GLenum valid_types_last = sizeof(valid_types) / sizeof(valid_types[0]) - 1;
glw::GLenum invalid_type = 0;
while (&valid_types[valid_types_last] !=
std::find(&valid_types[0], &valid_types[valid_types_last], (++invalid_type)))
;
/* Test. */
m_pClearNamedBufferData(buffer, GL_R8, GL_RED, invalid_type, &dummy_data);
is_ok &= ErrorCheckAndLog(
"glClearNamedBufferData", GL_INVALID_VALUE,
" if format is not a valid type "
"(one of GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, "
"GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, "
"GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, "
"GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, "
"GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, "
"GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, and GL_UNSIGNED_INT_2_10_10_10_REV).");
}
}
catch (...)
{
is_ok = false;
internal_error = true;
}
if (buffer)
{
gl.deleteBuffers(1, &buffer);
buffer = 0;
}
if (internal_error)
{
throw 0;
}
return is_ok;
}
/** @brief Test Errors Of ClearNamedBufferSubData function.
*
* Check that INVALID_OPERATION is generated by ClearNamedBufferSubData
* if buffer is not the name of an existing buffer object.
*
* Check that INVALID_ENUM is generated by ClearNamedBufferSubData if
* internal format is not one of the valid sized internal formats listed in
* the table above.
*
* Check that INVALID_VALUE is generated by ClearNamedBufferSubData if
* offset or range are not multiples of the number of basic machine units
* per-element for the internal format specified by internal format. This
* value may be computed by multiplying the number of components for
* internal format from the table by the size of the base type from the
* specification table.
*
* Check that INVALID_VALUE is generated by ClearNamedBufferSubData if
* offset or size is negative, or if offset+size is greater than the value
* of BUFFER_SIZE for the buffer object.
*
* Check that INVALID_OPERATION is generated by ClearNamedBufferSubData
* if any part of the specified range of the buffer object is mapped with
* MapBufferRange or MapBuffer, unless it was mapped with the
* MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags.
*
* Check that INVALID_VALUE is generated by ClearNamedBufferSubData if format is not
* a valid format, or type is not a valid type.
*
* True if test case succeeded, false otherwise.
*/
bool ErrorsTest::TestErrorsOfClearNamedBufferSubData()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Return value. */
bool is_ok = true;
bool internal_error = false;
/* Common variables. */
glw::GLuint buffer = 0;
glw::GLubyte dummy_data[4] = {};
try
{
/* Common preparations. */
gl.createBuffers(1, &buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed.");
m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed.");
/* Test invalid buffer name error behavior. */
{
/* Prepare for invalid buffer name error behavior verification. */
glw::GLuint not_a_buffer_name = 0;
while (gl.isBuffer(++not_a_buffer_name))
;
/* Test. */
m_pClearNamedBufferSubData(not_a_buffer_name, GL_R8, 0, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE,
&dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_OPERATION,
" if buffer is not the name of an existing buffer object.");
}
/* Test invalid sized internal format error behavior. */
{
/* Prepare for invalid sized internal format error behavior verification. */
static const glw::GLenum valid_internal_formats[] = {
GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I,
GL_R8UI, GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F,
GL_RG8I, GL_RG16I, GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F,
GL_RGB32I, GL_RGB32UI, GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I,
GL_RGBA16I, GL_RGBA32I, GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI, GL_NONE
};
static const glw::GLenum valid_internal_formats_last =
sizeof(valid_internal_formats) / sizeof(valid_internal_formats[0]) - 1;
glw::GLenum invalid_internal_format = 0;
while (&valid_internal_formats[valid_internal_formats_last] !=
std::find(&valid_internal_formats[0], &valid_internal_formats[valid_internal_formats_last],
(++invalid_internal_format)))
;
/* Test. */
m_pClearNamedBufferData(buffer, invalid_internal_format, GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_ENUM,
" if internal format is not one of the valid sized internal formats "
"(GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I, GL_R8UI,"
" GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F, GL_RG8I, GL_RG16I,"
" GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F, GL_RGB32I, GL_RGB32UI,"
" GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I, GL_RGBA16I, GL_RGBA32I,"
" GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI).");
}
/* Test incorrect offset alignment error behavior. */
{
/* Test. */
m_pClearNamedBufferSubData(buffer, GL_RGBA8, sizeof(dummy_data[0]), sizeof(dummy_data), GL_RGBA,
GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE,
"if offset is not multiples of the number of basic machine units (GLubyte)"
"per-element for the internal format (GL_RGBA) specified by internal format.");
}
/* Test incorrect range alignment error behavior. */
{
m_pClearNamedBufferSubData(buffer, GL_RGBA8, 0, sizeof(dummy_data) - sizeof(dummy_data[0]), GL_RGBA,
GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE,
"if range is not multiples of the number of basic machine units (GLubyte)"
"per-element for the internal format (GL_RGBA) specified by internal format.");
}
/* Test negative offset error behavior. */
{
/* Test. */
m_pClearNamedBufferSubData(buffer, GL_R8, -1, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE, " if offset or size is negative.");
}
/* Test negative size error behavior. */
{
/* Test. */
m_pClearNamedBufferSubData(buffer, GL_R8, 0, -((glw::GLsizei)sizeof(dummy_data)), GL_RGBA, GL_UNSIGNED_BYTE,
&dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE, " if offset or size is negative.");
}
/* Test size overflow error behavior. */
{
/* Test. */
m_pClearNamedBufferSubData(buffer, GL_R8, 0, 2 * sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE,
&dummy_data);
is_ok &= ErrorCheckAndLog(
"glClearNamedBufferSubData", GL_INVALID_VALUE,
" if offset+size is greater than the value of BUFFER_SIZE for the specified buffer object.");
}
/* Test of mapped buffer clear error behavior verification (glMapNamedBuffer version). */
{
(void)(glw::GLbyte*) m_pMapNamedBuffer(buffer, GL_READ_ONLY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
m_pClearNamedBufferSubData(buffer, GL_R8, 0, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_OPERATION,
" if any part of the specified range of the buffer"
" object is mapped with MapBuffer, unless it was mapped with "
"the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags.");
m_pUnmapNamedBuffer(buffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed.");
}
/* Test of mapped buffer clear error behavior verification (glMapNamedBufferRange version). */
{
(void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed.");
m_pClearNamedBufferSubData(buffer, GL_R8, 0, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data);
is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_OPERATION,
" if any part of the specified range of the buffer"
" object is mapped with MapBufferRange, unless it was mapped with "
"the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags.");
m_pUnmapNamedBuffer(buffer);