1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2015-2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 /** 25 * \file gl4cSyncTests.cpp 26 * \brief Declares test classes for synchronization functionality. 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "gl4cSyncTests.hpp" 30 31 #include "deSharedPtr.hpp" 32 33 #include "gluContextInfo.hpp" 34 #include "gluDefs.hpp" 35 #include "gluPixelTransfer.hpp" 36 #include "gluStrUtil.hpp" 37 38 #include "tcuFuzzyImageCompare.hpp" 39 #include "tcuImageCompare.hpp" 40 #include "tcuRenderTarget.hpp" 41 #include "tcuSurface.hpp" 42 #include "tcuTestLog.hpp" 43 44 #include "glw.h" 45 #include "glwFunctions.hpp" 46 47 /* Timeout of the test in nanoseconds. */ 48 #define TEST_SYNC_WAIT_TIMEOUT 16000000000 49 50 namespace gl4cts 51 { 52 namespace Sync 53 { 54 /****************************************** Tests Group ***********************************************/ 55 56 /** @brief Sync Tests Group constructor. 57 * 58 * @param [in] context OpenGL context. 59 */ 60 Tests::Tests(deqp::Context& context) : TestCaseGroup(context, "sync", "Sync Tests Suite") 61 { 62 } 63 64 /** @brief Sync Tests initializer. */ 65 void Tests::init() 66 { 67 addChild(new Sync::FlushCommandsTest(m_context)); 68 } 69 70 /*************************************** Flush Commands Test *******************************************/ 71 72 /** @brief Sync Flush Commands Test constructor. 73 * 74 * @param [in] context OpenGL context. 75 */ 76 FlushCommandsTest::FlushCommandsTest(deqp::Context& context) 77 : deqp::TestCase(context, "flush_commands", "Sync Flush Commands Test") 78 { 79 /* Intentionally left blank. */ 80 } 81 82 /** @brief Iterate Sync Flush Commands Test cases. 83 * 84 * @return Iteration result. 85 */ 86 tcu::TestNode::IterateResult FlushCommandsTest::iterate() 87 { 88 /* Shortcut for GL functionality. */ 89 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 90 91 /* Get context setup. */ 92 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); 93 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); 94 95 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) 96 { 97 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); 98 99 return STOP; 100 } 101 102 /* Running tests. */ 103 bool is_ok = false; 104 bool is_error = false; 105 bool is_timeout = false; 106 107 /* Test constants. */ 108 static const glw::GLuint reference[2] = { 3, 1415927 }; 109 static const glw::GLuint reference_size = sizeof(reference); 110 111 /* Test objects. */ 112 glw::GLuint buffer_src = 0; 113 glw::GLuint buffer_dst = 0; 114 glw::GLsync sync = 0; 115 glw::GLenum error = GL_NO_ERROR; 116 117 try 118 { 119 /* Prepare buffers. */ 120 gl.createBuffers(1, &buffer_src); 121 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers have failed"); 122 gl.namedBufferData(buffer_src, reference_size, reference, GL_STATIC_COPY); 123 GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData have failed"); 124 125 gl.createBuffers(1, &buffer_dst); 126 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers have failed"); 127 gl.namedBufferStorage(buffer_dst, reference_size, NULL, 128 GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); 129 GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage have failed"); 130 131 /* Map perisistently buffer range. */ 132 glw::GLuint* data_dst = (glw::GLuint*)gl.mapNamedBufferRange( 133 buffer_dst, 0, reference_size, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); 134 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange have failed"); 135 136 /* Copy data from source to destination buffer */ 137 gl.copyNamedBufferSubData(buffer_src, buffer_dst, 0, 0, reference_size); 138 139 if (GL_NO_ERROR != (error = gl.getError())) 140 { 141 gl.unmapNamedBuffer(buffer_dst); 142 143 GLU_EXPECT_NO_ERROR(error, "glCopyNamedBufferSubData have failed"); 144 } 145 146 /* Create fence sync object. */ 147 sync = gl.fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 148 149 if (GL_NO_ERROR == (error = gl.getError())) 150 { 151 /* Wait until done. */ 152 glw::GLenum wait_result = gl.clientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, TEST_SYNC_WAIT_TIMEOUT); 153 154 /* Check for error. */ 155 if (GL_NO_ERROR == (error = gl.getError())) 156 { 157 /* Check for timeout. */ 158 if (GL_TIMEOUT_EXPIRED == wait_result) 159 { 160 m_context.getTestContext().getLog() 161 << tcu::TestLog::Message 162 << "ClientWaitSync with SYNC_FLUSH_COMMANDS_BIT flag has returned TIMEOUT_EXPIRED after " 163 << TEST_SYNC_WAIT_TIMEOUT << " nanoseconds. Potentially test may not be done in finite time " 164 "which is expected (OpenGL 4.5 Core Profile, Chapter 4.1.2)." 165 << " However this cannot be proven in finite time. Test timeouts." << tcu::TestLog::EndMessage; 166 167 is_timeout = true; 168 } /* Check for proper wait result. */ 169 else if ((GL_CONDITION_SATISFIED == wait_result) || (GL_ALREADY_SIGNALED == wait_result)) 170 { 171 /* Compare destination buffer data with reference. */ 172 if ((reference[0] == data_dst[0]) || (reference[1] == data_dst[1])) 173 { 174 is_ok = true; 175 } 176 else 177 { 178 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Result data [" << data_dst[0] 179 << ", " << data_dst[1] << "is not equal to the reference [" 180 << reference[0] << ", " << reference[1] << "]. Tests fails." 181 << tcu::TestLog::EndMessage; 182 } 183 } 184 } 185 else 186 { 187 m_context.getTestContext().getLog() 188 << tcu::TestLog::Message << "ClientWaitSync unexpectedly generated error " 189 << glu::getErrorStr(error) << ". Tests fails." << tcu::TestLog::EndMessage; 190 } 191 } 192 193 /* Unmapping. */ 194 gl.unmapNamedBuffer(buffer_dst); 195 GLU_EXPECT_NO_ERROR(error, "glUnmapNamedBuffer have failed"); 196 } 197 catch (...) 198 { 199 is_ok = false; 200 is_error = true; 201 } 202 203 /* Cleanup. */ 204 if (buffer_src) 205 { 206 gl.deleteBuffers(1, &buffer_src); 207 } 208 209 if (buffer_dst) 210 { 211 gl.deleteBuffers(1, &buffer_dst); 212 } 213 214 if (sync) 215 { 216 gl.deleteSync(sync); 217 } 218 219 /* Result's setup. */ 220 if (is_timeout) 221 { 222 m_testCtx.setTestResult( 223 QP_TEST_RESULT_TIMEOUT, 224 "Timeout (Potentially, ClientWaitSync with SYNC_FLUSH_COMMANDS does not return in finite time)."); 225 } 226 else 227 { 228 if (is_ok) 229 { 230 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 231 } 232 else 233 { 234 if (is_error) 235 { 236 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 237 } 238 else 239 { 240 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 241 } 242 } 243 } 244 245 return STOP; 246 } 247 } /* Sync namespace */ 248 } /* gl4cts namespace */ 249