Home | History | Annotate | Download | only in gl
      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