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 */
Tests(deqp::Context & context)60 Tests::Tests(deqp::Context& context) : TestCaseGroup(context, "sync", "Sync Tests Suite")
61 {
62 }
63
64 /** @brief Sync Tests initializer. */
init()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 */
FlushCommandsTest(deqp::Context & context)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 */
iterate()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