Add new framebuffer fetch extension tests am: 2a609fb223
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / functional / es2fBufferWriteTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.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 "es2fBufferWriteTests.hpp"
25 #include "es2fBufferTestUtil.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 gles2
48 {
49 namespace Functional
50 {
51
52 using namespace 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, 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_context, 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);
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, 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_context, 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);
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, 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_context, 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);
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, 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_context, 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()))
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, 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_context, 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_ELEMENT_ARRAY_BUFFER
441                 };
442
443                 static const deUint32 usageHints[] =
444                 {
445                         GL_STREAM_DRAW,
446                         GL_STATIC_DRAW,
447                         GL_DYNAMIC_DRAW,
448                 };
449
450                 bool            iterOk                                  = true;
451                 deUint32        curBoundTarget                  = GL_NONE;
452                 de::Random      rnd                                             (m_seed ^ deInt32Hash(m_iterNdx) ^ 0xacf92e);
453
454                 m_testCtx.getLog() << TestLog::Section(string("Iteration") + de::toString(m_iterNdx+1), string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(numIterations));
455
456                 for (int uploadNdx = 0; uploadNdx < uploadsPerIteration; uploadNdx++)
457                 {
458                         const deUint32  target          = bufferTargets[rnd.getInt(0, DE_LENGTH_OF_ARRAY(bufferTargets)-1)];
459                         const bool              respecify       = m_curSize == 0 || rnd.getFloat() < respecifyProbability;
460
461                         if (target != curBoundTarget)
462                         {
463                                 glBindBuffer(target, m_buffer);
464                                 curBoundTarget = target;
465                         }
466
467                         if (respecify)
468                         {
469                                 const int               size                    = rnd.getInt(minSize, maxSize);
470                                 const deUint32  hint                    = usageHints[rnd.getInt(0, DE_LENGTH_OF_ARRAY(usageHints)-1)];
471                                 const bool              fillWithData    = rnd.getFloat() < respecifyDataProbability;
472
473                                 m_refBuffer.setSize(size);
474                                 if (fillWithData)
475                                         fillWithRandomBytes(m_refBuffer.getPtr(), size, rnd.getUint32());
476
477                                 glBufferData(target, size, fillWithData ? m_refBuffer.getPtr() : DE_NULL, hint);
478
479                                 m_validRanges.clear();
480                                 if (fillWithData)
481                                         m_validRanges.push_back(tcu::IVec2(0, size));
482
483                                 m_curSize = size;
484                         }
485                         else
486                         {
487                                 // \note Non-uniform size distribution.
488                                 const int       size    = de::clamp(deRoundFloatToInt32((float)m_curSize * deFloatPow(rnd.getFloat(0.0f, 0.7f), 3.0f)), minSize, m_curSize);
489                                 const int       offset  = rnd.getInt(0, m_curSize-size);
490
491                                 fillWithRandomBytes(m_refBuffer.getPtr()+offset, size, rnd.getUint32());
492                                 glBufferSubData(target, offset, size, m_refBuffer.getPtr()+offset);
493
494                                 m_validRanges = addRangeToList(m_validRanges, tcu::IVec2(offset, size));
495                         }
496                 }
497
498                 // Check error.
499                 {
500                         deUint32 err = glGetError();
501                         if (err != GL_NO_ERROR)
502                                 throw tcu::TestError(string("Got ") + glu::getErrorStr(err).toString());
503                 }
504
505                 // Verify valid ranges.
506                 for (vector<IVec2>::const_iterator range = m_validRanges.begin(); range != m_validRanges.end(); range++)
507                 {
508                         if (!m_verifier->verify(m_buffer, m_refBuffer.getPtr(), range->x(), range->y()))
509                         {
510                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer verification failed");
511                                 iterOk = false;
512                                 break;
513                         }
514                 }
515
516                 m_testCtx.getLog() << TestLog::EndSection;
517
518                 DE_ASSERT(iterOk || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS);
519
520                 m_iterNdx += 1;
521                 return (iterOk && m_iterNdx < numIterations) ? CONTINUE : STOP;
522         }
523
524 private:
525         deUint32                                m_seed;
526
527         BufferVerifier*                 m_verifier;
528         deUint32                                m_buffer;
529         ReferenceBuffer                 m_refBuffer;
530         std::vector<tcu::IVec2> m_validRanges;
531         int                                             m_curSize;
532         int                                             m_iterNdx;
533 };
534
535 BufferWriteTests::BufferWriteTests (Context& context)
536         : TestCaseGroup(context, "write", "Buffer data upload tests")
537 {
538 }
539
540 BufferWriteTests::~BufferWriteTests (void)
541 {
542 }
543
544 void BufferWriteTests::init (void)
545 {
546         static const deUint32 bufferTargets[] =
547         {
548                 GL_ARRAY_BUFFER,
549                 GL_ELEMENT_ARRAY_BUFFER
550         };
551
552         static const deUint32 usageHints[] =
553         {
554                 GL_STREAM_DRAW,
555                 GL_STATIC_DRAW,
556                 GL_DYNAMIC_DRAW
557         };
558
559         static const struct
560         {
561                 const char*     name;
562                 VerifyType      verify;
563         } verifyTypes[] =
564         {
565                 { "vertex_array",       VERIFY_AS_VERTEX_ARRAY  },
566                 { "index_array",        VERIFY_AS_INDEX_ARRAY   }
567         };
568
569         // .basic
570         {
571                 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic upload with glBufferData()");
572                 addChild(basicGroup);
573
574                 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
575                 {
576                         for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageHints); usageNdx++)
577                         {
578                                 const deUint32          target  = bufferTargets[targetNdx];
579                                 const deUint32          usage   = usageHints[usageNdx];
580                                 const int                       size    = 1020;
581                                 const VerifyType        verify  = VERIFY_AS_VERTEX_ARRAY;
582                                 const string            name    = string(getBufferTargetName(target)) + "_" + getUsageHintName(usage);
583
584                                 basicGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify));
585                         }
586                 }
587         }
588
589         // .use
590         {
591                 tcu::TestCaseGroup* const useGroup = new tcu::TestCaseGroup(m_testCtx, "use", "Buffer uses");
592                 addChild(useGroup);
593
594                 for (int verifyNdx = 0; verifyNdx < DE_LENGTH_OF_ARRAY(verifyTypes); verifyNdx++)
595                 {
596                         tcu::TestCaseGroup* const verifyGroup = new tcu::TestCaseGroup(m_testCtx, verifyTypes[verifyNdx].name, "");
597                         useGroup->addChild(verifyGroup);
598
599                         for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
600                         {
601                                 const deUint32          target  = bufferTargets[targetNdx];
602                                 const deUint32          usage   = GL_STATIC_DRAW;
603                                 const int                       size    = 763;
604                                 const VerifyType        verify  = verifyTypes[verifyNdx].verify;
605                                 const string            name    = getBufferTargetName(target);
606
607                                 verifyGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify));
608                         }
609                 }
610         }
611
612         // .recreate_store
613         {
614                 tcu::TestCaseGroup* const recreateStoreGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_store", "Data store recreate using glBufferData()");
615                 addChild(recreateStoreGroup);
616
617 #define RECREATE_STORE_CASE(NAME, DESC, SPECLIST)                                                                                                                                                                                                                       \
618                 do {                                                                                                                                                                                                                                                                                            \
619                         std::vector<DataStoreSpec> specs;                                                                                                                                                                                                                               \
620                         DataStoreSpecVecBuilder builder(specs);                                                                                                                                                                                                                 \
621                         builder SPECLIST;                                                                                                                                                                                                                                                               \
622                         recreateStoreGroup->addChild(new RecreateBufferDataStoreCase(m_context, #NAME, DESC, &specs[0], (int)specs.size(), VERIFY_AS_VERTEX_ARRAY));    \
623                 } while (deGetFalse())
624
625                 RECREATE_STORE_CASE(identical_1, "Recreate with identical parameters",
626                         << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996)
627                         << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996)
628                         << DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996));
629
630                 RECREATE_STORE_CASE(identical_2, "Recreate with identical parameters",
631                         << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72)
632                         << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72)
633                         << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72));
634
635                 RECREATE_STORE_CASE(different_target_1, "Recreate with different target",
636                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STATIC_DRAW, 504)
637                         << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER,               GL_STATIC_DRAW, 504));
638
639                 RECREATE_STORE_CASE(different_target_2, "Recreate with different target",
640                         << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER,               GL_STATIC_DRAW, 716)
641                         << DataStoreSpec(GL_ARRAY_BUFFER,                               GL_STATIC_DRAW, 716)
642                         << DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER,               GL_STATIC_DRAW, 716));
643
644                 RECREATE_STORE_CASE(different_usage, "Recreate with different usage",
645                         << DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,       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,       12379)
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_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1728,
721                         << IVec2(729, 999)
722                         << IVec2(0, 729));
723                 PARTIAL_SPECIFY_CASE(whole_3, "Whole buffer specification with three calls", GL_ARRAY_BUFFER, GL_STREAM_DRAW, 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_ELEMENT_ARRAY_BUFFER, GL_STREAM_DRAW, 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_STATIC_DRAW, 1000,
733                         << IVec2(0, 513));
734                 PARTIAL_SPECIFY_CASE(low_2, "Low part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996,
735                         << IVec2(0, 98)
736                         << IVec2(98, 511));
737                 PARTIAL_SPECIFY_CASE(low_3, "Low part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 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_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 1000,
742                         << IVec2(500, 500));
743                 PARTIAL_SPECIFY_CASE(high_2, "High part of buffer specified with two calls", GL_ARRAY_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_ARRAY_BUFFER, GL_STREAM_DRAW, 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_ELEMENT_ARRAY_BUFFER, GL_STREAM_DRAW, 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_DYNAMIC_DRAW, 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 } // gles2
774 } // deqp