Merge "Fix color change verification in dithering tests" into nougat-cts-dev am:...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fBufferWriteTests.cpp
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 data upload tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fBufferWriteTests.hpp"
25 #include "glsBufferTestUtil.hpp"
26 #include "tcuTestLog.hpp"
27 #include "gluStrUtil.hpp"
28 #include "deMemory.h"
29 #include "deString.h"
30 #include "deRandom.hpp"
31 #include "deStringUtil.hpp"
32 #include "deMath.h"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35
36 #include <algorithm>
37 #include <list>
38
39 using std::set;
40 using std::vector;
41 using std::string;
42 using tcu::TestLog;
43 using tcu::IVec2;
44
45 namespace deqp
46 {
47 namespace gles3
48 {
49 namespace Functional
50 {
51
52 using namespace gls::BufferTestUtil;
53
54 struct DataStoreSpec
55 {
56         DataStoreSpec (void)
57                 : target        (0)
58                 , usage         (0)
59                 , size          (0)
60         {
61         }
62
63         DataStoreSpec (deUint32 target_, deUint32 usage_, int size_)
64                 : target        (target_)
65                 , usage         (usage_)
66                 , size          (size_)
67         {
68         }
69
70         deUint32        target;
71         deUint32        usage;
72         int                     size;
73 };
74
75 struct DataStoreSpecVecBuilder
76 {
77         std::vector<DataStoreSpec>& list;
78
79         DataStoreSpecVecBuilder (std::vector<DataStoreSpec>& list_)
80                 : list(list_)
81         {
82         }
83
84         DataStoreSpecVecBuilder& operator<< (const DataStoreSpec& spec)
85         {
86                 list.push_back(spec);
87                 return *this;
88         }
89 };
90
91 struct RangeVecBuilder
92 {
93         std::vector<tcu::IVec2>& list;
94
95         RangeVecBuilder (std::vector<tcu::IVec2>& list_)
96                 : list(list_)
97         {
98         }
99
100         RangeVecBuilder& operator<< (const tcu::IVec2& vec)
101         {
102                 list.push_back(vec);
103                 return *this;
104         }
105 };
106
107 template<typename Iterator>
108 static bool isRangeListValid (Iterator begin, Iterator end)
109 {
110         if (begin != end)
111         {
112                 // Fetch first.
113                 tcu::IVec2 prev = *begin;
114                 ++begin;
115
116                 for (; begin != end; ++begin)
117                 {
118                         tcu::IVec2 cur = *begin;
119                         if (cur.x() <= prev.x() || cur.x() <= prev.x()+prev.y())
120                                 return false;
121                         prev = cur;
122                 }
123         }
124
125         return true;
126 }
127
128 inline bool rangesIntersect (const tcu::IVec2& a, const tcu::IVec2& b)
129 {
130         return de::inRange(a.x(), b.x(), b.x()+b.y()) || de::inRange(a.x()+a.y(), b.x(), b.x()+b.y()) ||
131                    de::inRange(b.x(), a.x(), a.x()+a.y()) || de::inRange(b.x()+b.y(), a.x(), a.x()+a.y());
132 }
133
134 inline tcu::IVec2 unionRanges (const tcu::IVec2& a, const tcu::IVec2& b)
135 {
136         DE_ASSERT(rangesIntersect(a, b));
137
138         int start       = de::min(a.x(), b.x());
139         int end         = de::max(a.x()+a.y(), b.x()+b.y());
140
141         return tcu::IVec2(start, end-start);
142 }
143
144 //! Updates range list (start, len) with a new range.
145 std::vector<tcu::IVec2> addRangeToList (const std::vector<tcu::IVec2>& oldList, const tcu::IVec2& newRange)
146 {
147         DE_ASSERT(newRange.y() > 0);
148
149         std::vector<tcu::IVec2>                                 newList;
150         std::vector<tcu::IVec2>::const_iterator oldListIter     = oldList.begin();
151
152         // Append ranges that end before the new range.
153         for (; oldListIter != oldList.end() && oldListIter->x()+oldListIter->y() < newRange.x(); ++oldListIter)
154                 newList.push_back(*oldListIter);
155
156         // Join any ranges that intersect new range
157         {
158                 tcu::IVec2 curRange = newRange;
159                 while (oldListIter != oldList.end() && rangesIntersect(curRange, *oldListIter))
160                 {
161                         curRange = unionRanges(curRange, *oldListIter);
162                         ++oldListIter;
163                 }
164
165                 newList.push_back(curRange);
166         }
167
168         // Append remaining ranges.
169         for (; oldListIter != oldList.end(); oldListIter++)
170                 newList.push_back(*oldListIter);
171
172         DE_ASSERT(isRangeListValid(newList.begin(), newList.end()));
173
174         return newList;
175 }
176
177 class BasicBufferDataCase : public BufferCase
178 {
179 public:
180         BasicBufferDataCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, VerifyType verify)
181                 : BufferCase    (context.getTestContext(), context.getRenderContext(), name, desc)
182                 , m_target              (target)
183                 , m_usage               (usage)
184                 , m_size                (size)
185                 , m_verify              (verify)
186         {
187         }
188
189         IterateResult iterate (void)
190         {
191                 const deUint32                  dataSeed        = deStringHash(getName()) ^ 0x125;
192                 BufferVerifier                  verifier        (m_renderCtx, m_testCtx.getLog(), m_verify);
193                 ReferenceBuffer                 refBuf;
194                 bool                                    isOk            = false;
195
196                 refBuf.setSize(m_size);
197                 fillWithRandomBytes(refBuf.getPtr(), m_size, dataSeed);
198
199                 deUint32 buf = genBuffer();
200                 glBindBuffer(m_target, buf);
201                 glBufferData(m_target, m_size, refBuf.getPtr(), m_usage);
202
203                 checkError();
204
205                 isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_size, m_target);
206
207                 deleteBuffer(buf);
208
209                 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
210                                                                 isOk ? "Pass"                           : "Buffer verification failed");
211                 return STOP;
212         }
213
214 private:
215         deUint32                m_target;
216         deUint32                m_usage;
217         int                             m_size;
218         VerifyType              m_verify;
219 };
220
221 class RecreateBufferDataStoreCase : public BufferCase
222 {
223 public:
224         RecreateBufferDataStoreCase (Context& context, const char* name, const char* desc, const DataStoreSpec* specs, int numSpecs, VerifyType verify)
225                 : BufferCase(context.getTestContext(), context.getRenderContext(), name, desc)
226                 , m_specs       (specs, specs+numSpecs)
227                 , m_verify      (verify)
228         {
229         }
230
231         IterateResult iterate (void)
232         {
233                 const deUint32                  baseSeed        = deStringHash(getName()) ^ 0xbeef;
234                 BufferVerifier                  verifier        (m_renderCtx, m_testCtx.getLog(), m_verify);
235                 ReferenceBuffer                 refBuf;
236                 const deUint32                  buf                     = genBuffer();
237
238                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
239
240                 for (vector<DataStoreSpec>::const_iterator spec = m_specs.begin(); spec != m_specs.end(); spec++)
241                 {
242                         bool iterOk = false;
243
244                         refBuf.setSize(spec->size);
245                         fillWithRandomBytes(refBuf.getPtr(), spec->size, baseSeed ^ deInt32Hash(spec->size+spec->target+spec->usage));
246
247                         glBindBuffer(spec->target, buf);
248                         glBufferData(spec->target, spec->size, refBuf.getPtr(), spec->usage);
249
250                         checkError();
251
252                         iterOk = verifier.verify(buf, refBuf.getPtr(), 0, spec->size, spec->target);
253
254                         if (!iterOk)
255                         {
256                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
257                                 break;
258                         }
259                 }
260
261                 deleteBuffer(buf);
262                 return STOP;
263         }
264
265 private:
266         std::vector<DataStoreSpec>      m_specs;
267         VerifyType                                      m_verify;
268 };
269
270 class BasicBufferSubDataCase : public BufferCase
271 {
272 public:
273         BasicBufferSubDataCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, int subDataOffs, int subDataSize, VerifyType verify)
274                 : BufferCase    (context.getTestContext(), context.getRenderContext(), name, desc)
275                 , m_target              (target)
276                 , m_usage               (usage)
277                 , m_size                (size)
278                 , m_subDataOffs (subDataOffs)
279                 , m_subDataSize (subDataSize)
280                 , m_verify              (verify)
281         {
282                 DE_ASSERT(de::inBounds(subDataOffs, 0, size) && de::inRange(subDataOffs+subDataSize, 0, size));
283         }
284
285         IterateResult iterate (void)
286         {
287                 const deUint32                  dataSeed        = deStringHash(getName());
288                 BufferVerifier                  verifier        (m_renderCtx, m_testCtx.getLog(), m_verify);
289                 ReferenceBuffer                 refBuf;
290                 bool                                    isOk            = false;
291
292                 refBuf.setSize(m_size);
293
294                 deUint32 buf = genBuffer();
295                 glBindBuffer(m_target, buf);
296
297                 // Initialize with glBufferData()
298                 fillWithRandomBytes(refBuf.getPtr(), m_size, dataSeed ^ 0x80354f);
299                 glBufferData(m_target, m_size, refBuf.getPtr(), m_usage);
300                 checkError();
301
302                 // Re-specify part of buffer
303                 fillWithRandomBytes(refBuf.getPtr()+m_subDataOffs, m_subDataSize, dataSeed ^ 0xfac425c);
304                 glBufferSubData(m_target, m_subDataOffs, m_subDataSize, refBuf.getPtr()+m_subDataOffs);
305
306                 isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_size, m_target);
307
308                 deleteBuffer(buf);
309
310                 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
311                                                                 isOk ? "Pass"                           : "Buffer verification failed");
312                 return STOP;
313         }
314
315 private:
316         deUint32                m_target;
317         deUint32                m_usage;
318         int                             m_size;
319         int                             m_subDataOffs;
320         int                             m_subDataSize;
321         VerifyType              m_verify;
322 };
323
324 class SubDataToUndefinedCase : public BufferCase
325 {
326 public:
327         SubDataToUndefinedCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, const tcu::IVec2* ranges, int numRanges, VerifyType verify)
328                 : BufferCase    (context.getTestContext(), context.getRenderContext(), name, desc)
329                 , m_target              (target)
330                 , m_usage               (usage)
331                 , m_size                (size)
332                 , m_ranges              (ranges, ranges+numRanges)
333                 , m_verify              (verify)
334         {
335         }
336
337         IterateResult iterate (void)
338         {
339                 const deUint32                  dataSeed        = deStringHash(getName());
340                 BufferVerifier                  verifier        (m_renderCtx, m_testCtx.getLog(), m_verify);
341                 ReferenceBuffer                 refBuf;
342                 bool                                    isOk            = true;
343                 std::vector<tcu::IVec2> definedRanges;
344
345                 refBuf.setSize(m_size);
346
347                 deUint32 buf = genBuffer();
348                 glBindBuffer(m_target, buf);
349
350                 // Initialize storage with glBufferData()
351                 glBufferData(m_target, m_size, DE_NULL, m_usage);
352                 checkError();
353
354                 // Fill specified ranges with glBufferSubData()
355                 for (vector<tcu::IVec2>::const_iterator range = m_ranges.begin(); range != m_ranges.end(); range++)
356                 {
357                         fillWithRandomBytes(refBuf.getPtr()+range->x(), range->y(), dataSeed ^ deInt32Hash(range->x()+range->y()));
358                         glBufferSubData(m_target, range->x(), range->y(), refBuf.getPtr()+range->x());
359
360                         // Mark range as defined
361                         definedRanges = addRangeToList(definedRanges, *range);
362                 }
363
364                 // Verify defined parts
365                 for (vector<tcu::IVec2>::const_iterator range = definedRanges.begin(); range != definedRanges.end(); range++)
366                 {
367                         if (!verifier.verify(buf, refBuf.getPtr(), range->x(), range->y(), m_target))
368                                 isOk = false;
369                 }
370
371                 deleteBuffer(buf);
372
373                 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
374                                                                 isOk ? "Pass"                           : "Buffer verification failed");
375                 return STOP;
376         }
377
378 private:
379         deUint32                                m_target;
380         deUint32                                m_usage;
381         int                                             m_size;
382         std::vector<tcu::IVec2> m_ranges;
383         VerifyType                              m_verify;
384 };
385
386 class RandomBufferWriteCase : public BufferCase
387 {
388 public:
389         RandomBufferWriteCase (Context& context, const char* name, const char* desc, deUint32 seed)
390                 : BufferCase(context.getTestContext(), context.getRenderContext(), name, desc)
391                 , m_seed                (seed)
392                 , m_verifier    (DE_NULL)
393                 , m_buffer              (0)
394                 , m_curSize             (0)
395                 , m_iterNdx             (0)
396         {
397         }
398
399         ~RandomBufferWriteCase (void)
400         {
401                 delete m_verifier;
402         }
403
404         void init (void)
405         {
406                 BufferCase::init();
407
408                 m_iterNdx       = 0;
409                 m_buffer        = genBuffer();
410                 m_curSize       = 0;
411                 m_verifier      = new BufferVerifier(m_renderCtx, m_testCtx.getLog(), VERIFY_AS_VERTEX_ARRAY);
412
413                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
414         }
415
416         void deinit (void)
417         {
418                 deleteBuffer(m_buffer);
419                 m_refBuffer.setSize(0);
420
421                 delete m_verifier;
422                 m_verifier = DE_NULL;
423
424                 BufferCase::deinit();
425         }
426
427         IterateResult iterate (void)
428         {
429                 // Parameters.
430                 const int       numIterations                           = 5;
431                 const int       uploadsPerIteration                     = 7;
432                 const int       minSize                                         = 12;
433                 const int       maxSize                                         = 32*1024;
434                 const float     respecifyProbability            = 0.07f;
435                 const float     respecifyDataProbability        = 0.2f;
436
437                 static const deUint32 bufferTargets[] =
438                 {
439                         GL_ARRAY_BUFFER,
440                         GL_COPY_READ_BUFFER,
441                         GL_COPY_WRITE_BUFFER,
442                         GL_ELEMENT_ARRAY_BUFFER,
443                         GL_PIXEL_PACK_BUFFER,
444                         GL_PIXEL_UNPACK_BUFFER,
445                         GL_TRANSFORM_FEEDBACK_BUFFER,
446                         GL_UNIFORM_BUFFER
447                 };
448
449                 static const deUint32 usageHints[] =
450                 {
451                         GL_STREAM_DRAW,
452                         GL_STREAM_READ,
453                         GL_STREAM_COPY,
454                         GL_STATIC_DRAW,
455                         GL_STATIC_READ,
456                         GL_STATIC_COPY,
457                         GL_DYNAMIC_DRAW,
458                         GL_DYNAMIC_READ,
459                         GL_DYNAMIC_COPY
460                 };
461
462                 bool            iterOk                                  = true;
463                 deUint32        curBoundTarget                  = GL_NONE;
464                 de::Random      rnd                                             (m_seed ^ deInt32Hash(m_iterNdx) ^ 0xacf92e);
465
466                 m_testCtx.getLog() << TestLog::Section(string("Iteration") + de::toString(m_iterNdx+1), string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(numIterations));
467
468                 for (int uploadNdx = 0; uploadNdx < uploadsPerIteration; uploadNdx++)
469                 {
470                         const deUint32  target          = bufferTargets[rnd.getInt(0, DE_LENGTH_OF_ARRAY(bufferTargets)-1)];
471                         const bool              respecify       = m_curSize == 0 || rnd.getFloat() < respecifyProbability;
472
473                         if (target != curBoundTarget)
474                         {
475                                 glBindBuffer(target, m_buffer);
476                                 curBoundTarget = target;
477                         }
478
479                         if (respecify)
480                         {
481                                 const int               size                    = rnd.getInt(minSize, maxSize);
482                                 const deUint32  hint                    = usageHints[rnd.getInt(0, DE_LENGTH_OF_ARRAY(usageHints)-1)];
483                                 const bool              fillWithData    = rnd.getFloat() < respecifyDataProbability;
484
485                                 m_refBuffer.setSize(size);
486                                 if (fillWithData)
487                                         fillWithRandomBytes(m_refBuffer.getPtr(), size, rnd.getUint32());
488
489                                 glBufferData(target, size, fillWithData ? m_refBuffer.getPtr() : DE_NULL, hint);
490
491                                 m_validRanges.clear();
492                                 if (fillWithData)
493                                         m_validRanges.push_back(tcu::IVec2(0, size));
494
495                                 m_curSize = size;
496                         }
497                         else
498                         {
499                                 // \note Non-uniform size distribution.
500                                 const int       size    = de::clamp(deRoundFloatToInt32((float)m_curSize * deFloatPow(rnd.getFloat(0.0f, 0.7f), 3.0f)), minSize, m_curSize);
501                                 const int       offset  = rnd.getInt(0, m_curSize-size);
502
503                                 fillWithRandomBytes(m_refBuffer.getPtr()+offset, size, rnd.getUint32());
504                                 glBufferSubData(target, offset, size, m_refBuffer.getPtr()+offset);
505
506                                 m_validRanges = addRangeToList(m_validRanges, tcu::IVec2(offset, size));
507                         }
508                 }
509
510                 // Check error.
511                 {
512                         deUint32 err = glGetError();
513                         if (err != GL_NO_ERROR)
514                                 throw tcu::TestError(string("Got ") + glu::getErrorStr(err).toString());
515                 }
516
517                 // Verify valid ranges.
518                 for (vector<IVec2>::const_iterator range = m_validRanges.begin(); range != m_validRanges.end(); range++)
519                 {
520                         const deUint32 targetHint = GL_ARRAY_BUFFER;
521                         if (!m_verifier->verify(m_buffer, m_refBuffer.getPtr(), range->x(), range->y(), targetHint))
522                         {
523                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer verification failed");
524                                 iterOk = false;
525                                 break;
526                         }
527                 }
528
529                 m_testCtx.getLog() << TestLog::EndSection;
530
531                 DE_ASSERT(iterOk || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS);
532
533                 m_iterNdx += 1;
534                 return (iterOk && m_iterNdx < numIterations) ? CONTINUE : STOP;
535         }
536
537 private:
538         deUint32                                m_seed;
539
540         BufferVerifier*                 m_verifier;
541         deUint32                                m_buffer;
542         ReferenceBuffer                 m_refBuffer;
543         std::vector<tcu::IVec2> m_validRanges;
544         int                                             m_curSize;
545         int                                             m_iterNdx;
546 };
547
548 BufferWriteTests::BufferWriteTests (Context& context)
549         : TestCaseGroup(context, "write", "Buffer data upload tests")
550 {
551 }
552
553 BufferWriteTests::~BufferWriteTests (void)
554 {
555 }
556
557 void BufferWriteTests::init (void)
558 {
559         static const deUint32 bufferTargets[] =
560         {
561                 GL_ARRAY_BUFFER,
562                 GL_COPY_READ_BUFFER,
563                 GL_COPY_WRITE_BUFFER,
564                 GL_ELEMENT_ARRAY_BUFFER,
565                 GL_PIXEL_PACK_BUFFER,
566                 GL_PIXEL_UNPACK_BUFFER,
567                 GL_TRANSFORM_FEEDBACK_BUFFER,
568                 GL_UNIFORM_BUFFER
569         };
570
571         static const deUint32 usageHints[] =
572         {
573                 GL_STREAM_DRAW,
574                 GL_STREAM_READ,
575                 GL_STREAM_COPY,
576                 GL_STATIC_DRAW,
577                 GL_STATIC_READ,
578                 GL_STATIC_COPY,
579                 GL_DYNAMIC_DRAW,
580                 GL_DYNAMIC_READ,
581                 GL_DYNAMIC_COPY
582         };
583
584         // .basic
585         {
586                 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic upload with glBufferData()");
587                 addChild(basicGroup);
588
589                 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
590                 {
591                         for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageHints); usageNdx++)
592                         {
593                                 const deUint32          target  = bufferTargets[targetNdx];
594                                 const deUint32          usage   = usageHints[usageNdx];
595                                 const int                       size    = 1020;
596                                 const VerifyType        verify  = VERIFY_AS_VERTEX_ARRAY;
597                                 const string            name    = string(getBufferTargetName(target)) + "_" + getUsageHintName(usage);
598
599                                 basicGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify));
600                         }
601                 }
602         }
603
604         // .recreate_store
605         {
606                 tcu::TestCaseGroup* const recreateStoreGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_store", "Data store recreate using glBufferData()");
607                 addChild(recreateStoreGroup);
608
609 #define RECREATE_STORE_CASE(NAME, DESC, SPECLIST)                                                                                                                                                                                                                               \
610                 do {                                                                                                                                                                                                                                                                                            \
611                         std::vector<DataStoreSpec> specs;                                                                                                                                                                                                                               \
612                         DataStoreSpecVecBuilder builder(specs);                                                                                                                                                                                                                 \
613                         builder SPECLIST;                                                                                                                                                                                                                                                               \
614                         recreateStoreGroup->addChild(new RecreateBufferDataStoreCase(m_context, #NAME, DESC, &specs[0], (int)specs.size(), VERIFY_AS_VERTEX_ARRAY));    \
615                 } while (deGetFalse())
616
617                 RECREATE_STORE_CASE(identical_1, "Recreate with identical parameters",
618                         << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996)
619                         << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996)
620                         << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996));
621
622                 RECREATE_STORE_CASE(identical_2, "Recreate with identical parameters",
623                         << DataStoreSpec(GL_COPY_WRITE_BUFFER, GL_STATIC_DRAW, 72)
624                         << DataStoreSpec(GL_COPY_WRITE_BUFFER, GL_STATIC_DRAW, 72)
625                         << DataStoreSpec(GL_COPY_WRITE_BUFFER, GL_STATIC_DRAW, 72));
626
627                 RECREATE_STORE_CASE(different_target, "Recreate with different target",
628                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STATIC_DRAW, 504)
629                         << DataStoreSpec(GL_COPY_READ_BUFFER,                   GL_STATIC_DRAW, 504)
630                         << DataStoreSpec(GL_COPY_WRITE_BUFFER,                  GL_STATIC_DRAW, 504)
631                         << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER,               GL_STATIC_DRAW, 504)
632                         << DataStoreSpec(GL_PIXEL_PACK_BUFFER,                  GL_STATIC_DRAW, 504)
633                         << DataStoreSpec(GL_PIXEL_UNPACK_BUFFER,                GL_STATIC_DRAW, 504)
634                         << DataStoreSpec(GL_TRANSFORM_FEEDBACK_BUFFER,  GL_STATIC_DRAW, 504)
635                         << DataStoreSpec(GL_UNIFORM_BUFFER,                             GL_STATIC_DRAW, 504)
636                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STATIC_DRAW, 504));
637
638                 RECREATE_STORE_CASE(different_usage, "Recreate with different usage",
639                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         1644)
640                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_COPY,         1644)
641                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STATIC_READ,         1644)
642                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_READ,         1644)
643                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_DYNAMIC_COPY,        1644)
644                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STATIC_COPY,         1644)
645                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_DYNAMIC_READ,        1644)
646                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_DYNAMIC_DRAW,        1644)
647                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STATIC_DRAW,         1644)
648                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         1644));
649
650                 RECREATE_STORE_CASE(different_size, "Recreate with different size",
651                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         1024)
652                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         12)
653                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         3327)
654                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         92)
655                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         123795)
656                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STREAM_DRAW,         571));
657
658 #undef RECREATE_STORE_CASE
659
660                 // Random cases.
661                 {
662                         const int                       numRandomCases          = 4;
663                         const int                       numUploadsPerCase       = 10;
664                         const int                       minSize                         = 12;
665                         const int                       maxSize                         = 65536;
666                         const VerifyType        verify                          = VERIFY_AS_VERTEX_ARRAY;
667                         de::Random                      rnd                                     (23921);
668
669                         for (int caseNdx = 0; caseNdx < numRandomCases; caseNdx++)
670                         {
671                                 vector<DataStoreSpec> specs(numUploadsPerCase);
672
673                                 for (vector<DataStoreSpec>::iterator spec = specs.begin(); spec != specs.end(); spec++)
674                                 {
675                                         spec->target    = bufferTargets[rnd.getInt(0, DE_LENGTH_OF_ARRAY(bufferTargets)-1)];
676                                         spec->usage             = usageHints[rnd.getInt(0, DE_LENGTH_OF_ARRAY(usageHints)-1)];
677                                         spec->size              = rnd.getInt(minSize, maxSize);
678                                 }
679
680                                 recreateStoreGroup->addChild(new RecreateBufferDataStoreCase(m_context, (string("random_") + de::toString(caseNdx+1)).c_str(), "", &specs[0], (int)specs.size(), verify));
681                         }
682                 }
683         }
684
685         // .basic_subdata
686         {
687                 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic_subdata", "Basic glBufferSubData() usage");
688                 addChild(basicGroup);
689
690                 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
691                 {
692                         for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageHints); usageNdx++)
693                         {
694                                 const deUint32          target  = bufferTargets[targetNdx];
695                                 const deUint32          usage   = usageHints[usageNdx];
696                                 const int                       size    = 1020;
697                                 const VerifyType        verify  = VERIFY_AS_VERTEX_ARRAY;
698                                 const string            name    = string(getBufferTargetName(target)) + "_" + getUsageHintName(usage);
699
700                                 basicGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify));
701                         }
702                 }
703         }
704
705         // .partial_specify
706         {
707                 tcu::TestCaseGroup* const partialSpecifyGroup = new tcu::TestCaseGroup(m_testCtx, "partial_specify", "Partial buffer data specification with glBufferSubData()");
708                 addChild(partialSpecifyGroup);
709
710 #define PARTIAL_SPECIFY_CASE(NAME, DESC, TARGET, USAGE, SIZE, RANGELIST)                                                                                                                                                                                                        \
711                 do {                                                                                                                                                                                                                                                                                                                            \
712                         std::vector<tcu::IVec2> ranges;                                                                                                                                                                                                                                                                 \
713                         RangeVecBuilder builder(ranges);                                                                                                                                                                                                                                                                \
714                         builder RANGELIST;                                                                                                                                                                                                                                                                                              \
715                         partialSpecifyGroup->addChild(new SubDataToUndefinedCase(m_context, #NAME, DESC, TARGET, USAGE, SIZE, &ranges[0], (int)ranges.size(), VERIFY_AS_VERTEX_ARRAY)); \
716                 } while (deGetFalse())
717
718                 PARTIAL_SPECIFY_CASE(whole_1, "Whole buffer specification with single glBufferSubData()", GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996,
719                         << IVec2(0, 996));
720                 PARTIAL_SPECIFY_CASE(whole_2, "Whole buffer specification with two calls", GL_UNIFORM_BUFFER, GL_DYNAMIC_READ, 1728,
721                         << IVec2(729, 999)
722                         << IVec2(0, 729));
723                 PARTIAL_SPECIFY_CASE(whole_3, "Whole buffer specification with three calls", GL_TRANSFORM_FEEDBACK_BUFFER, GL_STREAM_COPY, 1944,
724                         << IVec2(0, 421)
725                         << IVec2(1421, 523)
726                         << IVec2(421, 1000));
727                 PARTIAL_SPECIFY_CASE(whole_4, "Whole buffer specification with three calls", GL_TRANSFORM_FEEDBACK_BUFFER, GL_STREAM_COPY, 1200,
728                         << IVec2(0, 500)
729                         << IVec2(429, 200)
730                         << IVec2(513, 687));
731
732                 PARTIAL_SPECIFY_CASE(low_1, "Low part of buffer specified with single call", GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1000,
733                         << IVec2(0, 513));
734                 PARTIAL_SPECIFY_CASE(low_2, "Low part of buffer specified with two calls", GL_COPY_READ_BUFFER, GL_DYNAMIC_COPY, 996,
735                         << IVec2(0, 98)
736                         << IVec2(98, 511));
737                 PARTIAL_SPECIFY_CASE(low_3, "Low part of buffer specified with two calls", GL_COPY_READ_BUFFER, GL_DYNAMIC_COPY, 1200,
738                         << IVec2(0, 591)
739                         << IVec2(371, 400));
740
741                 PARTIAL_SPECIFY_CASE(high_1, "High part of buffer specified with single call", GL_COPY_WRITE_BUFFER, GL_STATIC_COPY, 1000,
742                         << IVec2(500, 500));
743                 PARTIAL_SPECIFY_CASE(high_2, "High part of buffer specified with two calls", GL_TRANSFORM_FEEDBACK_BUFFER, GL_STREAM_DRAW, 1200,
744                         << IVec2(600, 123)
745                         << IVec2(723, 477));
746                 PARTIAL_SPECIFY_CASE(high_3, "High part of buffer specified with two calls", GL_PIXEL_PACK_BUFFER, GL_STREAM_READ, 1200,
747                         << IVec2(600, 200)
748                         << IVec2(601, 599));
749
750                 PARTIAL_SPECIFY_CASE(middle_1, "Middle part of buffer specified with single call", GL_PIXEL_UNPACK_BUFFER, GL_STREAM_READ, 2500,
751                         << IVec2(1000, 799));
752                 PARTIAL_SPECIFY_CASE(middle_2, "Middle part of buffer specified with two calls", GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 2500,
753                         << IVec2(780, 220)
754                         << IVec2(1000, 500));
755                 PARTIAL_SPECIFY_CASE(middle_3, "Middle part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STREAM_READ, 2500,
756                         << IVec2(780, 321)
757                         << IVec2(1000, 501));
758
759 #undef PARTIAL_SPECIFY_CASE
760         }
761
762         // .random
763         {
764                 tcu::TestCaseGroup* const randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Randomized buffer data cases");
765                 addChild(randomGroup);
766
767                 for (int i = 0; i < 10; i++)
768                         randomGroup->addChild(new RandomBufferWriteCase(m_context, de::toString(i).c_str(), "", deInt32Hash(i)));
769         }
770 }
771
772 } // Functional
773 } // gles3
774 } // deqp