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