• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  gl4cMapBufferAlignmentTests.cpp
26  * \brief Implements conformance tests for "Map Buffer Alignment" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cMapBufferAlignmentTests.hpp"
30 
31 #include "gluDefs.hpp"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
34 
35 #include <algorithm>
36 #include <vector>
37 
38 using namespace glw;
39 
40 namespace gl4cts
41 {
42 namespace MapBufferAlignment
43 {
44 /** Implementation of Query test, description follows:
45  *
46  * Verify that GetInteger returns at least 64 when MIN_MAP_BUFFER_ALIGNEMENT is
47  * requested.
48  **/
49 class Query : public deqp::TestCase
50 {
51 public:
52 	/* Public methods */
Query(deqp::Context & context)53 	Query(deqp::Context& context) : TestCase(context, "query", "Verifies value of MIN_MAP_BUFFER_ALIGNEMENT")
54 	{
55 		/* Nothing to be done */
56 	}
~Query()57 	virtual ~Query()
58 	{
59 		/* Nothing to be done */
60 	}
61 
62 	/** Execute test
63 	 *
64 	 * @return tcu::TestNode::STOP
65 	 **/
66 	virtual tcu::TestNode::IterateResult iterate(void);
67 
68 	static const GLint m_min_map_buffer_alignment = 64;
69 };
70 
71 /** Implementation of Functional test, description follows:
72  *
73  * Verifies that results of MapBuffer operations are as required.
74  *
75  * Steps:
76  * - prepare buffer filled with specific content;
77  * - map buffer with MapBuffer;
78  * - verify that returned data match contents of the buffer;
79  * - unmap buffer;
80  * - map buffer with MapBufferRange;
81  * - verify that returned data match contents of the buffer;
82  * - unmap buffer;
83  * - verify that pointers returned by map operations fulfil alignment
84  * requirements.
85  *
86  * Repeat steps for all valid:
87  * - <buffer> values;
88  * - <access> combinations.
89  *
90  * <offset> should be set to MIN_MAP_BUFFER_ALIGNEMENT - 1.
91  **/
92 class Functional : public deqp::TestCase
93 {
94 public:
95 	/* Public methods */
Functional(deqp::Context & context)96 	Functional(deqp::Context& context)
97 		: TestCase(context, "functional", "Verifies alignment of memory returned by MapBuffer operations")
98 	{
99 		/* Nothing to be done */
100 	}
101 
~Functional()102 	virtual ~Functional()
103 	{
104 		/* Nothing to be done */
105 	}
106 
107 	/** Execute test
108 	 *
109 	 * @return tcu::TestNode::STOP
110 	 **/
111 	virtual tcu::TestNode::IterateResult iterate(void);
112 };
113 
114 /** Execute test
115  *
116  * @return tcu::TestNode::STOP
117  **/
iterate()118 tcu::TestNode::IterateResult Query::iterate()
119 {
120 	GLint min_map_buffer_alignment = 0;
121 	bool  test_result			   = true;
122 
123 	const Functions& gl = m_context.getRenderContext().getFunctions();
124 
125 	gl.getIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &min_map_buffer_alignment);
126 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
127 
128 	if (m_min_map_buffer_alignment > min_map_buffer_alignment)
129 	{
130 		test_result = false;
131 	}
132 
133 	/* Set result */
134 	if (true == test_result)
135 	{
136 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
137 	}
138 	else
139 	{
140 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
141 	}
142 
143 	/* Done */
144 	return tcu::TestNode::STOP;
145 }
146 
147 struct BufferEnums
148 {
149 	GLenum m_target;
150 	GLenum m_max_size;
151 };
152 
153 /** Execute test
154  *
155  * @return tcu::TestNode::STOP
156  **/
iterate()157 tcu::TestNode::IterateResult Functional::iterate()
158 {
159 	static const GLenum storage_flags[] = {
160 		GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT,
161 		GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT, GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
162 		GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
163 		GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
164 		GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT,
165 		GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT,
166 		GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
167 		GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
168 		GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
169 		GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
170 		GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT,
171 		GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT,
172 		GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
173 		GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
174 		GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
175 		GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
176 		GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT,
177 		GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT,
178 		GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT |
179 			GL_MAP_WRITE_BIT,
180 	};
181 
182 	static const size_t n_storage_flags = sizeof(storage_flags) / sizeof(storage_flags[0]);
183 
184 	static const BufferEnums buffers[] = {
185 		{ GL_ARRAY_BUFFER, GL_MAX_VARYING_COMPONENTS },
186 		{ GL_ATOMIC_COUNTER_BUFFER, GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE },
187 		{ GL_COPY_READ_BUFFER, 0 },
188 		{ GL_COPY_WRITE_BUFFER, 0 },
189 		{ GL_DISPATCH_INDIRECT_BUFFER, 0 },
190 		{ GL_DRAW_INDIRECT_BUFFER, 0 },
191 		{ GL_ELEMENT_ARRAY_BUFFER, GL_MAX_ELEMENTS_INDICES },
192 		{ GL_PIXEL_PACK_BUFFER, 0 },
193 		{ GL_PIXEL_UNPACK_BUFFER, 0 },
194 		{ GL_QUERY_BUFFER, 0 },
195 		{ GL_SHADER_STORAGE_BUFFER, GL_MAX_SHADER_STORAGE_BLOCK_SIZE },
196 		{ GL_TEXTURE_BUFFER, GL_MAX_TEXTURE_BUFFER_SIZE },
197 		{ GL_TRANSFORM_FEEDBACK_BUFFER, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS },
198 		{ GL_UNIFORM_BUFFER, GL_MAX_UNIFORM_BLOCK_SIZE }
199 	};
200 	static const size_t n_buffers = sizeof(buffers) / sizeof(buffers[0]);
201 
202 	const Functions& gl = m_context.getRenderContext().getFunctions();
203 
204 	std::vector<GLubyte> buffer_data;
205 	size_t				 buffer_data_size		  = 0;
206 	GLuint				 buffer_id				  = 0;
207 	GLint				 buffer_size			  = 0;
208 	GLint				 min_map_buffer_alignment = 0;
209 	GLuint				 offset					  = 0;
210 	bool				 test_result			  = true;
211 
212 	/* Get min alignment */
213 	gl.getIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &min_map_buffer_alignment);
214 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
215 
216 	/* Prepare storage */
217 	buffer_data_size = 2 * min_map_buffer_alignment;
218 	buffer_data.resize(buffer_data_size);
219 
220 	/* Prepare data */
221 	for (size_t i = 0; i < buffer_data_size; ++i)
222 	{
223 		buffer_data[i] = (GLubyte)i;
224 	}
225 
226 	/* Run test */
227 	try
228 	{
229 		for (size_t buffer_idx = 0; buffer_idx < n_buffers; ++buffer_idx)
230 		{
231 			const BufferEnums& buffer = buffers[buffer_idx];
232 
233 			buffer_size = static_cast<GLint>(buffer_data_size);
234 
235 			/* Get max size */
236 			if (0 != buffer.m_max_size)
237 			{
238 				gl.getIntegerv(buffer.m_max_size, &buffer_size);
239 				GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
240 			}
241 
242 			switch (buffer.m_max_size)
243 			{
244 			case GL_MAX_VARYING_COMPONENTS:
245 			case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
246 				buffer_size = static_cast<glw::GLint>(buffer_size * sizeof(GLfloat));
247 				break;
248 
249 			case GL_MAX_ELEMENTS_INDICES:
250 				buffer_size = static_cast<glw::GLint>(buffer_size * sizeof(GLuint));
251 				break;
252 
253 			default:
254 				break;
255 			}
256 
257 			buffer_size = std::min(buffer_size, (GLint)buffer_data_size);
258 			offset		= std::min(buffer_size - 1, min_map_buffer_alignment - 1);
259 
260 			for (size_t set_idx = 0; set_idx < n_storage_flags; ++set_idx)
261 			{
262 				const GLenum& storage_set = storage_flags[set_idx];
263 
264 				/* Prepare buffer */
265 				gl.genBuffers(1, &buffer_id);
266 				GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
267 
268 				gl.bindBuffer(buffer.m_target, buffer_id);
269 				GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
270 
271 				gl.bufferStorage(buffer.m_target, buffer_size, &buffer_data[0], storage_set);
272 				GLU_EXPECT_NO_ERROR(gl.getError(), "BufferStorage");
273 
274 				/* Test MapBuffer */
275 				GLenum map_buffer_access = GL_READ_WRITE;
276 				if (0 == (storage_set & GL_MAP_READ_BIT))
277 				{
278 					map_buffer_access = GL_WRITE_ONLY;
279 				}
280 				else if (0 == (storage_set & GL_MAP_WRITE_BIT))
281 				{
282 					map_buffer_access = GL_READ_ONLY;
283 				}
284 
285 				GLubyte* map_buffer_ptr = (GLubyte*)gl.mapBuffer(buffer.m_target, map_buffer_access);
286 				GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
287 
288 				if (GL_WRITE_ONLY != map_buffer_access)
289 				{
290 					for (size_t i = 0; i < (size_t)buffer_size; ++i)
291 					{
292 						if (buffer_data[i] != map_buffer_ptr[i])
293 						{
294 							test_result = false;
295 							break;
296 						}
297 					}
298 				}
299 
300 				gl.unmapBuffer(buffer.m_target);
301 				GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
302 
303 				/* Test MapBufferRange */
304 				static const GLenum map_buffer_range_access_mask = GL_DYNAMIC_STORAGE_BIT | GL_CLIENT_STORAGE_BIT;
305 				GLenum				map_buffer_range_access		 = (storage_set & (~map_buffer_range_access_mask));
306 
307 				GLubyte* map_buffer_range_ptr =
308 					(GLubyte*)gl.mapBufferRange(buffer.m_target, offset, buffer_size - offset, map_buffer_range_access);
309 				GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
310 
311 				if (0 != (GL_MAP_READ_BIT & map_buffer_range_access))
312 				{
313 					for (size_t i = 0; i < (size_t)buffer_size - (size_t)offset; ++i)
314 					{
315 						if (buffer_data[i + offset] != map_buffer_range_ptr[i])
316 						{
317 							test_result = false;
318 							break;
319 						}
320 					}
321 				}
322 
323 				gl.unmapBuffer(buffer.m_target);
324 				GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
325 
326 				gl.bindBuffer(buffer.m_target, 0 /* id */);
327 				GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
328 
329 				/* Remove buffer */
330 				gl.deleteBuffers(1, &buffer_id);
331 				GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteBuffers");
332 
333 				buffer_id = 0;
334 
335 				/* Verify that pointers are properly aligned */
336 				if (0 != ((GLintptr)map_buffer_ptr % min_map_buffer_alignment))
337 				{
338 					test_result = false;
339 					break;
340 				}
341 
342 				if (0 != (((GLintptr)map_buffer_range_ptr - offset) % min_map_buffer_alignment))
343 				{
344 					test_result = false;
345 					break;
346 				}
347 			}
348 		}
349 	}
350 	catch (const std::exception& exc)
351 	{
352 		if (0 != buffer_id)
353 		{
354 			gl.deleteBuffers(1, &buffer_id);
355 			GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteBuffers");
356 		}
357 
358 		TCU_FAIL(exc.what());
359 	}
360 
361 	/* Set result */
362 	if (true == test_result)
363 	{
364 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
365 	}
366 	else
367 	{
368 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
369 	}
370 
371 	/* Done */
372 	return tcu::TestNode::STOP;
373 }
374 } /* MapBufferAlignment namespace */
375 
376 /** Constructor.
377  *
378  *  @param context Rendering context.
379  **/
MapBufferAlignmentTests(deqp::Context & context)380 MapBufferAlignmentTests::MapBufferAlignmentTests(deqp::Context& context)
381 	: TestCaseGroup(context, "map_buffer_alignment", "Verifies \"map buffer alignment\" functionality")
382 {
383 	/* Left blank on purpose */
384 }
385 
386 /** Initializes a texture_storage_multisample test group.
387  *
388  **/
init(void)389 void MapBufferAlignmentTests::init(void)
390 {
391 	addChild(new MapBufferAlignment::Query(m_context));
392 	addChild(new MapBufferAlignment::Functional(m_context));
393 }
394 
395 } /* gl4cts namespace */
396