#ifndef _GL4CBUFFERSTORAGETESTS_HPP #define _GL4CBUFFERSTORAGETESTS_HPP /*------------------------------------------------------------------------- * OpenGL Conformance Test Suite * ----------------------------- * * Copyright (c) 2015-2016 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /*! * \file * \brief */ /*-------------------------------------------------------------------*/ /** * \file gl4cBufferStorageTests.hpp * \brief Declares test classes for "Buffer Storage" functionality. */ /*-------------------------------------------------------------------*/ #include "glcTestCase.hpp" #include "glwDefs.hpp" namespace gl4cts { namespace BufferStorage { class Buffer; /** Implementation of test "Errors". Description follows: * * Verify that proper errors are generated: * - INVALID_OPERATION is generated by BufferStorage when 0 is bound to * ; Check all targets; * - INVLIAD_OPERATION is generated by BufferStorage, NamedBufferStorage and * BufferData if buffer already have immutable store; * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when * is less or equal to zero; * - INVLAID_VALUE is generated by BufferStorage and NamedBufferStorage when * contains MAP_PERSISTENT_BIT and neither MAP_READ_BIT nor * MAP_WRITE_BIT; * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when * contains MAP_COHERENT_BIT and no MAP_PERSISTENT_BIT; * - INVALID_OPERATION is generated by MapBufferRange if any of: * * MAP_COHERENT_BIT, * * MAP_PERSISTENT_BIT, * * MAP_READ_BIT, * * MAP_WRITE_BIT * is included in and not in buffer's storage flags; * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData * when buffer has immutable store but its flags does not include * DYNAMIC_STORAGE. **/ class ErrorsTest : public deqp::TestCase { public: /* Public methods */ ErrorsTest(deqp::Context& context); virtual ~ErrorsTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private methods */ void verifyError(glw::GLenum expected_error, const glw::GLchar* error_message, bool& out_test_result); }; /** Implementation of test "GetBufferParameter". Description follows: * * Verify that proper values are reported for buffers with immutable store. * * Steps: * - prepare immutable buffer with tested set of ; * - inspect BUFFER_STORAGE_FLAGS to verify that correct flags are * reported; * - inspect BUFFER_IMMUTABLE_STORAGE to verify that TRUE is reported; * - inspect BUFFER_SIZE to verify that correct value is reported; * - if tested flags set allows mapping, for each valid set: * * execute MapBufferRange with given * * inspect BUFFER_ACCESS_FLAGS to verify that correct values are * reported; * - delete buffer. * * Repeat steps for all valid combinations of flags for BufferStorage. **/ class GetBufferParameterTest : public deqp::TestCase { public: /* Public methods */ GetBufferParameterTest(deqp::Context& context); virtual ~GetBufferParameterTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private types */ struct testCase { testCase(glw::GLenum flags, glw::GLenum access); glw::GLenum m_flags; glw::GLenum m_access; }; /* Private fields */ std::vector m_test_cases; }; /** Implementation of test "DynamicStorage". Description follows: * * Verify that: * - server can update contents of immutable buffer when DYNAMIC_STORAGE_BIT is * not set; * - client cannot update contents of immutable buffer when DYNAMIC_STORAGE_BIT * is not set; * - client can update contents of immutable buffer when DYNAMIC_STORAGE_BIT is * set. * * Steps: * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to * COPY_READ_BUFFER; * - prepare 64 bytes immutable buffer filled with value 2; Do not set * DYNAMIC_STORAGE_BIT for ; Bind the buffer to COPY_WRITE_BUFFER; * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes * filled with value 3; INVLIAD_OPERATION error should be generated; * - inspect contents of buffer to verify it is filled with 2; * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to * COPY_WRITE_BUFFER; No error should be generated; * - inspect contents of buffer to verify it is filled with 1; * - delete buffer and create new one; This time should contain * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER; * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes * filled with value 3; No error should be generated; * - inspect contents of buffer to verify it is filled with 3; **/ class DynamicStorageTest : public deqp::TestCase { public: /* Public methods */ DynamicStorageTest(deqp::Context& context); virtual ~DynamicStorageTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); }; /** Implementation of test "MapPersistentBufferSubData". Description follows: * * Verify that buffer mapped with MAP_PERSISTENT_BIT can be used by following * operations: * - BufferSubData, * - NamedBufferSubData. * * Steps: * - generate buffer and prepare its storage with BufferStorage; Use following * flags MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; * Provide NULL as and 64 as ; * - bind buffer to ARRAY_BUFFER; * - execute tested operation, to update whole buffer with incrementing values * starting from 0; No error should be generated; * - map buffer contents with MapBufferRange; should contain * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as * and ; * - mapped region should contain values from 16 to 31; * - execute tested operation, to update portions of buffer specified below; * No error should be generated; * - unmap buffer; * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; * - execute tested operation to update regions specified below; It is expected * that INVALID_OPERATION will be generated for cases that cross mapped region; * No error should be generated for other cases. * * Repeat steps for all tested commands. * * Portions of buffer to be updated: * * * before mapped region: 0, 16, * * after mapped region: 32, 16, * * at the beginning: 8, 16, * * at the end: 24, 16, * * in the middle: 12, 8; **/ class MapPersistentBufferSubDataTest : public deqp::TestCase { public: /* Public methods */ MapPersistentBufferSubDataTest(deqp::Context& context); virtual ~MapPersistentBufferSubDataTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLintptr m_offset; glw::GLsizeiptr m_size; bool m_cross_mapped_region; }; }; /** Implementation of test "MapPersistentTexture". Description follows: * * Verify that buffer mapped with MAP_PERSISTENT_BIT can be used by following * operations: * - CompressedTexImage operations, * - CompressedTexSubImage operations, * - CompressedTextureSubImage operations, * - TexImage operations, * - TexSubImage operations. * * Steps: * - generate buffer and prepare its storage with BufferStorage; Use following * flags MAP_READ_BIT, MAP_WRITE_BIT and MAP_PERSISTENT_BIT; Provide data * relevant for tested operation; * - bind buffer to PIXEL_UNPACK_BUFFER; * - prepare texture in a way that is relevant for tested operation; * - execute tested operation, no error should be generated; * - delete texture and prepare next one; * - map buffer contents with MapBufferRange, should contain * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; * - execute tested operation, no error should be generated; * - delete texture and prepare next one; * - unmap buffer * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; * - execute tested operation, INVALID_OPERATION error should be generated. * * Repeat steps for all tested commands. **/ class MapPersistentTextureTest : public deqp::TestCase { public: /* Public methods */ MapPersistentTextureTest(deqp::Context& context); virtual ~MapPersistentTextureTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private types */ enum TESTED_OPERATION { OP_COMPRESSED_TEX_IMAGE = 0, OP_COMPRESSED_TEX_SUB_IMAGE, OP_COMPRESSED_TEXTURE_SUB_IMAGE, OP_TEX_IMAGE, OP_TEX_SUB_IMAGE, TESTED_OPERATION_MAX }; void getCompressedInfo(); const char* getOperationName(TESTED_OPERATION operation); bool verifyTestedOperation(TESTED_OPERATION operation, Buffer& buffer, glw::GLenum expected_error); /* Private fields */ glw::GLint m_compressed_image_size; glw::GLint m_compressed_internal_format; }; /** Implementation of test "MapPersistentReadPixels". Description follows: * * Verify that buffer mapped with MAP_PERSISTENT_BIT can be used by ReadPixels. * * Steps: * - generate buffer and prepare its storage with BufferStorage; Use following * flags MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; * Provide NULL as and 64 as ; * - bind buffer to PIXEL_PACK_BUFFER; * - prepare 8x8 R8UI texture filled with unique values; Attach texture to FBO; * - execute ReadPixels to transfer texture contents to buffer, no error should * be generated; * - update contents of texture with different image; * - map buffer contents with MapBufferRange, should contain * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; * - execute ReadPixels to transfer texture contents to buffer, no error should * be generated; * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish; * - inspect contents of mapped buffer, to verify that latest data transfer was * successful; * - unmap buffer * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT; * - execute ReadPixels to transfer texture contents to buffer, * INVALID_OPERATION error should be generated. **/ class MapPersistentReadPixelsTest : public deqp::TestCase { public: /* Public methods */ MapPersistentReadPixelsTest(deqp::Context& context); virtual ~MapPersistentReadPixelsTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); }; /** Implementation of test "MapPersistentDispatch". Description follows: * * Test if dispatch operation can work with buffers mapped as * MAP_PERSISTENT_BIT. * * Steps: * - prepare program with compute shader that will: * * calculate sum gl_GlobalInvocationID.x elements of source buffer; * * store result in destination buffer at index gl_GlobalInvocationID.x; * Contents of both buffers should be treated as unsigned integers; * - prepare destination and source buffers as follows: * * both are immutable; * * both are 64 bytes long; * * destination is filled with 0; * * source is filled with specific unsigned integer values; * * both shall have MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set; * * for source MAP_WRITE_BIT flag shall be set; * * for destination MAP_READ_BIT flag shall be set; * - bind buffers to SHADER_STORAGE_BUFFER; * - use MapBufferRange to map both buffers; shall be set as follows: * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both * * MAP_WRITE_BIT flag shall be set for source; * * MAP_READ_BIT flag shall be set for destination; * - dispatch program for 16x1x1 groups; * - execute Finish; * - modify contents of source buffer via mapped memory; * - inspect contents of destination buffer via mapped memory; It is expected * that it will contain results based on original content of source buffer; * - dispatch program for 16x1x1 groups; * - execute Finish; * - inspect contents of destination buffer via mapped memory; It is expected * that it will contain results based on modified content of source buffer. **/ class MapPersistentDispatchTest : public deqp::TestCase { public: /* Public methods */ MapPersistentDispatchTest(deqp::Context& context); MapPersistentDispatchTest(deqp::Context& context, const glw::GLchar* test_name, const glw::GLchar* test_description); virtual ~MapPersistentDispatchTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); }; /** Implementation of test "MapPersistentFlush". Description follows: * * Test checks if FlushMappedBufferRange works correctly with persistent mapped * buffers. * * Modify MapPersistenDispatch in the following aspects: * - drop MAP_COHERENT_BIT for source buffer; * - apply FlushMappedBufferRange to ensure that modifications of source buffer * are visible to server. **/ class MapPersistentFlushTest : public deqp::TestCase { public: /* Public methods */ MapPersistentFlushTest(deqp::Context& context); virtual ~MapPersistentFlushTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); }; /** Implementation of test "MapPersistentDraw". Description follows: * * Test if draw operation can work with buffers mapped as MAP_PERSISTENT_BIT. * * Steps: * - prepare program consisting of vertex, geometry and fragment shader; * * vertex shader should output single varying "vs_gs_index" of type uint, * equal to gl_VertexID; * * geometry shader should: * - define single uniform buffer array "rectangles" with unspecified size; * Rectangles should have two vec2 fields: position and size; * - define single atomic_uint "atom_color"; * - increment "atom_color" once per execution; * - output a quad that is placed at rectangles[vs_gs_index].position and * has size equal rectangles[vs_gs_index].size; * - define output float varying "gs_fs_color" equal to "atom_color" / 255; * * fragment shader should pass value of "gs_fs_color" varying to red * channel of output color; * - prepare FBO with 16x16 RGBA8 texture as color 0 attachment filled with 0; * - prepare immutable buffer with single unsigned integer bound to * "atom_color"; * - prepare immutable buffer bound to "rectangles", with store for two sets of * data (2 * 2 * sizeof(vec2)); * - make persistent mapping of both buffers for reads and writes; * - modify "rectangles" buffer via mapped memory with the following two sets * * position [-0.5,-0.5], size [1.0,1.0], * * position [-0.25,-0.25], size [1.5,1.5]; * - modify "atom_color" buffer via mapped memory to value 1; * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT; * - enable blending with functions ONE for both source and destination; * - execute DrawArrays for two vertices; * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish; * - inspect contents of: * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0), * * "atom_color" - to verify that it is equal to 3; * - modify "rectangles" buffer via mapped memory with the following two sets * * position [-1.0,-1.0], size [0.5,0.5], * * position [0.5,0.5], size [0.5,0.5]; * - modify "atom_color" buffer via mapped memory to value 5; * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT; * - execute DrawArrays for two vertices; * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish; * - inspect contents of: * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0), * * "atom_color" - to verify that it is equal to 7; * * OpenGL 4.5 Changes * * The OpenGL 4.5 specification changed wording from: * "If MAP_COHERENT_BIT is not set and the client performs a write followed * by a call to the MemoryBarrier command with the CLIENT_MAPPED_BUFFER_BARRIER_BIT set, * then in subsequent commands the server will see the writes." (OpenGL 4.4, chapter 6.2) * to form: * "If MAP_COHERENT_BIT is not set and the client performs a write followed by * a call to one of the FlushMapped*BufferRange commands with a range including * the written range, then in subsequent commands the server will see the writes." * (OpenGL 4.5, chapter 6.2). * As a results writes to persistently mapped buffer shall be followed by FlushMapped*BufferRange * not the MemoryBarrier (MemoryBarrier only synchronizes form GPU to the CPU). * * Steps: * Change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile. * **/ class MapPersistentDrawTest : public deqp::TestCase { public: /* Public methods */ MapPersistentDrawTest(deqp::Context& context); virtual ~MapPersistentDrawTest() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); }; } /* BufferStorage */ /** Group class for Buffer Storage conformance tests */ class BufferStorageTests : public deqp::TestCaseGroup { public: /* Public methods */ BufferStorageTests(deqp::Context& context); virtual ~BufferStorageTests(void) { } virtual void init(void); private: /* Private methods */ BufferStorageTests(const BufferStorageTests& other); BufferStorageTests& operator=(const BufferStorageTests& other); }; } /* gl4cts */ #endif // _GL4CBUFFERSTORAGETESTS_HPP