1 #ifndef _GL4CBUFFERSTORAGETESTS_HPP 2 #define _GL4CBUFFERSTORAGETESTS_HPP 3 /*------------------------------------------------------------------------- 4 * OpenGL Conformance Test Suite 5 * ----------------------------- 6 * 7 * Copyright (c) 2015-2016 The Khronos Group Inc. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ /*! 22 * \file 23 * \brief 24 */ /*-------------------------------------------------------------------*/ 25 26 /** 27 * \file gl4cBufferStorageTests.hpp 28 * \brief Declares test classes for "Buffer Storage" functionality. 29 */ /*-------------------------------------------------------------------*/ 30 31 #include "glcTestCase.hpp" 32 #include "glwDefs.hpp" 33 34 namespace gl4cts 35 { 36 namespace BufferStorage 37 { 38 class Buffer; 39 40 /** Implementation of test "Errors". Description follows: 41 * 42 * Verify that proper errors are generated: 43 * - INVALID_OPERATION is generated by BufferStorage when 0 is bound to 44 * <target>; Check all targets; 45 * - INVLIAD_OPERATION is generated by BufferStorage, NamedBufferStorage and 46 * BufferData if buffer already have immutable store; 47 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when 48 * <size> is less or equal to zero; 49 * - INVLAID_VALUE is generated by BufferStorage and NamedBufferStorage when 50 * <flags> contains MAP_PERSISTENT_BIT and neither MAP_READ_BIT nor 51 * MAP_WRITE_BIT; 52 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when 53 * <flags> contains MAP_COHERENT_BIT and no MAP_PERSISTENT_BIT; 54 * - INVALID_OPERATION is generated by MapBufferRange if any of: 55 * * MAP_COHERENT_BIT, 56 * * MAP_PERSISTENT_BIT, 57 * * MAP_READ_BIT, 58 * * MAP_WRITE_BIT 59 * is included in <access> and not in buffer's storage flags; 60 * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData 61 * when buffer has immutable store but its flags does not include 62 * DYNAMIC_STORAGE. 63 **/ 64 class ErrorsTest : public deqp::TestCase 65 { 66 public: 67 /* Public methods */ 68 ErrorsTest(deqp::Context& context); ~ErrorsTest()69 virtual ~ErrorsTest() 70 { 71 } 72 73 /* Public methods inherited from TestCase */ 74 virtual tcu::TestNode::IterateResult iterate(void); 75 76 private: 77 /* Private methods */ 78 void verifyError(glw::GLenum expected_error, const glw::GLchar* error_message, bool& out_test_result); 79 }; 80 81 /** Implementation of test "GetBufferParameter". Description follows: 82 * 83 * Verify that proper values are reported for buffers with immutable store. 84 * 85 * Steps: 86 * - prepare immutable buffer with tested set of <flags>; 87 * - inspect <param> BUFFER_STORAGE_FLAGS to verify that correct flags are 88 * reported; 89 * - inspect <param> BUFFER_IMMUTABLE_STORAGE to verify that TRUE is reported; 90 * - inspect <param> BUFFER_SIZE to verify that correct value is reported; 91 * - if tested flags set allows mapping, for each valid <access> set: 92 * * execute MapBufferRange with given <access> 93 * * inspect <param> BUFFER_ACCESS_FLAGS to verify that correct values are 94 * reported; 95 * - delete buffer. 96 * 97 * Repeat steps for all valid combinations of flags for BufferStorage. 98 **/ 99 class GetBufferParameterTest : public deqp::TestCase 100 { 101 public: 102 /* Public methods */ 103 GetBufferParameterTest(deqp::Context& context); ~GetBufferParameterTest()104 virtual ~GetBufferParameterTest() 105 { 106 } 107 108 /* Public methods inherited from TestCase */ 109 virtual tcu::TestNode::IterateResult iterate(void); 110 111 private: 112 /* Private types */ 113 struct testCase 114 { 115 testCase(glw::GLenum flags, glw::GLenum access); 116 117 glw::GLenum m_flags; 118 glw::GLenum m_access; 119 }; 120 121 /* Private fields */ 122 std::vector<testCase> m_test_cases; 123 }; 124 125 /** Implementation of test "DynamicStorage". Description follows: 126 * 127 * Verify that: 128 * - server can update contents of immutable buffer when DYNAMIC_STORAGE_BIT is 129 * not set; 130 * - client cannot update contents of immutable buffer when DYNAMIC_STORAGE_BIT 131 * is not set; 132 * - client can update contents of immutable buffer when DYNAMIC_STORAGE_BIT is 133 * set. 134 * 135 * Steps: 136 * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to 137 * COPY_READ_BUFFER; 138 * - prepare 64 bytes immutable buffer filled with value 2; Do not set 139 * DYNAMIC_STORAGE_BIT for <flags>; Bind the buffer to COPY_WRITE_BUFFER; 140 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes 141 * filled with value 3; INVLIAD_OPERATION error should be generated; 142 * - inspect contents of buffer to verify it is filled with 2; 143 * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to 144 * COPY_WRITE_BUFFER; No error should be generated; 145 * - inspect contents of buffer to verify it is filled with 1; 146 * - delete buffer and create new one; This time <flags> should contain 147 * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER; 148 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes 149 * filled with value 3; No error should be generated; 150 * - inspect contents of buffer to verify it is filled with 3; 151 **/ 152 class DynamicStorageTest : public deqp::TestCase 153 { 154 public: 155 /* Public methods */ 156 DynamicStorageTest(deqp::Context& context); ~DynamicStorageTest()157 virtual ~DynamicStorageTest() 158 { 159 } 160 161 /* Public methods inherited from TestCase */ 162 virtual tcu::TestNode::IterateResult iterate(void); 163 }; 164 165 /** Implementation of test "MapPersistentBufferSubData". Description follows: 166 * 167 * Verify that buffer mapped with MAP_PERSISTENT_BIT can be used by following 168 * operations: 169 * - BufferSubData, 170 * - NamedBufferSubData. 171 * 172 * Steps: 173 * - generate buffer and prepare its storage with BufferStorage; Use following 174 * flags MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; 175 * Provide NULL as <data> and 64 as <size>; 176 * - bind buffer to ARRAY_BUFFER; 177 * - execute tested operation, to update whole buffer with incrementing values 178 * starting from 0; No error should be generated; 179 * - map buffer contents with MapBufferRange; <access> should contain 180 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as <offset> 181 * and <size>; 182 * - mapped region should contain values from 16 to 31; 183 * - execute tested operation, to update portions of buffer specified below; 184 * No error should be generated; 185 * - unmap buffer; 186 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; 187 * - execute tested operation to update regions specified below; It is expected 188 * that INVALID_OPERATION will be generated for cases that cross mapped region; 189 * No error should be generated for other cases. 190 * 191 * Repeat steps for all tested commands. 192 * 193 * Portions of buffer to be updated: 194 * 195 * * before mapped region: <offset> 0, <size> 16, 196 * * after mapped region: <offset> 32, <size> 16, 197 * * at the beginning: <offset> 8, <size> 16, 198 * * at the end: <offset> 24, <size> 16, 199 * * in the middle: <offset> 12, <size> 8; 200 **/ 201 class MapPersistentBufferSubDataTest : public deqp::TestCase 202 { 203 public: 204 /* Public methods */ 205 MapPersistentBufferSubDataTest(deqp::Context& context); ~MapPersistentBufferSubDataTest()206 virtual ~MapPersistentBufferSubDataTest() 207 { 208 } 209 210 /* Public methods inherited from TestCase */ 211 virtual tcu::TestNode::IterateResult iterate(void); 212 213 private: 214 /* Private types */ 215 struct testCase 216 { 217 glw::GLintptr m_offset; 218 glw::GLsizeiptr m_size; 219 bool m_cross_mapped_region; 220 }; 221 }; 222 223 /** Implementation of test "MapPersistentTexture". Description follows: 224 * 225 * Verify that buffer mapped with MAP_PERSISTENT_BIT can be used by following 226 * operations: 227 * - CompressedTexImage operations, 228 * - CompressedTexSubImage operations, 229 * - CompressedTextureSubImage operations, 230 * - TexImage operations, 231 * - TexSubImage operations. 232 * 233 * Steps: 234 * - generate buffer and prepare its storage with BufferStorage; Use following 235 * flags MAP_READ_BIT, MAP_WRITE_BIT and MAP_PERSISTENT_BIT; Provide data 236 * relevant for tested operation; 237 * - bind buffer to PIXEL_UNPACK_BUFFER; 238 * - prepare texture in a way that is relevant for tested operation; 239 * - execute tested operation, no error should be generated; 240 * - delete texture and prepare next one; 241 * - map buffer contents with MapBufferRange, <access> should contain 242 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; 243 * - execute tested operation, no error should be generated; 244 * - delete texture and prepare next one; 245 * - unmap buffer 246 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; 247 * - execute tested operation, INVALID_OPERATION error should be generated. 248 * 249 * Repeat steps for all tested commands. 250 **/ 251 class MapPersistentTextureTest : public deqp::TestCase 252 { 253 public: 254 /* Public methods */ 255 MapPersistentTextureTest(deqp::Context& context); 256 ~MapPersistentTextureTest()257 virtual ~MapPersistentTextureTest() 258 { 259 } 260 261 /* Public methods inherited from TestCase */ 262 virtual tcu::TestNode::IterateResult iterate(void); 263 264 private: 265 /* Private types */ 266 enum TESTED_OPERATION 267 { 268 OP_COMPRESSED_TEX_IMAGE = 0, 269 OP_COMPRESSED_TEX_SUB_IMAGE, 270 OP_COMPRESSED_TEXTURE_SUB_IMAGE, 271 OP_TEX_IMAGE, 272 OP_TEX_SUB_IMAGE, 273 274 TESTED_OPERATION_MAX 275 }; 276 277 void getCompressedInfo(); 278 const char* getOperationName(TESTED_OPERATION operation); 279 280 bool verifyTestedOperation(TESTED_OPERATION operation, Buffer& buffer, glw::GLenum expected_error); 281 282 /* Private fields */ 283 glw::GLint m_compressed_image_size; 284 glw::GLint m_compressed_internal_format; 285 }; 286 287 /** Implementation of test "MapPersistentReadPixels". Description follows: 288 * 289 * Verify that buffer mapped with MAP_PERSISTENT_BIT can be used by ReadPixels. 290 * 291 * Steps: 292 * - generate buffer and prepare its storage with BufferStorage; Use following 293 * flags MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; 294 * Provide NULL as <data> and 64 as <size>; 295 * - bind buffer to PIXEL_PACK_BUFFER; 296 * - prepare 8x8 R8UI texture filled with unique values; Attach texture to FBO; 297 * - execute ReadPixels to transfer texture contents to buffer, no error should 298 * be generated; 299 * - update contents of texture with different image; 300 * - map buffer contents with MapBufferRange, <access> should contain 301 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; 302 * - execute ReadPixels to transfer texture contents to buffer, no error should 303 * be generated; 304 * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish; 305 * - inspect contents of mapped buffer, to verify that latest data transfer was 306 * successful; 307 * - unmap buffer 308 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; 309 * - execute ReadPixels to transfer texture contents to buffer, 310 * INVALID_OPERATION error should be generated. 311 **/ 312 class MapPersistentReadPixelsTest : public deqp::TestCase 313 { 314 public: 315 /* Public methods */ 316 MapPersistentReadPixelsTest(deqp::Context& context); 317 ~MapPersistentReadPixelsTest()318 virtual ~MapPersistentReadPixelsTest() 319 { 320 } 321 322 /* Public methods inherited from TestCase */ 323 virtual tcu::TestNode::IterateResult iterate(void); 324 }; 325 326 /** Implementation of test "MapPersistentDispatch". Description follows: 327 * 328 * Test if dispatch operation can work with buffers mapped as 329 * MAP_PERSISTENT_BIT. 330 * 331 * Steps: 332 * - prepare program with compute shader that will: 333 * * calculate sum gl_GlobalInvocationID.x elements of source buffer; 334 * * store result in destination buffer at index gl_GlobalInvocationID.x; 335 * Contents of both buffers should be treated as unsigned integers; 336 * - prepare destination and source buffers as follows: 337 * * both are immutable; 338 * * both are 64 bytes long; 339 * * destination is filled with 0; 340 * * source is filled with specific unsigned integer values; 341 * * both shall have MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set; 342 * * for source MAP_WRITE_BIT flag shall be set; 343 * * for destination MAP_READ_BIT flag shall be set; 344 * - bind buffers to SHADER_STORAGE_BUFFER; 345 * - use MapBufferRange to map both buffers; <access> shall be set as follows: 346 * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both 347 * * MAP_WRITE_BIT flag shall be set for source; 348 * * MAP_READ_BIT flag shall be set for destination; 349 * - dispatch program for 16x1x1 groups; 350 * - execute Finish; 351 * - modify contents of source buffer via mapped memory; 352 * - inspect contents of destination buffer via mapped memory; It is expected 353 * that it will contain results based on original content of source buffer; 354 * - dispatch program for 16x1x1 groups; 355 * - execute Finish; 356 * - inspect contents of destination buffer via mapped memory; It is expected 357 * that it will contain results based on modified content of source buffer. 358 **/ 359 class MapPersistentDispatchTest : public deqp::TestCase 360 { 361 public: 362 /* Public methods */ 363 MapPersistentDispatchTest(deqp::Context& context); 364 365 MapPersistentDispatchTest(deqp::Context& context, const glw::GLchar* test_name, 366 const glw::GLchar* test_description); 367 ~MapPersistentDispatchTest()368 virtual ~MapPersistentDispatchTest() 369 { 370 } 371 372 /* Public methods inherited from TestCase */ 373 virtual tcu::TestNode::IterateResult iterate(void); 374 }; 375 376 /** Implementation of test "MapPersistentFlush". Description follows: 377 * 378 * Test checks if FlushMappedBufferRange works correctly with persistent mapped 379 * buffers. 380 * 381 * Modify MapPersistenDispatch in the following aspects: 382 * - drop MAP_COHERENT_BIT for source buffer; 383 * - apply FlushMappedBufferRange to ensure that modifications of source buffer 384 * are visible to server. 385 **/ 386 class MapPersistentFlushTest : public deqp::TestCase 387 { 388 public: 389 /* Public methods */ 390 MapPersistentFlushTest(deqp::Context& context); 391 ~MapPersistentFlushTest()392 virtual ~MapPersistentFlushTest() 393 { 394 } 395 396 /* Public methods inherited from TestCase */ 397 virtual tcu::TestNode::IterateResult iterate(void); 398 }; 399 400 /** Implementation of test "MapPersistentDraw". Description follows: 401 * 402 * Test if draw operation can work with buffers mapped as MAP_PERSISTENT_BIT. 403 * 404 * Steps: 405 * - prepare program consisting of vertex, geometry and fragment shader; 406 * * vertex shader should output single varying "vs_gs_index" of type uint, 407 * equal to gl_VertexID; 408 * * geometry shader should: 409 * - define single uniform buffer array "rectangles" with unspecified size; 410 * Rectangles should have two vec2 fields: position and size; 411 * - define single atomic_uint "atom_color"; 412 * - increment "atom_color" once per execution; 413 * - output a quad that is placed at rectangles[vs_gs_index].position and 414 * has size equal rectangles[vs_gs_index].size; 415 * - define output float varying "gs_fs_color" equal to "atom_color" / 255; 416 * * fragment shader should pass value of "gs_fs_color" varying to red 417 * channel of output color; 418 * - prepare FBO with 16x16 RGBA8 texture as color 0 attachment filled with 0; 419 * - prepare immutable buffer with single unsigned integer bound to 420 * "atom_color"; 421 * - prepare immutable buffer bound to "rectangles", with store for two sets of 422 * data (2 * 2 * sizeof(vec2)); 423 * - make persistent mapping of both buffers for reads and writes; 424 * - modify "rectangles" buffer via mapped memory with the following two sets 425 * * position [-0.5,-0.5], size [1.0,1.0], 426 * * position [-0.25,-0.25], size [1.5,1.5]; 427 * - modify "atom_color" buffer via mapped memory to value 1; 428 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT; 429 * - enable blending with functions ONE for both source and destination; 430 * - execute DrawArrays for two vertices; 431 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish; 432 * - inspect contents of: 433 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0), 434 * * "atom_color" - to verify that it is equal to 3; 435 * - modify "rectangles" buffer via mapped memory with the following two sets 436 * * position [-1.0,-1.0], size [0.5,0.5], 437 * * position [0.5,0.5], size [0.5,0.5]; 438 * - modify "atom_color" buffer via mapped memory to value 5; 439 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT; 440 * - execute DrawArrays for two vertices; 441 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish; 442 * - inspect contents of: 443 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0), 444 * * "atom_color" - to verify that it is equal to 7; 445 * 446 * OpenGL 4.5 Changes 447 * 448 * The OpenGL 4.5 specification changed wording from: 449 * "If MAP_COHERENT_BIT is not set and the client performs a write followed 450 * by a call to the MemoryBarrier command with the CLIENT_MAPPED_BUFFER_BARRIER_BIT set, 451 * then in subsequent commands the server will see the writes." (OpenGL 4.4, chapter 6.2) 452 * to form: 453 * "If MAP_COHERENT_BIT is not set and the client performs a write followed by 454 * a call to one of the FlushMapped*BufferRange commands with a range including 455 * the written range, then in subsequent commands the server will see the writes." 456 * (OpenGL 4.5, chapter 6.2). 457 * As a results writes to persistently mapped buffer shall be followed by FlushMapped*BufferRange 458 * not the MemoryBarrier (MemoryBarrier only synchronizes form GPU to the CPU). 459 * 460 * Steps: 461 * Change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile. 462 * 463 **/ 464 class MapPersistentDrawTest : public deqp::TestCase 465 { 466 public: 467 /* Public methods */ 468 MapPersistentDrawTest(deqp::Context& context); 469 ~MapPersistentDrawTest()470 virtual ~MapPersistentDrawTest() 471 { 472 } 473 474 /* Public methods inherited from TestCase */ 475 virtual tcu::TestNode::IterateResult iterate(void); 476 }; 477 } /* BufferStorage */ 478 479 /** Group class for Buffer Storage conformance tests */ 480 class BufferStorageTests : public deqp::TestCaseGroup 481 { 482 public: 483 /* Public methods */ 484 BufferStorageTests(deqp::Context& context); 485 ~BufferStorageTests(void)486 virtual ~BufferStorageTests(void) 487 { 488 } 489 490 virtual void init(void); 491 492 private: 493 /* Private methods */ 494 BufferStorageTests(const BufferStorageTests& other); 495 BufferStorageTests& operator=(const BufferStorageTests& other); 496 }; 497 498 } /* gl4cts */ 499 500 #endif // _GL4CBUFFERSTORAGETESTS_HPP 501