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
34using std::set;
35using std::vector;
36using std::string;
37using tcu::TestLog;
38
39namespace deqp
40{
41namespace gles3
42{
43namespace Functional
44{
45
46using namespace gls::BufferTestUtil;
47
48// Test cases.
49
50class BufferMapReadCase : public BufferCase
51{
52public:
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
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
98private:
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
107class BufferMapWriteCase : public BufferCase
108{
109public:
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
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
149private:
150	deUint32		m_bufferTarget;
151	deUint32		m_usage;
152	int				m_size;
153	VerifyType		m_verify;
154};
155
156class BufferPartialMapWriteCase : public BufferCase
157{
158public:
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
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
203private:
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
212class BufferMapInvalidateCase : public BufferCase
213{
214public:
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
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
264private:
265	deUint32		m_bufferTarget;
266	deUint32		m_usage;
267	bool			m_partialWrite;
268	VerifyType		m_verify;
269};
270
271class BufferMapPartialInvalidateCase : public BufferCase
272{
273public:
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
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
323private:
324	deUint32		m_bufferTarget;
325	deUint32		m_usage;
326	bool			m_partialWrite;
327	VerifyType		m_verify;
328};
329
330class BufferMapExplicitFlushCase : public BufferCase
331{
332public:
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
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
403private:
404	deUint32		m_bufferTarget;
405	deUint32		m_usage;
406	bool			m_partialWrite;
407	VerifyType		m_verify;
408};
409
410class BufferMapUnsyncWriteCase : public BufferCase
411{
412public:
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
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
466private:
467	deUint32		m_bufferTarget;
468	deUint32		m_usage;
469};
470
471class BufferMapReadWriteCase : public BufferCase
472{
473public:
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
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
532private:
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
541BufferMapTests::BufferMapTests (Context& context)
542	: TestCaseGroup(context, "map", "Buffer map tests")
543{
544}
545
546BufferMapTests::~BufferMapTests (void)
547{
548}
549
550void 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