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 */ 53 Query(deqp::Context& context) : TestCase(context, "query", "Verifies value of MIN_MAP_BUFFER_ALIGNEMENT") 54 { 55 /* Nothing to be done */ 56 } 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 */ 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 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 **/ 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 **/ 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 **/ 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 **/ 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