1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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 Buffer map tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fBufferMapTests.hpp"
25 #include "glsBufferTestUtil.hpp"
26 #include "tcuTestLog.hpp"
27 #include "deMemory.h"
28 #include "deString.h"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 
32 #include <algorithm>
33 
34 using std::set;
35 using std::vector;
36 using std::string;
37 using tcu::TestLog;
38 
39 namespace deqp
40 {
41 namespace gles3
42 {
43 namespace Functional
44 {
45 
46 using namespace gls::BufferTestUtil;
47 
48 // Test cases.
49 
50 class BufferMapReadCase : public BufferCase
51 {
52 public:
BufferMapReadCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage,int bufferSize,int mapOffset,int mapSize,WriteType write)53 	BufferMapReadCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage, int bufferSize, int mapOffset, int mapSize, WriteType write)
54 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
55 		, m_bufferTarget	(bufferTarget)
56 		, m_usage			(usage)
57 		, m_bufferSize		(bufferSize)
58 		, m_mapOffset		(mapOffset)
59 		, m_mapSize			(mapSize)
60 		, m_write			(write)
61 	{
62 	}
63 
iterate(void)64 	IterateResult iterate (void)
65 	{
66 		TestLog&		log			= m_testCtx.getLog();
67 		deUint32		dataSeed	= deStringHash(getName());
68 		ReferenceBuffer	refBuf;
69 		BufferWriter	writer		(m_renderCtx, m_testCtx.getLog(), m_write);
70 		bool			isOk		= false;
71 
72 		// Setup reference data.
73 		refBuf.setSize(m_bufferSize);
74 		fillWithRandomBytes(refBuf.getPtr(), m_bufferSize, dataSeed);
75 
76 		deUint32 buf = genBuffer();
77 		glBindBuffer(m_bufferTarget, buf);
78 		glBufferData(m_bufferTarget, m_bufferSize, DE_NULL, m_usage);
79 		writer.write(buf, 0, m_bufferSize, refBuf.getPtr(), m_bufferTarget);
80 
81 		glBindBuffer(m_bufferTarget, buf);
82 		void* ptr = glMapBufferRange(m_bufferTarget, m_mapOffset, m_mapSize, GL_MAP_READ_BIT);
83 		GLU_CHECK_MSG("glMapBufferRange");
84 		TCU_CHECK(ptr);
85 
86 		isOk = compareByteArrays(log, (const deUint8*)ptr, refBuf.getPtr(m_mapOffset), m_mapSize);
87 
88 		glUnmapBuffer(m_bufferTarget);
89 		GLU_CHECK_MSG("glUnmapBuffer");
90 
91 		deleteBuffer(buf);
92 
93 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
94 								isOk ? "Pass"				: "Buffer verification failed");
95 		return STOP;
96 	}
97 
98 private:
99 	deUint32		m_bufferTarget;
100 	deUint32		m_usage;
101 	int				m_bufferSize;
102 	int				m_mapOffset;
103 	int				m_mapSize;
104 	WriteType		m_write;
105 };
106 
107 class BufferMapWriteCase : public BufferCase
108 {
109 public:
BufferMapWriteCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage,int size,VerifyType verify)110 	BufferMapWriteCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage, int size, VerifyType verify)
111 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
112 		, m_bufferTarget	(bufferTarget)
113 		, m_usage			(usage)
114 		, m_size			(size)
115 		, m_verify			(verify)
116 	{
117 	}
118 
iterate(void)119 	IterateResult iterate (void)
120 	{
121 		deUint32		dataSeed	= deStringHash(getName());
122 		ReferenceBuffer	refBuf;
123 		BufferVerifier	verifier	(m_renderCtx, m_testCtx.getLog(), m_verify);
124 
125 		// Setup reference data.
126 		refBuf.setSize(m_size);
127 		fillWithRandomBytes(refBuf.getPtr(), m_size, dataSeed);
128 
129 		deUint32 buf = genBuffer();
130 		glBindBuffer(m_bufferTarget, buf);
131 		glBufferData(m_bufferTarget, m_size, DE_NULL, m_usage);
132 
133 		void* ptr = glMapBufferRange(m_bufferTarget, 0, m_size, GL_MAP_WRITE_BIT);
134 		GLU_CHECK_MSG("glMapBufferRange");
135 		TCU_CHECK(ptr);
136 
137 		fillWithRandomBytes((deUint8*)ptr, m_size, dataSeed);
138 		glUnmapBuffer(m_bufferTarget);
139 		GLU_CHECK_MSG("glUnmapBuffer");
140 
141 		bool isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_size, m_bufferTarget);
142 		deleteBuffer(buf);
143 
144 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
145 								isOk ? "Pass"				: "Buffer verification failed");
146 		return STOP;
147 	}
148 
149 private:
150 	deUint32		m_bufferTarget;
151 	deUint32		m_usage;
152 	int				m_size;
153 	VerifyType		m_verify;
154 };
155 
156 class BufferPartialMapWriteCase : public BufferCase
157 {
158 public:
BufferPartialMapWriteCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage,int bufferSize,int mapOffset,int mapSize,VerifyType verify)159 	BufferPartialMapWriteCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage, int bufferSize, int mapOffset, int mapSize, VerifyType verify)
160 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
161 		, m_bufferTarget	(bufferTarget)
162 		, m_usage			(usage)
163 		, m_bufferSize		(bufferSize)
164 		, m_mapOffset		(mapOffset)
165 		, m_mapSize			(mapSize)
166 		, m_verify			(verify)
167 	{
168 	}
169 
iterate(void)170 	IterateResult iterate (void)
171 	{
172 		deUint32		dataSeed	= deStringHash(getName());
173 		ReferenceBuffer	refBuf;
174 		BufferVerifier	verifier	(m_renderCtx, m_testCtx.getLog(), m_verify);
175 
176 		// Setup reference data.
177 		refBuf.setSize(m_bufferSize);
178 		fillWithRandomBytes(refBuf.getPtr(), m_bufferSize, dataSeed);
179 
180 		deUint32 buf = genBuffer();
181 		glBindBuffer(m_bufferTarget, buf);
182 		glBufferData(m_bufferTarget, m_bufferSize, refBuf.getPtr(), m_usage);
183 
184 		// Do reference map.
185 		fillWithRandomBytes(refBuf.getPtr(m_mapOffset), m_mapSize, dataSeed&0xabcdef);
186 
187 		void* ptr = glMapBufferRange(m_bufferTarget, m_mapOffset, m_mapSize, GL_MAP_WRITE_BIT);
188 		GLU_CHECK_MSG("glMapBufferRange");
189 		TCU_CHECK(ptr);
190 
191 		deMemcpy(ptr, refBuf.getPtr(m_mapOffset), m_mapSize);
192 		glUnmapBuffer(m_bufferTarget);
193 		GLU_CHECK_MSG("glUnmapBuffer");
194 
195 		bool isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_bufferSize, m_bufferTarget);
196 		deleteBuffer(buf);
197 
198 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
199 								isOk ? "Pass"				: "Buffer verification failed");
200 		return STOP;
201 	}
202 
203 private:
204 	deUint32		m_bufferTarget;
205 	deUint32		m_usage;
206 	int				m_bufferSize;
207 	int				m_mapOffset;
208 	int				m_mapSize;
209 	VerifyType		m_verify;
210 };
211 
212 class BufferMapInvalidateCase : public BufferCase
213 {
214 public:
BufferMapInvalidateCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage,bool partialWrite,VerifyType verify)215 	BufferMapInvalidateCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage, bool partialWrite, VerifyType verify)
216 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
217 		, m_bufferTarget	(bufferTarget)
218 		, m_usage			(usage)
219 		, m_partialWrite	(partialWrite)
220 		, m_verify			(verify)
221 	{
222 	}
223 
iterate(void)224 	IterateResult iterate (void)
225 	{
226 		deUint32		dataSeed		= deStringHash(getName());
227 		deUint32		buf				= 0;
228 		ReferenceBuffer	refBuf;
229 		BufferVerifier	verifier		(m_renderCtx, m_testCtx.getLog(), m_verify);
230 		const int		bufferSize		= 1300;
231 		const int		mapOffset		= 200;
232 		const int		mapSize			= 1011;
233 		const int		mapWriteOffs	= m_partialWrite ? 91 : 0;
234 		const int		verifyOffset	= mapOffset+mapWriteOffs;
235 		const int		verifySize		= mapSize-mapWriteOffs;
236 
237 		// Setup reference data.
238 		refBuf.setSize(bufferSize);
239 		fillWithRandomBytes(refBuf.getPtr(), bufferSize, dataSeed);
240 
241 		buf = genBuffer();
242 		glBindBuffer(m_bufferTarget, buf);
243 		glBufferData(m_bufferTarget, bufferSize, refBuf.getPtr(), m_usage);
244 
245 		// Do reference map.
246 		fillWithRandomBytes(refBuf.getPtr(mapOffset+mapWriteOffs), mapSize-mapWriteOffs, dataSeed&0xabcdef);
247 
248 		void* ptr = glMapBufferRange(m_bufferTarget, mapOffset, mapSize, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT);
249 		GLU_CHECK_MSG("glMapBufferRange");
250 		TCU_CHECK(ptr);
251 
252 		deMemcpy((deUint8*)ptr+mapWriteOffs, refBuf.getPtr(mapOffset+mapWriteOffs), mapSize-mapWriteOffs);
253 		glUnmapBuffer(m_bufferTarget);
254 		GLU_CHECK_MSG("glUnmapBuffer");
255 
256 		bool isOk = verifier.verify(buf, refBuf.getPtr(), verifyOffset, verifySize, m_bufferTarget);
257 		deleteBuffer(buf);
258 
259 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
260 								isOk ? "Pass"				: "Buffer verification failed");
261 		return STOP;
262 	}
263 
264 private:
265 	deUint32		m_bufferTarget;
266 	deUint32		m_usage;
267 	bool			m_partialWrite;
268 	VerifyType		m_verify;
269 };
270 
271 class BufferMapPartialInvalidateCase : public BufferCase
272 {
273 public:
BufferMapPartialInvalidateCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage,bool partialWrite,VerifyType verify)274 	BufferMapPartialInvalidateCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage, bool partialWrite, VerifyType verify)
275 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
276 		, m_bufferTarget	(bufferTarget)
277 		, m_usage			(usage)
278 		, m_partialWrite	(partialWrite)
279 		, m_verify			(verify)
280 	{
281 	}
282 
iterate(void)283 	IterateResult iterate (void)
284 	{
285 		deUint32		dataSeed		= deStringHash(getName());
286 		deUint32		buf				= 0;
287 		ReferenceBuffer	refBuf;
288 		BufferVerifier	verifier		(m_renderCtx, m_testCtx.getLog(), m_verify);
289 		const int		bufferSize		= 1300;
290 		const int		mapOffset		= 200;
291 		const int		mapSize			= 1011;
292 		const int		mapWriteOffs	= m_partialWrite ? 91						: 0;
293 		const int		verifyOffset	= m_partialWrite ? mapOffset+mapWriteOffs	: 0;
294 		const int		verifySize		= bufferSize-verifyOffset;
295 
296 		// Setup reference data.
297 		refBuf.setSize(bufferSize);
298 		fillWithRandomBytes(refBuf.getPtr(), bufferSize, dataSeed);
299 
300 		buf = genBuffer();
301 		glBindBuffer(m_bufferTarget, buf);
302 		glBufferData(m_bufferTarget, bufferSize, refBuf.getPtr(), m_usage);
303 
304 		// Do reference map.
305 		fillWithRandomBytes(refBuf.getPtr(mapOffset+mapWriteOffs), mapSize-mapWriteOffs, dataSeed&0xabcdef);
306 
307 		void* ptr = glMapBufferRange(m_bufferTarget, mapOffset, mapSize, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT);
308 		GLU_CHECK_MSG("glMapBufferRange");
309 		TCU_CHECK(ptr);
310 
311 		deMemcpy((deUint8*)ptr+mapWriteOffs, refBuf.getPtr(mapOffset+mapWriteOffs), mapSize-mapWriteOffs);
312 		glUnmapBuffer(m_bufferTarget);
313 		GLU_CHECK_MSG("glUnmapBuffer");
314 
315 		bool isOk = verifier.verify(buf, refBuf.getPtr(), verifyOffset, verifySize, m_bufferTarget);
316 		deleteBuffer(buf);
317 
318 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
319 								isOk ? "Pass"				: "Buffer verification failed");
320 		return STOP;
321 	}
322 
323 private:
324 	deUint32		m_bufferTarget;
325 	deUint32		m_usage;
326 	bool			m_partialWrite;
327 	VerifyType		m_verify;
328 };
329 
330 class BufferMapExplicitFlushCase : public BufferCase
331 {
332 public:
BufferMapExplicitFlushCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage,bool partialWrite,VerifyType verify)333 	BufferMapExplicitFlushCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage, bool partialWrite, VerifyType verify)
334 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
335 		, m_bufferTarget	(bufferTarget)
336 		, m_usage			(usage)
337 		, m_partialWrite	(partialWrite)
338 		, m_verify			(verify)
339 	{
340 	}
341 
iterate(void)342 	IterateResult iterate (void)
343 	{
344 		deUint32		dataSeed		= deStringHash(getName());
345 		deUint32		buf				= 0;
346 		ReferenceBuffer	refBuf;
347 		BufferVerifier	verifier		(m_renderCtx, m_testCtx.getLog(), m_verify);
348 		const int		bufferSize		= 1300;
349 		const int		mapOffset		= 200;
350 		const int		mapSize			= 1011;
351 		const int		sliceAOffs		= m_partialWrite ? 1		: 0;
352 		const int		sliceASize		= m_partialWrite ? 96		: 473;
353 		const int		sliceBOffs		= m_partialWrite ? 503		: sliceAOffs+sliceASize;
354 		const int		sliceBSize		= mapSize-sliceBOffs;
355 		bool			isOk			= true;
356 
357 		// Setup reference data.
358 		refBuf.setSize(bufferSize);
359 		fillWithRandomBytes(refBuf.getPtr(), bufferSize, dataSeed);
360 
361 		buf = genBuffer();
362 		glBindBuffer(m_bufferTarget, buf);
363 		glBufferData(m_bufferTarget, bufferSize, refBuf.getPtr(), m_usage);
364 
365 		// Do reference map.
366 		fillWithRandomBytes(refBuf.getPtr(mapOffset), mapSize, dataSeed&0xabcdef);
367 
368 		void* ptr = glMapBufferRange(m_bufferTarget, mapOffset, mapSize, GL_MAP_WRITE_BIT|GL_MAP_FLUSH_EXPLICIT_BIT);
369 		GLU_CHECK_MSG("glMapBufferRange");
370 		TCU_CHECK(ptr);
371 
372 		deMemcpy(ptr, refBuf.getPtr(mapOffset), mapSize);
373 
374 		glFlushMappedBufferRange(m_bufferTarget, sliceAOffs, sliceASize);
375 		GLU_CHECK_MSG("glFlushMappedBufferRange");
376 		glFlushMappedBufferRange(m_bufferTarget, sliceBOffs, sliceBSize);
377 		GLU_CHECK_MSG("glFlushMappedBufferRange");
378 
379 		glUnmapBuffer(m_bufferTarget);
380 		GLU_CHECK_MSG("glUnmapBuffer");
381 
382 		if (m_partialWrite)
383 		{
384 			if (!verifier.verify(buf, refBuf.getPtr(), mapOffset+sliceAOffs, sliceASize, m_bufferTarget))
385 				isOk = false;
386 
387 			if (!verifier.verify(buf, refBuf.getPtr(), mapOffset+sliceBOffs, sliceBSize, m_bufferTarget))
388 				isOk = false;
389 		}
390 		else
391 		{
392 			if (!verifier.verify(buf, refBuf.getPtr(), mapOffset, mapSize, m_bufferTarget))
393 				isOk = false;
394 		}
395 
396 		deleteBuffer(buf);
397 
398 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
399 								isOk ? "Pass"				: "Buffer verification failed");
400 		return STOP;
401 	}
402 
403 private:
404 	deUint32		m_bufferTarget;
405 	deUint32		m_usage;
406 	bool			m_partialWrite;
407 	VerifyType		m_verify;
408 };
409 
410 class BufferMapUnsyncWriteCase : public BufferCase
411 {
412 public:
BufferMapUnsyncWriteCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage)413 	BufferMapUnsyncWriteCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage)
414 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
415 		, m_bufferTarget	(bufferTarget)
416 		, m_usage			(usage)
417 	{
418 	}
419 
iterate(void)420 	IterateResult iterate (void)
421 	{
422 		VertexArrayVerifier	verifier	(m_renderCtx, m_testCtx.getLog());
423 		deUint32			dataSeed	= deStringHash(getName());
424 		ReferenceBuffer		refBuf;
425 		deUint32			buf			= 0;
426 		bool				isOk		= true;
427 		const int			size		= 1200;
428 
429 		// Setup reference data.
430 		refBuf.setSize(size);
431 		fillWithRandomBytes(refBuf.getPtr(), size, dataSeed);
432 
433 		buf = genBuffer();
434 		glBindBuffer(m_bufferTarget, buf);
435 		glBufferData(m_bufferTarget, size, refBuf.getPtr(), m_usage);
436 
437 		// Use for rendering.
438 		if (!verifier.verify(buf, refBuf.getPtr(), 0, size))
439 			isOk = false;
440 		// \note ReadPixels() implies Finish
441 
442 		glBindBuffer(m_bufferTarget, buf);
443 		void* ptr = glMapBufferRange(m_bufferTarget, 0, size, GL_MAP_WRITE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
444 		GLU_CHECK_MSG("glMapBufferRange");
445 		TCU_CHECK(ptr);
446 
447 		fillWithRandomBytes(refBuf.getPtr(), size, dataSeed&0xabcdef);
448 		deMemcpy(ptr, refBuf.getPtr(), size);
449 
450 		glUnmapBuffer(m_bufferTarget);
451 		GLU_CHECK_MSG("glUnmapBuffer");
452 
453 		// Synchronize.
454 		glFinish();
455 
456 		if (!verifier.verify(buf, refBuf.getPtr(), 0, size))
457 			isOk = false;
458 
459 		deleteBuffer(buf);
460 
461 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
462 								isOk ? "Pass"				: "Buffer verification failed");
463 		return STOP;
464 	}
465 
466 private:
467 	deUint32		m_bufferTarget;
468 	deUint32		m_usage;
469 };
470 
471 class BufferMapReadWriteCase : public BufferCase
472 {
473 public:
BufferMapReadWriteCase(Context & context,const char * name,const char * desc,deUint32 bufferTarget,deUint32 usage,int bufferSize,int mapOffset,int mapSize,VerifyType verify)474 	BufferMapReadWriteCase (Context& context, const char* name, const char* desc, deUint32 bufferTarget, deUint32 usage, int bufferSize, int mapOffset, int mapSize, VerifyType verify)
475 		: BufferCase		(context.getTestContext(), context.getRenderContext(), name, desc)
476 		, m_bufferTarget	(bufferTarget)
477 		, m_usage			(usage)
478 		, m_bufferSize		(bufferSize)
479 		, m_mapOffset		(mapOffset)
480 		, m_mapSize			(mapSize)
481 		, m_verify			(verify)
482 	{
483 	}
484 
iterate(void)485 	IterateResult iterate (void)
486 	{
487 		TestLog&		log			= m_testCtx.getLog();
488 		deUint32		dataSeed	= deStringHash(getName());
489 		deUint32		buf			= 0;
490 		ReferenceBuffer	refBuf;
491 		BufferVerifier	verifier	(m_renderCtx, m_testCtx.getLog(), m_verify);
492 		bool			isOk		= true;
493 
494 		// Setup reference data.
495 		refBuf.setSize(m_bufferSize);
496 		fillWithRandomBytes(refBuf.getPtr(), m_bufferSize, dataSeed);
497 
498 		buf = genBuffer();
499 		glBindBuffer(m_bufferTarget, buf);
500 		glBufferData(m_bufferTarget, m_bufferSize, refBuf.getPtr(), m_usage);
501 
502 		// Verify before mapping.
503 		if (!verifier.verify(buf, refBuf.getPtr(), 0, m_bufferSize, m_bufferTarget))
504 			isOk = false;
505 
506 		glBindBuffer(m_bufferTarget, buf);
507 		void* ptr = glMapBufferRange(m_bufferTarget, m_mapOffset, m_mapSize, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
508 		GLU_CHECK_MSG("glMapBufferRange");
509 		TCU_CHECK(ptr);
510 
511 		// Compare mapped ptr.
512 		if (!compareByteArrays(log, (const deUint8*)ptr, refBuf.getPtr(m_mapOffset), m_mapSize))
513 			isOk = false;
514 
515 		fillWithRandomBytes(refBuf.getPtr(m_mapOffset), m_mapSize, dataSeed&0xabcdef);
516 		deMemcpy(ptr, refBuf.getPtr(m_mapOffset), m_mapSize);
517 
518 		glUnmapBuffer(m_bufferTarget);
519 		GLU_CHECK_MSG("glUnmapBuffer");
520 
521 		// Compare final buffer.
522 		if (!verifier.verify(buf, refBuf.getPtr(), 0, m_bufferSize, m_bufferTarget))
523 			isOk = false;
524 
525 		deleteBuffer(buf);
526 
527 		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
528 								isOk ? "Pass"				: "Buffer verification failed");
529 		return STOP;
530 	}
531 
532 private:
533 	deUint32		m_bufferTarget;
534 	deUint32		m_usage;
535 	int				m_bufferSize;
536 	int				m_mapOffset;
537 	int				m_mapSize;
538 	VerifyType		m_verify;
539 };
540 
BufferMapTests(Context & context)541 BufferMapTests::BufferMapTests (Context& context)
542 	: TestCaseGroup(context, "map", "Buffer map tests")
543 {
544 }
545 
~BufferMapTests(void)546 BufferMapTests::~BufferMapTests (void)
547 {
548 }
549 
init(void)550 void BufferMapTests::init (void)
551 {
552 	static const deUint32 bufferTargets[] =
553 	{
554 		GL_ARRAY_BUFFER,
555 		GL_COPY_READ_BUFFER,
556 		GL_COPY_WRITE_BUFFER,
557 		GL_ELEMENT_ARRAY_BUFFER,
558 		GL_PIXEL_PACK_BUFFER,
559 		GL_PIXEL_UNPACK_BUFFER,
560 		GL_TRANSFORM_FEEDBACK_BUFFER,
561 		GL_UNIFORM_BUFFER
562 	};
563 
564 	static const deUint32 usageHints[] =
565 	{
566 		GL_STREAM_DRAW,
567 		GL_STREAM_READ,
568 		GL_STREAM_COPY,
569 		GL_STATIC_DRAW,
570 		GL_STATIC_READ,
571 		GL_STATIC_COPY,
572 		GL_DYNAMIC_DRAW,
573 		GL_DYNAMIC_READ,
574 		GL_DYNAMIC_COPY
575 	};
576 
577 	static const struct
578 	{
579 		const char*		name;
580 		WriteType		write;
581 	} bufferDataSources[] =
582 	{
583 		{ "sub_data",		WRITE_BUFFER_SUB_DATA	},
584 		{ "map_write",		WRITE_BUFFER_WRITE_MAP	}
585 	};
586 
587 	static const struct
588 	{
589 		const char*		name;
590 		VerifyType		verify;
591 	} bufferUses[] =
592 	{
593 		{ "map_read",				VERIFY_BUFFER_READ_MAP	},
594 		{ "render_as_vertex_array",	VERIFY_AS_VERTEX_ARRAY	},
595 		{ "render_as_index_array",	VERIFY_AS_INDEX_ARRAY	}
596 	};
597 
598 	// .read
599 	{
600 		tcu::TestCaseGroup* mapReadGroup = new tcu::TestCaseGroup(m_testCtx, "read", "Buffer read using glMapBufferRange()");
601 		addChild(mapReadGroup);
602 
603 		// .[data src]
604 		for (int srcNdx = 0; srcNdx < DE_LENGTH_OF_ARRAY(bufferDataSources); srcNdx++)
605 		{
606 			WriteType			write		= bufferDataSources[srcNdx].write;
607 			tcu::TestCaseGroup* writeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferDataSources[srcNdx].name, "");
608 			mapReadGroup->addChild(writeGroup);
609 
610 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
611 			{
612 				deUint32		target		= bufferTargets[targetNdx];
613 				const deUint32	hint		= GL_STATIC_READ;
614 				const int		size		= 1019;
615 				const int		partialOffs	= 17;
616 				const int		partialSize	= 501;
617 
618 				writeGroup->addChild(new BufferMapReadCase(m_context, (string(getBufferTargetName(target)) + "_full").c_str(),		"", target, hint, size, 0, size, write));
619 				writeGroup->addChild(new BufferMapReadCase(m_context, (string(getBufferTargetName(target)) + "_partial").c_str(),	"", target, hint, size, partialOffs, partialSize, write));
620 			}
621 		}
622 
623 		// .usage_hints
624 		{
625 			tcu::TestCaseGroup* hintsGroup = new tcu::TestCaseGroup(m_testCtx, "usage_hints", "Different usage hints with glMapBufferRange()");
626 			mapReadGroup->addChild(hintsGroup);
627 
628 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
629 			{
630 				for (int hintNdx = 0; hintNdx < DE_LENGTH_OF_ARRAY(usageHints); hintNdx++)
631 				{
632 					deUint32		target		= bufferTargets[targetNdx];
633 					deUint32		hint		= usageHints[hintNdx];
634 					const int		size		= 1019;
635 					string			name		= string(getBufferTargetName(target)) + "_" + getUsageHintName(hint);
636 
637 					hintsGroup->addChild(new BufferMapReadCase(m_context, name.c_str(), "", target, hint, size, 0, size, WRITE_BUFFER_SUB_DATA));
638 				}
639 			}
640 		}
641 	}
642 
643 	// .write
644 	{
645 		tcu::TestCaseGroup* mapWriteGroup = new tcu::TestCaseGroup(m_testCtx, "write", "Buffer write using glMapBufferRange()");
646 		addChild(mapWriteGroup);
647 
648 		// .[verify type]
649 		for (int useNdx = 0; useNdx < DE_LENGTH_OF_ARRAY(bufferUses); useNdx++)
650 		{
651 			VerifyType			verify		= bufferUses[useNdx].verify;
652 			tcu::TestCaseGroup* useGroup	= new tcu::TestCaseGroup(m_testCtx, bufferUses[useNdx].name, "");
653 			mapWriteGroup->addChild(useGroup);
654 
655 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
656 			{
657 				deUint32		target		= bufferTargets[targetNdx];
658 				deUint32		hint		= GL_STATIC_DRAW;
659 				const int		size		= 1019;
660 				const int		partialOffs	= 17;
661 				const int		partialSize	= 501;
662 				string			name		= string(getBufferTargetName(target)) + "_" + getUsageHintName(hint);
663 
664 				useGroup->addChild(new BufferMapWriteCase			(m_context, (string(getBufferTargetName(target)) + "_full").c_str(),	"", target, hint, size, verify));
665 				useGroup->addChild(new BufferPartialMapWriteCase	(m_context, (string(getBufferTargetName(target)) + "_partial").c_str(),	"", target, hint, size, partialOffs, partialSize, verify));
666 			}
667 		}
668 
669 		// .usage_hints
670 		{
671 			tcu::TestCaseGroup* hintsGroup = new tcu::TestCaseGroup(m_testCtx, "usage_hints", "Usage hints");
672 			mapWriteGroup->addChild(hintsGroup);
673 
674 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
675 			{
676 				for (int hintNdx = 0; hintNdx < DE_LENGTH_OF_ARRAY(usageHints); hintNdx++)
677 				{
678 					deUint32		target		= bufferTargets[targetNdx];
679 					deUint32		hint		= usageHints[hintNdx];
680 					const int		size		= 1019;
681 					string			name		= string(getBufferTargetName(target)) + "_" + getUsageHintName(hint);
682 
683 					hintsGroup->addChild(new BufferMapWriteCase(m_context, name.c_str(), "", target, hint, size, VERIFY_AS_VERTEX_ARRAY));
684 				}
685 			}
686 		}
687 
688 		// .invalidate
689 		{
690 			tcu::TestCaseGroup* invalidateGroup = new tcu::TestCaseGroup(m_testCtx, "invalidate", "Buffer invalidate");
691 			mapWriteGroup->addChild(invalidateGroup);
692 
693 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
694 			{
695 				deUint32		target		= bufferTargets[targetNdx];
696 				deUint32		hint		= GL_STATIC_DRAW;
697 
698 				invalidateGroup->addChild(new BufferMapInvalidateCase(m_context, (string(getBufferTargetName(target)) + "_write_all").c_str(),		"", target, hint, false,	VERIFY_AS_VERTEX_ARRAY));
699 				invalidateGroup->addChild(new BufferMapInvalidateCase(m_context, (string(getBufferTargetName(target)) + "_write_partial").c_str(),	"", target, hint, true,		VERIFY_AS_VERTEX_ARRAY));
700 			}
701 		}
702 
703 		// .partial_invalidate
704 		{
705 			tcu::TestCaseGroup* invalidateGroup = new tcu::TestCaseGroup(m_testCtx, "partial_invalidate", "Partial invalidate");
706 			mapWriteGroup->addChild(invalidateGroup);
707 
708 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
709 			{
710 				deUint32		target		= bufferTargets[targetNdx];
711 				deUint32		hint		= GL_STATIC_DRAW;
712 
713 				invalidateGroup->addChild(new BufferMapPartialInvalidateCase(m_context, (string(getBufferTargetName(target)) + "_write_all").c_str(),		"", target, hint, false,	VERIFY_AS_VERTEX_ARRAY));
714 				invalidateGroup->addChild(new BufferMapPartialInvalidateCase(m_context, (string(getBufferTargetName(target)) + "_write_partial").c_str(),	"", target, hint, true,		VERIFY_AS_VERTEX_ARRAY));
715 			}
716 		}
717 
718 		// .explicit_flush
719 		{
720 			tcu::TestCaseGroup* flushGroup = new tcu::TestCaseGroup(m_testCtx, "explicit_flush", "Explicit flush");
721 			mapWriteGroup->addChild(flushGroup);
722 
723 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
724 			{
725 				deUint32		target		= bufferTargets[targetNdx];
726 				deUint32		hint		= GL_STATIC_DRAW;
727 
728 				flushGroup->addChild(new BufferMapExplicitFlushCase(m_context, (string(getBufferTargetName(target)) + "_all").c_str(),		"", target, hint, false,	VERIFY_AS_VERTEX_ARRAY));
729 				flushGroup->addChild(new BufferMapExplicitFlushCase(m_context, (string(getBufferTargetName(target)) + "_partial").c_str(),	"", target, hint, true,		VERIFY_AS_VERTEX_ARRAY));
730 			}
731 		}
732 
733 		// .unsynchronized
734 		{
735 			tcu::TestCaseGroup* unsyncGroup = new tcu::TestCaseGroup(m_testCtx, "unsynchronized", "Unsynchronized map");
736 			mapWriteGroup->addChild(unsyncGroup);
737 
738 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
739 			{
740 				deUint32		target		= bufferTargets[targetNdx];
741 				deUint32		hint		= GL_STATIC_DRAW;
742 
743 				unsyncGroup->addChild(new BufferMapUnsyncWriteCase(m_context, getBufferTargetName(target),	"", target, hint));
744 			}
745 		}
746 	}
747 
748 	// .read_write
749 	{
750 		tcu::TestCaseGroup* mapReadWriteGroup = new tcu::TestCaseGroup(m_testCtx, "read_write", "Buffer read and write using glMapBufferRange()");
751 		addChild(mapReadWriteGroup);
752 
753 		// .[verify type]
754 		for (int useNdx = 0; useNdx < DE_LENGTH_OF_ARRAY(bufferUses); useNdx++)
755 		{
756 			VerifyType			verify		= bufferUses[useNdx].verify;
757 			tcu::TestCaseGroup* useGroup	= new tcu::TestCaseGroup(m_testCtx, bufferUses[useNdx].name, "");
758 			mapReadWriteGroup->addChild(useGroup);
759 
760 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
761 			{
762 				deUint32		target		= bufferTargets[targetNdx];
763 				deUint32		hint		= GL_STATIC_DRAW;
764 				const int		size		= 1019;
765 				const int		partialOffs	= 17;
766 				const int		partialSize	= 501;
767 				string			name		= string(getBufferTargetName(target)) + "_" + getUsageHintName(hint);
768 
769 				useGroup->addChild(new BufferMapReadWriteCase(m_context, (string(getBufferTargetName(target)) + "_full").c_str(),		"", target, hint, size, 0, size, verify));
770 				useGroup->addChild(new BufferMapReadWriteCase(m_context, (string(getBufferTargetName(target)) + "_partial").c_str(),	"", target, hint, size, partialOffs, partialSize, verify));
771 			}
772 		}
773 
774 		// .usage_hints
775 		{
776 			tcu::TestCaseGroup* hintsGroup = new tcu::TestCaseGroup(m_testCtx, "usage_hints", "Usage hints");
777 			mapReadWriteGroup->addChild(hintsGroup);
778 
779 			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
780 			{
781 				for (int hintNdx = 0; hintNdx < DE_LENGTH_OF_ARRAY(usageHints); hintNdx++)
782 				{
783 					deUint32		target		= bufferTargets[targetNdx];
784 					deUint32		hint		= usageHints[hintNdx];
785 					const int		size		= 1019;
786 					string			name		= string(getBufferTargetName(target)) + "_" + getUsageHintName(hint);
787 
788 					hintsGroup->addChild(new BufferMapReadWriteCase(m_context, name.c_str(), "", target, hint, size, 0, size, VERIFY_AS_VERTEX_ARRAY));
789 				}
790 			}
791 		}
792 	}
793 }
794 
795 } // Functional
796 } // gles3
797 } // deqp
798