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