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 test utilities.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fBufferTestUtil.hpp"
25 #include "tcuRandomValueIterator.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuImageCompare.hpp"
28 #include "tcuVector.hpp"
29 #include "tcuFormatUtil.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuRenderTarget.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluRenderContext.hpp"
34 #include "gluStrUtil.hpp"
35 #include "gluShaderProgram.hpp"
36 #include "deMemory.h"
37 #include "deStringUtil.hpp"
38
39 #include <algorithm>
40
41 #include "glwEnums.hpp"
42 #include "glwFunctions.hpp"
43
44 namespace deqp
45 {
46 namespace gles2
47 {
48 namespace Functional
49 {
50 namespace BufferTestUtil
51 {
52
53 enum
54 {
55 VERIFY_QUAD_SIZE = 8, //!< Quad size in VertexArrayVerifier
56 MAX_LINES_PER_INDEX_ARRAY_DRAW = 128, //!< Maximum number of lines per one draw in IndexArrayVerifier
57 INDEX_ARRAY_DRAW_VIEWPORT_WIDTH = 128,
58 INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT = 128
59 };
60
61 static const bool LOG_VERIFIER_CALLS = false; //! \note Especially array verifier generates a lot of calls.
62
63 using tcu::TestLog;
64 using std::vector;
65 using std::string;
66 using std::set;
67
68 // Helper functions.
69
fillWithRandomBytes(deUint8 * ptr,int numBytes,deUint32 seed)70 void fillWithRandomBytes (deUint8* ptr, int numBytes, deUint32 seed)
71 {
72 std::copy(tcu::RandomValueIterator<deUint8>::begin(seed, numBytes), tcu::RandomValueIterator<deUint8>::end(), ptr);
73 }
74
compareByteArrays(tcu::TestLog & log,const deUint8 * resPtr,const deUint8 * refPtr,int numBytes)75 bool compareByteArrays (tcu::TestLog& log, const deUint8* resPtr, const deUint8* refPtr, int numBytes)
76 {
77 bool isOk = true;
78 const int maxSpanLen = 8;
79 const int maxDiffSpans = 4;
80 int numDiffSpans = 0;
81 int diffSpanStart = -1;
82 int ndx = 0;
83
84 log << TestLog::Section("Verify", "Verification result");
85
86 for (;ndx < numBytes; ndx++)
87 {
88 if (resPtr[ndx] != refPtr[ndx])
89 {
90 if (diffSpanStart < 0)
91 diffSpanStart = ndx;
92
93 isOk = false;
94 }
95 else if (diffSpanStart >= 0)
96 {
97 if (numDiffSpans < maxDiffSpans)
98 {
99 int len = ndx-diffSpanStart;
100 int printLen = de::min(len, maxSpanLen);
101
102 log << TestLog::Message << len << " byte difference at offset " << diffSpanStart << "\n"
103 << " expected " << tcu::formatArray(tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart+printLen)) << "\n"
104 << " got " << tcu::formatArray(tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart+printLen))
105 << TestLog::EndMessage;
106 }
107 else
108 log << TestLog::Message << "(output too long, truncated)" << TestLog::EndMessage;
109
110 numDiffSpans += 1;
111 diffSpanStart = -1;
112 }
113 }
114
115 if (diffSpanStart >= 0)
116 {
117 if (numDiffSpans < maxDiffSpans)
118 {
119 int len = ndx-diffSpanStart;
120 int printLen = de::min(len, maxSpanLen);
121
122 log << TestLog::Message << len << " byte difference at offset " << diffSpanStart << "\n"
123 << " expected " << tcu::formatArray(tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(refPtr+diffSpanStart+printLen)) << "\n"
124 << " got " << tcu::formatArray(tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart), tcu::Format::HexIterator<deUint8>(resPtr+diffSpanStart+printLen))
125 << TestLog::EndMessage;
126 }
127 else
128 log << TestLog::Message << "(output too long, truncated)" << TestLog::EndMessage;
129 }
130
131 log << TestLog::Message << (isOk ? "Verification passed." : "Verification FAILED!") << TestLog::EndMessage;
132 log << TestLog::EndSection;
133
134 return isOk;
135 }
136
getBufferTargetName(deUint32 target)137 const char* getBufferTargetName (deUint32 target)
138 {
139 switch (target)
140 {
141 case GL_ARRAY_BUFFER: return "array";
142 case GL_ELEMENT_ARRAY_BUFFER: return "element_array";
143 default:
144 DE_ASSERT(false);
145 return DE_NULL;
146 }
147 }
148
getUsageHintName(deUint32 hint)149 const char* getUsageHintName (deUint32 hint)
150 {
151 switch (hint)
152 {
153 case GL_STREAM_DRAW: return "stream_draw";
154 case GL_STATIC_DRAW: return "static_draw";
155 case GL_DYNAMIC_DRAW: return "dynamic_draw";
156 default:
157 DE_ASSERT(false);
158 return DE_NULL;
159 }
160 }
161
162 // BufferCase
163
BufferCase(Context & context,const char * name,const char * description)164 BufferCase::BufferCase (Context& context, const char* name, const char* description)
165 : TestCase (context, name, description)
166 , CallLogWrapper (context.getRenderContext().getFunctions(), m_context.getTestContext().getLog())
167 {
168 }
169
~BufferCase(void)170 BufferCase::~BufferCase (void)
171 {
172 enableLogging(false);
173 BufferCase::deinit();
174 }
175
init(void)176 void BufferCase::init (void)
177 {
178 enableLogging(true);
179 }
180
deinit(void)181 void BufferCase::deinit (void)
182 {
183 for (set<deUint32>::const_iterator bufIter = m_allocatedBuffers.begin(); bufIter != m_allocatedBuffers.end(); bufIter++)
184 glDeleteBuffers(1, &(*bufIter));
185 }
186
genBuffer(void)187 deUint32 BufferCase::genBuffer (void)
188 {
189 deUint32 buf = 0;
190 glGenBuffers(1, &buf);
191 if (buf != 0)
192 {
193 try
194 {
195 m_allocatedBuffers.insert(buf);
196 }
197 catch (const std::exception&)
198 {
199 glDeleteBuffers(1, &buf);
200 throw;
201 }
202 }
203 return buf;
204 }
205
deleteBuffer(deUint32 buffer)206 void BufferCase::deleteBuffer (deUint32 buffer)
207 {
208 glDeleteBuffers(1, &buffer);
209 m_allocatedBuffers.erase(buffer);
210 }
211
checkError(void)212 void BufferCase::checkError (void)
213 {
214 glw::GLenum err = glGetError();
215 if (err != GL_NO_ERROR)
216 throw tcu::TestError(string("Got ") + glu::getErrorStr(err).toString());
217 }
218
219 // ReferenceBuffer
220
setSize(int numBytes)221 void ReferenceBuffer::setSize (int numBytes)
222 {
223 m_data.resize(numBytes);
224 }
225
setData(int numBytes,const deUint8 * bytes)226 void ReferenceBuffer::setData (int numBytes, const deUint8* bytes)
227 {
228 m_data.resize(numBytes);
229 std::copy(bytes, bytes+numBytes, m_data.begin());
230 }
231
setSubData(int offset,int numBytes,const deUint8 * bytes)232 void ReferenceBuffer::setSubData (int offset, int numBytes, const deUint8* bytes)
233 {
234 DE_ASSERT(de::inBounds(offset, 0, (int)m_data.size()) && de::inRange(offset+numBytes, offset, (int)m_data.size()));
235 std::copy(bytes, bytes+numBytes, m_data.begin()+offset);
236 }
237
238 // BufferVerifierBase
239
BufferVerifierBase(Context & context)240 BufferVerifierBase::BufferVerifierBase (Context& context)
241 : CallLogWrapper (context.getRenderContext().getFunctions(), context.getTestContext().getLog())
242 , m_context (context)
243 {
244 enableLogging(LOG_VERIFIER_CALLS);
245 }
246
247 // BufferVerifier
248
BufferVerifier(Context & context,VerifyType verifyType)249 BufferVerifier::BufferVerifier (Context& context, VerifyType verifyType)
250 : m_verifier(DE_NULL)
251 {
252 switch (verifyType)
253 {
254 case VERIFY_AS_VERTEX_ARRAY: m_verifier = new VertexArrayVerifier(context); break;
255 case VERIFY_AS_INDEX_ARRAY: m_verifier = new IndexArrayVerifier (context); break;
256 default:
257 TCU_FAIL("Unsupported verifier");
258 }
259 }
260
~BufferVerifier(void)261 BufferVerifier::~BufferVerifier (void)
262 {
263 delete m_verifier;
264 }
265
verify(deUint32 buffer,const deUint8 * reference,int offset,int numBytes)266 bool BufferVerifier::verify (deUint32 buffer, const deUint8* reference, int offset, int numBytes)
267 {
268 DE_ASSERT(numBytes >= getMinSize());
269 DE_ASSERT(offset%getAlignment() == 0);
270 DE_ASSERT((offset+numBytes)%getAlignment() == 0);
271 return m_verifier->verify(buffer, reference, offset, numBytes);
272 }
273
274 // VertexArrayVerifier
275
VertexArrayVerifier(Context & context)276 VertexArrayVerifier::VertexArrayVerifier (Context& context)
277 : BufferVerifierBase (context)
278 , m_program (DE_NULL)
279 , m_posLoc (0)
280 , m_byteVecLoc (0)
281 {
282 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
283 "attribute highp vec2 a_position;\n"
284 "attribute mediump vec3 a_byteVec;\n"
285 "varying mediump vec3 v_byteVec;\n"
286 "void main (void)\n"
287 "{\n"
288 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
289 " v_byteVec = a_byteVec;\n"
290 "}\n",
291
292 "varying mediump vec3 v_byteVec;\n"
293 "void main (void)\n"
294 "{\n"
295 " gl_FragColor = vec4(v_byteVec, 1.0);\n"
296 "}\n"));
297
298 if (!m_program->isOk())
299 {
300 m_context.getTestContext().getLog() << *m_program;
301 delete m_program;
302 TCU_FAIL("Compile failed");
303 }
304
305 const glw::Functions& funcs = context.getRenderContext().getFunctions();
306 m_posLoc = funcs.getAttribLocation(m_program->getProgram(), "a_position");
307 m_byteVecLoc = funcs.getAttribLocation(m_program->getProgram(), "a_byteVec");
308 }
309
~VertexArrayVerifier(void)310 VertexArrayVerifier::~VertexArrayVerifier (void)
311 {
312 delete m_program;
313 }
314
computePositions(vector<tcu::Vec2> & positions,int gridSizeX,int gridSizeY)315 static void computePositions (vector<tcu::Vec2>& positions, int gridSizeX, int gridSizeY)
316 {
317 positions.resize(gridSizeX*gridSizeY*4);
318
319 for (int y = 0; y < gridSizeY; y++)
320 for (int x = 0; x < gridSizeX; x++)
321 {
322 float sx0 = (float)(x+0) / (float)gridSizeX;
323 float sy0 = (float)(y+0) / (float)gridSizeY;
324 float sx1 = (float)(x+1) / (float)gridSizeX;
325 float sy1 = (float)(y+1) / (float)gridSizeY;
326 float fx0 = 2.0f * sx0 - 1.0f;
327 float fy0 = 2.0f * sy0 - 1.0f;
328 float fx1 = 2.0f * sx1 - 1.0f;
329 float fy1 = 2.0f * sy1 - 1.0f;
330 int baseNdx = (y * gridSizeX + x)*4;
331
332 positions[baseNdx+0] = tcu::Vec2(fx0, fy0);
333 positions[baseNdx+1] = tcu::Vec2(fx0, fy1);
334 positions[baseNdx+2] = tcu::Vec2(fx1, fy0);
335 positions[baseNdx+3] = tcu::Vec2(fx1, fy1);
336 }
337 }
338
computeIndices(vector<deUint16> & indices,int gridSizeX,int gridSizeY)339 static void computeIndices (vector<deUint16>& indices, int gridSizeX, int gridSizeY)
340 {
341 indices.resize(3 * 2 * gridSizeX * gridSizeY);
342
343 for (int quadNdx = 0; quadNdx < gridSizeX*gridSizeY; quadNdx++)
344 {
345 int v00 = quadNdx*4 + 0;
346 int v01 = quadNdx*4 + 1;
347 int v10 = quadNdx*4 + 2;
348 int v11 = quadNdx*4 + 3;
349
350 DE_ASSERT(v11 < (1<<16));
351
352 indices[quadNdx*6 + 0] = (deUint16)v10;
353 indices[quadNdx*6 + 1] = (deUint16)v00;
354 indices[quadNdx*6 + 2] = (deUint16)v01;
355
356 indices[quadNdx*6 + 3] = (deUint16)v10;
357 indices[quadNdx*6 + 4] = (deUint16)v01;
358 indices[quadNdx*6 + 5] = (deUint16)v11;
359 }
360 }
361
fetchVtxColor(const deUint8 * ptr,int vtxNdx)362 static inline tcu::Vec4 fetchVtxColor (const deUint8* ptr, int vtxNdx)
363 {
364 return tcu::RGBA(*(ptr + vtxNdx*3 + 0),
365 *(ptr + vtxNdx*3 + 1),
366 *(ptr + vtxNdx*3 + 2),
367 255).toVec();
368 }
369
renderQuadGridReference(tcu::Surface & dst,int numQuads,int rowLength,const deUint8 * inPtr)370 static void renderQuadGridReference (tcu::Surface& dst, int numQuads, int rowLength, const deUint8* inPtr)
371 {
372 using tcu::Vec4;
373
374 dst.setSize(rowLength*VERIFY_QUAD_SIZE, (numQuads/rowLength + (numQuads%rowLength != 0 ? 1 : 0))*VERIFY_QUAD_SIZE);
375
376 tcu::PixelBufferAccess dstAccess = dst.getAccess();
377 tcu::clear(dstAccess, tcu::IVec4(0, 0, 0, 0xff));
378
379 for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
380 {
381 int x0 = (quadNdx%rowLength)*VERIFY_QUAD_SIZE;
382 int y0 = (quadNdx/rowLength)*VERIFY_QUAD_SIZE;
383 Vec4 v00 = fetchVtxColor(inPtr, quadNdx*4 + 0);
384 Vec4 v10 = fetchVtxColor(inPtr, quadNdx*4 + 1);
385 Vec4 v01 = fetchVtxColor(inPtr, quadNdx*4 + 2);
386 Vec4 v11 = fetchVtxColor(inPtr, quadNdx*4 + 3);
387
388 for (int y = 0; y < VERIFY_QUAD_SIZE; y++)
389 for (int x = 0; x < VERIFY_QUAD_SIZE; x++)
390 {
391 float fx = ((float)x+0.5f) / (float)VERIFY_QUAD_SIZE;
392 float fy = ((float)y+0.5f) / (float)VERIFY_QUAD_SIZE;
393
394 bool tri = fx + fy <= 1.0f;
395 float tx = tri ? fx : (1.0f-fx);
396 float ty = tri ? fy : (1.0f-fy);
397 const Vec4& t0 = tri ? v00 : v11;
398 const Vec4& t1 = tri ? v01 : v10;
399 const Vec4& t2 = tri ? v10 : v01;
400 Vec4 color = t0 + (t1-t0)*tx + (t2-t0)*ty;
401
402 dstAccess.setPixel(color, x0+x, y0+y);
403 }
404 }
405 }
406
verify(deUint32 buffer,const deUint8 * refPtr,int offset,int numBytes)407 bool VertexArrayVerifier::verify (deUint32 buffer, const deUint8* refPtr, int offset, int numBytes)
408 {
409 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
410 const int numBytesInVtx = 3;
411 const int numBytesInQuad = numBytesInVtx*4;
412 int maxQuadsX = de::min(128, renderTarget.getWidth() / VERIFY_QUAD_SIZE);
413 int maxQuadsY = de::min(128, renderTarget.getHeight() / VERIFY_QUAD_SIZE);
414 int maxQuadsPerBatch = maxQuadsX*maxQuadsY;
415 int numVerified = 0;
416 deUint32 program = m_program->getProgram();
417 tcu::RGBA threshold = renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(4,4,4,4);
418 bool isOk = true;
419
420 vector<tcu::Vec2> positions;
421 vector<deUint16> indices;
422
423 tcu::Surface rendered;
424 tcu::Surface reference;
425
426 DE_ASSERT(numBytes >= numBytesInQuad); // Can't render full quad with smaller buffers.
427
428 computePositions(positions, maxQuadsX, maxQuadsY);
429 computeIndices(indices, maxQuadsX, maxQuadsY);
430
431 // Reset buffer bindings.
432 glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
433 glBindBuffer (GL_ARRAY_BUFFER, 0);
434
435 // Setup rendering state.
436 glViewport (0, 0, maxQuadsX*VERIFY_QUAD_SIZE, maxQuadsY*VERIFY_QUAD_SIZE);
437 glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
438 glUseProgram (program);
439 glEnableVertexAttribArray (m_posLoc);
440 glVertexAttribPointer (m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, &positions[0]);
441 glEnableVertexAttribArray (m_byteVecLoc);
442 glBindBuffer (GL_ARRAY_BUFFER, buffer);
443
444 while (numVerified < numBytes)
445 {
446 int numRemaining = numBytes-numVerified;
447 bool isLeftoverBatch = numRemaining < numBytesInQuad;
448 int numBytesToVerify = isLeftoverBatch ? numBytesInQuad : de::min(maxQuadsPerBatch*numBytesInQuad, numRemaining - numRemaining%numBytesInQuad);
449 int curOffset = isLeftoverBatch ? (numBytes-numBytesInQuad) : numVerified;
450 int numQuads = numBytesToVerify/numBytesInQuad;
451 int numCols = de::min(maxQuadsX, numQuads);
452 int numRows = numQuads/maxQuadsX + (numQuads%maxQuadsX != 0 ? 1 : 0);
453 string imageSetDesc = string("Bytes ") + de::toString(offset+curOffset) + " to " + de::toString(offset+curOffset+numBytesToVerify-1);
454
455 DE_ASSERT(numBytesToVerify > 0 && numBytesToVerify%numBytesInQuad == 0);
456 DE_ASSERT(de::inBounds(curOffset, 0, numBytes));
457 DE_ASSERT(de::inRange(curOffset+numBytesToVerify, curOffset, numBytes));
458
459 // Render batch.
460 glClear (GL_COLOR_BUFFER_BIT);
461 glVertexAttribPointer (m_byteVecLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, (const glw::GLvoid*)(deUintptr)(offset + curOffset));
462 glDrawElements (GL_TRIANGLES, numQuads*6, GL_UNSIGNED_SHORT, &indices[0]);
463
464 renderQuadGridReference(reference, numQuads, numCols, refPtr + offset + curOffset);
465
466 rendered.setSize(numCols*VERIFY_QUAD_SIZE, numRows*VERIFY_QUAD_SIZE);
467 glu::readPixels(m_context.getRenderContext(), 0, 0, rendered.getAccess());
468
469 if (!tcu::pixelThresholdCompare(m_context.getTestContext().getLog(), "RenderResult", imageSetDesc.c_str(), reference, rendered, threshold, tcu::COMPARE_LOG_RESULT))
470 {
471 isOk = false;
472 break;
473 }
474
475 numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
476 }
477
478 glDisableVertexAttribArray (m_posLoc);
479 glDisableVertexAttribArray (m_byteVecLoc);
480
481 return isOk;
482 }
483
484 // IndexArrayVerifier
485
IndexArrayVerifier(Context & context)486 IndexArrayVerifier::IndexArrayVerifier (Context& context)
487 : BufferVerifierBase (context)
488 , m_program (DE_NULL)
489 , m_posLoc (0)
490 , m_colorLoc (0)
491 {
492 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
493 "attribute highp vec2 a_position;\n"
494 "attribute mediump vec3 a_color;\n"
495 "varying mediump vec3 v_color;\n"
496 "void main (void)\n"
497 "{\n"
498 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
499 " v_color = a_color;\n"
500 "}\n",
501
502 "varying mediump vec3 v_color;\n"
503 "void main (void)\n"
504 "{\n"
505 " gl_FragColor = vec4(v_color, 1.0);\n"
506 "}\n"));
507
508 if (!m_program->isOk())
509 {
510 m_context.getTestContext().getLog() << *m_program;
511 delete m_program;
512 TCU_FAIL("Compile failed");
513 }
514
515 const glw::Functions& funcs = context.getRenderContext().getFunctions();
516 m_posLoc = funcs.getAttribLocation(m_program->getProgram(), "a_position");
517 m_colorLoc = funcs.getAttribLocation(m_program->getProgram(), "a_color");
518 }
519
~IndexArrayVerifier(void)520 IndexArrayVerifier::~IndexArrayVerifier (void)
521 {
522 delete m_program;
523 }
524
computeIndexVerifierPositions(std::vector<tcu::Vec2> & dst)525 static void computeIndexVerifierPositions (std::vector<tcu::Vec2>& dst)
526 {
527 const int numPosX = 16;
528 const int numPosY = 16;
529
530 dst.resize(numPosX*numPosY);
531
532 for (int y = 0; y < numPosY; y++)
533 {
534 for (int x = 0; x < numPosX; x++)
535 {
536 float xf = float(x) / float(numPosX-1);
537 float yf = float(y) / float(numPosY-1);
538
539 dst[y*numPosX + x] = tcu::Vec2(2.0f*xf - 1.0f, 2.0f*yf - 1.0f);
540 }
541 }
542 }
543
computeIndexVerifierColors(std::vector<tcu::Vec3> & dst)544 static void computeIndexVerifierColors (std::vector<tcu::Vec3>& dst)
545 {
546 const int numColors = 256;
547 const float minVal = 0.1f;
548 const float maxVal = 0.5f;
549 de::Random rnd (0xabc231);
550
551 dst.resize(numColors);
552
553 for (std::vector<tcu::Vec3>::iterator i = dst.begin(); i != dst.end(); ++i)
554 {
555 i->x() = rnd.getFloat(minVal, maxVal);
556 i->y() = rnd.getFloat(minVal, maxVal);
557 i->z() = rnd.getFloat(minVal, maxVal);
558 }
559 }
560
561 template<typename T>
execVertexFetch(T * dst,const T * src,const deUint8 * indices,int numIndices)562 static void execVertexFetch (T* dst, const T* src, const deUint8* indices, int numIndices)
563 {
564 for (int i = 0; i < numIndices; ++i)
565 dst[i] = src[indices[i]];
566 }
567
verify(deUint32 buffer,const deUint8 * refPtr,int offset,int numBytes)568 bool IndexArrayVerifier::verify (deUint32 buffer, const deUint8* refPtr, int offset, int numBytes)
569 {
570 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
571 const int viewportW = de::min<int>(INDEX_ARRAY_DRAW_VIEWPORT_WIDTH, renderTarget.getWidth());
572 const int viewportH = de::min<int>(INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT, renderTarget.getHeight());
573 const int minBytesPerBatch = 2;
574 const tcu::RGBA threshold (0,0,0,0);
575
576 std::vector<tcu::Vec2> positions;
577 std::vector<tcu::Vec3> colors;
578
579 std::vector<tcu::Vec2> fetchedPos (MAX_LINES_PER_INDEX_ARRAY_DRAW+1);
580 std::vector<tcu::Vec3> fetchedColor (MAX_LINES_PER_INDEX_ARRAY_DRAW+1);
581
582 tcu::Surface indexBufferImg (viewportW, viewportH);
583 tcu::Surface referenceImg (viewportW, viewportH);
584
585 int numVerified = 0;
586 bool isOk = true;
587
588 DE_STATIC_ASSERT(sizeof(tcu::Vec2) == sizeof(float)*2);
589 DE_STATIC_ASSERT(sizeof(tcu::Vec3) == sizeof(float)*3);
590
591 computeIndexVerifierPositions(positions);
592 computeIndexVerifierColors(colors);
593
594 // Reset buffer bindings.
595 glBindBuffer (GL_ARRAY_BUFFER, 0);
596 glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffer);
597
598 // Setup rendering state.
599 glViewport (0, 0, viewportW, viewportH);
600 glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
601 glUseProgram (m_program->getProgram());
602 glEnableVertexAttribArray (m_posLoc);
603 glEnableVertexAttribArray (m_colorLoc);
604 glEnable (GL_BLEND);
605 glBlendFunc (GL_ONE, GL_ONE);
606 glBlendEquation (GL_FUNC_ADD);
607
608 while (numVerified < numBytes)
609 {
610 int numRemaining = numBytes-numVerified;
611 bool isLeftoverBatch = numRemaining < minBytesPerBatch;
612 int numBytesToVerify = isLeftoverBatch ? minBytesPerBatch : de::min(MAX_LINES_PER_INDEX_ARRAY_DRAW+1, numRemaining);
613 int curOffset = isLeftoverBatch ? (numBytes-minBytesPerBatch) : numVerified;
614 string imageSetDesc = string("Bytes ") + de::toString(offset+curOffset) + " to " + de::toString(offset+curOffset+numBytesToVerify-1);
615
616 // Step 1: Render using index buffer.
617 glClear (GL_COLOR_BUFFER_BIT);
618 glVertexAttribPointer (m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, &positions[0]);
619 glVertexAttribPointer (m_colorLoc, 3, GL_FLOAT, GL_FALSE, 0, &colors[0]);
620 glDrawElements (GL_LINE_STRIP, numBytesToVerify, GL_UNSIGNED_BYTE, (void*)(deUintptr)(offset+curOffset));
621 glu::readPixels (m_context.getRenderContext(), 0, 0, indexBufferImg.getAccess());
622
623 // Step 2: Do manual fetch and render without index buffer.
624 execVertexFetch(&fetchedPos[0], &positions[0], refPtr+offset+curOffset, numBytesToVerify);
625 execVertexFetch(&fetchedColor[0], &colors[0], refPtr+offset+curOffset, numBytesToVerify);
626
627 glClear (GL_COLOR_BUFFER_BIT);
628 glVertexAttribPointer (m_posLoc, 2, GL_FLOAT, GL_FALSE, 0, &fetchedPos[0]);
629 glVertexAttribPointer (m_colorLoc, 3, GL_FLOAT, GL_FALSE, 0, &fetchedColor[0]);
630 glDrawArrays (GL_LINE_STRIP, 0, numBytesToVerify);
631 glu::readPixels (m_context.getRenderContext(), 0, 0, referenceImg.getAccess());
632
633 if (!tcu::pixelThresholdCompare(m_context.getTestContext().getLog(), "RenderResult", imageSetDesc.c_str(), referenceImg, indexBufferImg, threshold, tcu::COMPARE_LOG_RESULT))
634 {
635 isOk = false;
636 break;
637 }
638
639 numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
640 }
641
642 return isOk;
643 }
644
645 } // BufferTestUtil
646 } // Functional
647 } // gles2
648 } // deqp
649