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