blob: 277db1c5c20fd07a2ac3e4f7ed55cf4e2f71f586 [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 gl4cSyncTests.cpp
* \brief Declares test classes for synchronization functionality.
*/ /*-------------------------------------------------------------------*/
#include "gl4cSyncTests.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"
/* Timeout of the test in nanoseconds. */
#define TEST_SYNC_WAIT_TIMEOUT 16000000000
namespace gl4cts
{
namespace Sync
{
/****************************************** Tests Group ***********************************************/
/** @brief Sync Tests Group constructor.
*
* @param [in] context OpenGL context.
*/
Tests::Tests(deqp::Context& context) : TestCaseGroup(context, "sync", "Sync Tests Suite")
{
}
/** @brief Sync Tests initializer. */
void Tests::init()
{
addChild(new Sync::FlushCommandsTest(m_context));
}
/*************************************** Flush Commands Test *******************************************/
/** @brief Sync Flush Commands Test constructor.
*
* @param [in] context OpenGL context.
*/
FlushCommandsTest::FlushCommandsTest(deqp::Context& context)
: deqp::TestCase(context, "flush_commands", "Sync Flush Commands Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Sync Flush Commands Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult FlushCommandsTest::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 = false;
bool is_error = false;
bool is_timeout = false;
/* Test constants. */
static const glw::GLuint reference[2] = { 3, 1415927 };
static const glw::GLuint reference_size = sizeof(reference);
/* Test objects. */
glw::GLuint buffer_src = 0;
glw::GLuint buffer_dst = 0;
glw::GLsync sync = 0;
glw::GLenum error = GL_NO_ERROR;
try
{
/* Prepare buffers. */
gl.createBuffers(1, &buffer_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers have failed");
gl.namedBufferData(buffer_src, reference_size, reference, GL_STATIC_COPY);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData have failed");
gl.createBuffers(1, &buffer_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers have failed");
gl.namedBufferStorage(buffer_dst, reference_size, NULL,
GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage have failed");
/* Map perisistently buffer range. */
glw::GLuint* data_dst = (glw::GLuint*)gl.mapNamedBufferRange(
buffer_dst, 0, reference_size, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange have failed");
/* Copy data from source to destination buffer */
gl.copyNamedBufferSubData(buffer_src, buffer_dst, 0, 0, reference_size);
if (GL_NO_ERROR != (error = gl.getError()))
{
gl.unmapNamedBuffer(buffer_dst);
GLU_EXPECT_NO_ERROR(error, "glCopyNamedBufferSubData have failed");
}
/* Create fence sync object. */
sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
if (GL_NO_ERROR == (error = gl.getError()))
{
/* Wait until done. */
glw::GLenum wait_result = gl.clientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, TEST_SYNC_WAIT_TIMEOUT);
/* Check for error. */
if (GL_NO_ERROR == (error = gl.getError()))
{
/* Check for timeout. */
if (GL_TIMEOUT_EXPIRED == wait_result)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "ClientWaitSync with SYNC_FLUSH_COMMANDS_BIT flag has returned TIMEOUT_EXPIRED after "
<< TEST_SYNC_WAIT_TIMEOUT << " nanoseconds. Potentially test may not be done in finite time "
"which is expected (OpenGL 4.5 Core Profile, Chapter 4.1.2)."
<< " However this cannot be proven in finite time. Test timeouts." << tcu::TestLog::EndMessage;
is_timeout = true;
} /* Check for proper wait result. */
else if ((GL_CONDITION_SATISFIED == wait_result) || (GL_ALREADY_SIGNALED == wait_result))
{
/* Compare destination buffer data with reference. */
if ((reference[0] == data_dst[0]) || (reference[1] == data_dst[1]))
{
is_ok = true;
}
else
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Result data [" << data_dst[0]
<< ", " << data_dst[1] << "is not equal to the reference ["
<< reference[0] << ", " << reference[1] << "]. Tests fails."
<< tcu::TestLog::EndMessage;
}
}
}
else
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ClientWaitSync unexpectedly generated error "
<< glu::getErrorStr(error) << ". Tests fails." << tcu::TestLog::EndMessage;
}
}
/* Unmapping. */
gl.unmapNamedBuffer(buffer_dst);
GLU_EXPECT_NO_ERROR(error, "glUnmapNamedBuffer have failed");
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
if (buffer_src)
{
gl.deleteBuffers(1, &buffer_src);
}
if (buffer_dst)
{
gl.deleteBuffers(1, &buffer_dst);
}
if (sync)
{
gl.deleteSync(sync);
}
/* Result's setup. */
if (is_timeout)
{
m_testCtx.setTestResult(
QP_TEST_RESULT_TIMEOUT,
"Timeout (Potentially, ClientWaitSync with SYNC_FLUSH_COMMANDS does not return in finite time).");
}
else
{
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;
}
} /* Sync namespace */
} /* gl4cts namespace */