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