Bug 1918529 - fix some subpixel misalignment issues with gfx.webrender.svg-filter...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / modules / shared / glsBufferTestUtil.js
blob446782b4b651416d6c6e2cb5874f3568476842fb
1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 'use strict';
22 goog.provide('modules.shared.glsBufferTestUtil');
23 goog.require('framework.common.tcuImageCompare');
24 goog.require('framework.common.tcuRGBA');
25 goog.require('framework.common.tcuSurface');
26 goog.require('framework.common.tcuTestCase');
27 goog.require('framework.common.tcuTexture');
28 goog.require('framework.delibs.debase.deMath');
29 goog.require('framework.delibs.debase.deRandom');
30 goog.require('framework.delibs.debase.deString');
31 goog.require('framework.delibs.debase.deUtil');
32 goog.require('framework.opengl.gluDrawUtil');
33 goog.require('framework.opengl.gluShaderProgram');
34 goog.require('framework.opengl.gluShaderUtil');
36 goog.scope(function() {
38 var glsBufferTestUtil = modules.shared.glsBufferTestUtil;
39 var tcuImageCompare = framework.common.tcuImageCompare;
40 var tcuRGBA = framework.common.tcuRGBA;
41 var tcuSurface = framework.common.tcuSurface;
42 var tcuTestCase = framework.common.tcuTestCase;
43 var tcuTexture = framework.common.tcuTexture;
44 var gluShaderProgram = framework.opengl.gluShaderProgram;
45 var gluShaderUtil = framework.opengl.gluShaderUtil;
46 var gluDrawUtil = framework.opengl.gluDrawUtil;
47 var deUtil = framework.delibs.debase.deUtil;
48 var deMath = framework.delibs.debase.deMath;
49 var deRandom = framework.delibs.debase.deRandom;
50 var deString = framework.delibs.debase.deString;
52 glsBufferTestUtil.VERIFY_QUAD_SIZE = 8; //!< Quad size in VertexArrayVerifier
53 glsBufferTestUtil.MAX_LINES_PER_INDEX_ARRAY_DRAW = 128; //!< Maximum number of lines per one draw in IndexArrayVerifier
54 glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_WIDTH = 128;
55 glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT = 128;
57 // Helper functions.
59 /**
60 * @param {Uint8Array} ptr
61 * @param {number} numBytes
62 * @param {number} seed
64 glsBufferTestUtil.fillWithRandomBytes = function(ptr, numBytes, seed) {
65 var rnd = new deRandom.Random(seed);
66 for (var left = numBytes; left > 0; left--)
67 ptr[left - 1] = rnd.getInt();
70 /**
71 * @param {Uint8Array} resPtr
72 * @param {Uint8Array} refPtr
73 * @param {number} numBytes
74 * @return {boolean}
76 glsBufferTestUtil.compareByteArrays = function(resPtr, refPtr, numBytes) {
77 var isOk = true;
78 var maxSpanLen = 8;
79 var maxDiffSpans = 4;
80 var numDiffSpans = 0;
81 var diffSpanStart = -1;
82 var ndx = 0;
84 var log = 'Verification result: ';
86 for (; ndx < numBytes; ndx++) {
87 if (resPtr[ndx] != refPtr[ndx]) {
88 if (diffSpanStart < 0)
89 diffSpanStart = ndx;
91 isOk = false;
92 } else if (diffSpanStart >= 0) {
93 if (numDiffSpans < maxDiffSpans) {
94 var len = ndx - diffSpanStart;
95 var printLen = Math.min(len, maxSpanLen);
97 log += len + ' byte difference at offset ' + diffSpanStart + '\n' +
98 ' expected ' + refPtr.subarray(diffSpanStart, diffSpanStart + printLen) +
99 ' got ' + resPtr.subarray(diffSpanStart, diffSpanStart + printLen);
100 } else
101 log += '(output too long, truncated)';
103 numDiffSpans += 1;
104 diffSpanStart = -1;
108 if (diffSpanStart >= 0) {
109 if (numDiffSpans < maxDiffSpans) {
110 var len = ndx - diffSpanStart;
111 var printLen = Math.min(len, maxSpanLen);
113 log += len + ' byte difference at offset ' + diffSpanStart + '\n' +
114 ' expected ' + refPtr.subarray(diffSpanStart, diffSpanStart + printLen) +
115 ' got ' + resPtr.subarray(diffSpanStart, diffSpanStart + printLen);
116 } else
117 log += '(output too long, truncated)';
120 log += (isOk ? 'Verification passed.' : 'Verification FAILED!');
122 bufferedLogToConsole(log);
124 return isOk;
128 * @param {number} target
129 * @return {string}
131 glsBufferTestUtil.getBufferTargetName = function(target) {
132 switch (target) {
133 case gl.ARRAY_BUFFER: return 'array';
134 case gl.COPY_READ_BUFFER: return 'copy_read';
135 case gl.COPY_WRITE_BUFFER: return 'copy_write';
136 case gl.ELEMENT_ARRAY_BUFFER: return 'element_array';
137 case gl.PIXEL_PACK_BUFFER: return 'pixel_pack';
138 case gl.PIXEL_UNPACK_BUFFER: return 'pixel_unpack';
139 //case gl.TEXTURE_BUFFER: return "texture"; //TODO: Unimplemented in WebGL 2. Remove?
140 case gl.TRANSFORM_FEEDBACK_BUFFER: return 'transform_feedback';
141 case gl.UNIFORM_BUFFER: return 'uniform';
142 default:
143 throw new Error('Invalid buffer target');
148 * @param {number} hint
149 * @return {string}
151 glsBufferTestUtil.getUsageHintName = function(hint) {
152 switch (hint) {
153 case gl.STREAM_DRAW: return 'stream_draw';
154 case gl.STREAM_READ: return 'stream_read';
155 case gl.STREAM_COPY: return 'stream_copy';
156 case gl.STATIC_DRAW: return 'static_draw';
157 case gl.STATIC_READ: return 'static_read';
158 case gl.STATIC_COPY: return 'static_copy';
159 case gl.DYNAMIC_DRAW: return 'dynamic_draw';
160 case gl.DYNAMIC_READ: return 'dynamic_read';
161 case gl.DYNAMIC_COPY: return 'dynamic_copy';
162 default:
163 throw new Error('Invalid buffer usage hint');
167 // Base class for buffer cases.
168 // BufferCase
171 * @constructor
172 * @extends {tcuTestCase.DeqpTest}
173 * @param {string} name
174 * @param {string} description
176 glsBufferTestUtil.BufferCase = function(name, description) {
177 tcuTestCase.DeqpTest.call(this, name, description);
178 /** @type {Array<WebGLBuffer>} */ this.m_allocatedBuffers = [];
181 glsBufferTestUtil.BufferCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
182 glsBufferTestUtil.BufferCase.prototype.constructor = glsBufferTestUtil.BufferCase;
185 * init
187 glsBufferTestUtil.BufferCase.prototype.init = function() {};
190 * deinit
192 glsBufferTestUtil.BufferCase.prototype.deinit = function() {
193 for (var ndx = 0; ndx < this.m_allocatedBuffers.length; ndx++)
194 this.deleteBuffer(this.m_allocatedBuffers[ndx]);
198 * @return {WebGLBuffer}
200 glsBufferTestUtil.BufferCase.prototype.genBuffer = function() {
201 var buf = 0;
202 buf = gl.createBuffer();
203 if (buf != 0) {
204 try {
205 deUtil.dePushUniqueToArray(this.m_allocatedBuffers, buf);
207 catch (err) {
208 gl.deleteBuffer(buf);
209 throw err;
212 return buf;
216 * @param {WebGLBuffer} buffer
218 glsBufferTestUtil.BufferCase.prototype.deleteBuffer = function(buffer) {
219 gl.deleteBuffer(buffer);
220 this.m_allocatedBuffers.splice(this.m_allocatedBuffers.indexOf(buffer), 1);
223 glsBufferTestUtil.BufferCase.prototype.checkError = function() {
224 /** @type {number} */ var err = gl.getError();
225 if (err != gl.NO_ERROR)
226 throw new TestFailedException('Got ' + WebGLTestUtils.glEnumToString(gl, err));
229 // Reference buffer.
232 * @constructor
234 glsBufferTestUtil.ReferenceBuffer = function() {
235 /** @type {ArrayBuffer} */ this.m_data;
239 * @param {number=} offset
240 * @return {Uint8Array}
242 glsBufferTestUtil.ReferenceBuffer.prototype.getPtr = function(offset) {
243 offset = offset ? offset : 0; return new Uint8Array(this.m_data, offset);
247 * @param {number} numBytes
249 glsBufferTestUtil.ReferenceBuffer.prototype.setSize = function(numBytes) {
250 this.m_data = new ArrayBuffer(numBytes);
254 * @param {number} numBytes
255 * @param {Uint8Array} bytes
257 glsBufferTestUtil.ReferenceBuffer.prototype.setData = function(numBytes, bytes) {
258 this.setSize(numBytes);
259 var dst = new Uint8Array(this.m_data);
260 dst.set(bytes.subarray(numBytes));
264 * @param {number} offset
265 * @param {number} numBytes
266 * @param {Uint8Array} bytes
268 glsBufferTestUtil.ReferenceBuffer.prototype.setSubData = function(offset, numBytes, bytes) {
269 assertMsgOptions(deMath.deInBounds32(offset, 0, this.m_data.byteLength) && deMath.deInRange32(offset + numBytes, offset, this.m_data.byteLength),
270 'Parameters not in buffer bounds or range', false, true);
271 var dst = new Uint8Array(this.m_data, offset);
272 dst.set(bytes.subarray(offset, offset + numBytes));
275 // Buffer writer system.
278 * @enum {number}
280 glsBufferTestUtil.WriteType = {
281 BUFFER_SUB_DATA: 0,
282 BUFFER_WRITE_MAP: 1,
283 TRANSFORM_FEEDBACK: 2,
284 PIXEL_PACK: 3
288 * @param {glsBufferTestUtil.WriteType} write
289 * @return {string}
291 glsBufferTestUtil.getWriteTypeDescription = function(write) {
292 /** @type {Array<string>} */ var s_desc = [
293 'gl.bufferSubData()',
294 'gl.mapBufferRange()',
295 'transform feedback',
296 'gl.readPixels() into PBO binding'
298 return /** @type {string} */ (deUtil.getArrayElement(s_desc, write));
301 // BufferWriterBase
304 * @constructor
306 glsBufferTestUtil.BufferWriterBase = function() {};
309 * //Meant to be overriden
310 * @return {number}
312 glsBufferTestUtil.BufferWriterBase.prototype.getMinSize = function() { throw new Error('Must be overriden'); };
315 * //Meant to be overriden
316 * @return {number}
318 glsBufferTestUtil.BufferWriterBase.prototype.getAlignment = function() { throw new Error('Must be overriden'); };
321 * //Meant to be overriden
322 * @param {WebGLBuffer} buffer
323 * @param {number} offset
324 * @param {number} numBytes
325 * @param {Uint8Array} bytes
327 glsBufferTestUtil.BufferWriterBase.prototype.writeNoTarget = function(buffer, offset, numBytes, bytes) { throw new Error('Must be overriden'); };
330 * @param {WebGLBuffer} buffer
331 * @param {number} offset
332 * @param {number} numBytes
333 * @param {Uint8Array} bytes
334 * @param {number} targetHint
336 glsBufferTestUtil.BufferWriterBase.prototype.write = function(buffer, offset, numBytes, bytes, targetHint) {
337 this.writeNoTarget(buffer, offset, numBytes, bytes);
340 // BufferWriter
343 * @constructor
344 * @param {glsBufferTestUtil.WriteType} writeType
346 glsBufferTestUtil.BufferWriter = function(writeType) {
347 /** @type {glsBufferTestUtil.BufferWriterBase} */ this.m_writer = null;
348 switch (writeType) {
349 case glsBufferTestUtil.WriteType.BUFFER_SUB_DATA: this.m_writer = new glsBufferTestUtil.BufferSubDataWriter(); break;
350 default:
351 testFailed('Unsupported writer');
356 * @return {number}
358 glsBufferTestUtil.BufferWriter.prototype.getMinSize = function() {return this.m_writer.getMinSize();};
361 * @return {number}
363 glsBufferTestUtil.BufferWriter.prototype.getAlignment = function() {return this.m_writer.getAlignment();};
366 * @param {WebGLBuffer} buffer
367 * @param {number} offset
368 * @param {number} numBytes
369 * @param {Uint8Array} bytes
371 glsBufferTestUtil.BufferWriter.prototype.writeNoTarget = function(buffer, offset, numBytes, bytes) {
372 assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
373 assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
374 assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
375 return this.m_writer.writeNoTarget(buffer, offset, numBytes, bytes);
379 * @param {WebGLBuffer} buffer
380 * @param {number} offset
381 * @param {number} numBytes
382 * @param {Uint8Array} bytes
383 * @param {number} targetHint
385 glsBufferTestUtil.BufferWriter.prototype.write = function(buffer, offset, numBytes, bytes, targetHint) {
386 assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
387 assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
388 assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
389 return this.m_writer.write(buffer, offset, numBytes, bytes, targetHint);
392 // BufferSubDataWriter
395 * @constructor
396 * @extends {glsBufferTestUtil.BufferWriterBase}
398 glsBufferTestUtil.BufferSubDataWriter = function() {
399 glsBufferTestUtil.BufferWriterBase.call(this);
402 glsBufferTestUtil.BufferSubDataWriter.prototype = Object.create(glsBufferTestUtil.BufferWriterBase.prototype);
403 glsBufferTestUtil.BufferSubDataWriter.prototype.constructor = glsBufferTestUtil.BufferSubDataWriter;
406 * @return {number}
408 glsBufferTestUtil.BufferSubDataWriter.prototype.getMinSize = function() { return 1; };
411 * @return {number}
413 glsBufferTestUtil.BufferSubDataWriter.prototype.getAlignment = function() { return 1; };
416 * @param {WebGLBuffer} buffer
417 * @param {number} offset
418 * @param {number} numBytes
419 * @param {Uint8Array} bytes
421 glsBufferTestUtil.BufferSubDataWriter.prototype.writeNoTarget = function(buffer, offset, numBytes, bytes) {
422 this.write(buffer, offset, numBytes, bytes, gl.ARRAY_BUFFER);
426 * @param {WebGLBuffer} buffer
427 * @param {number} offset
428 * @param {number} numBytes
429 * @param {Uint8Array} bytes
430 * @param {number} target
432 glsBufferTestUtil.BufferSubDataWriter.prototype.write = function(buffer, offset, numBytes, bytes, target) {
433 gl.bindBuffer(target, buffer);
434 gl.bufferSubData(target, offset, bytes);
435 gl.bindBuffer(target, null);
438 // Buffer verifier system.
441 * @enum {number}
443 glsBufferTestUtil.VerifyType = {
444 AS_VERTEX_ARRAY: 0,
445 AS_INDEX_ARRAY: 1,
446 AS_UNIFORM_BUFFER: 2,
447 AS_PIXEL_UNPACK_BUFFER: 3,
448 BUFFER_READ_MAP: 4
452 * @param {glsBufferTestUtil.VerifyType} verify
453 * @return {string}
455 glsBufferTestUtil.getVerifyTypeDescription = function(verify) {
456 /** @type {Array<string>} */ var s_desc =
458 'rendering as vertex data',
459 'rendering as index data',
460 'reading in shader as uniform buffer data',
461 'using as PBO and uploading to texture',
462 'reading back using glMapBufferRange()'
465 return /** @type {string} */ (deUtil.getArrayElement(s_desc, verify));
469 * @constructor
471 glsBufferTestUtil.BufferVerifierBase = function() {};
474 * //Meant to be overriden
475 * @return {number}
477 glsBufferTestUtil.BufferVerifierBase.prototype.getMinSize = function() { throw new Error('Must be overriden'); };
480 * //Meant to be overriden
481 * @return {number}
483 glsBufferTestUtil.BufferVerifierBase.prototype.getAlignment = function() { throw new Error('Must be overriden'); };
486 * @param {WebGLBuffer} buffer
487 * @param {Uint8Array} reference
488 * @param {number} offset
489 * @param {number} numBytes
490 * @return {boolean}
492 glsBufferTestUtil.BufferVerifierBase.prototype.verifyNoTarget = function(buffer, reference, offset, numBytes) {
493 throw new Error('Must be overriden');
497 * //Meant to be overriden
498 * @param {WebGLBuffer} buffer
499 * @param {Uint8Array} reference
500 * @param {number} offset
501 * @param {number} numBytes
502 * @param {number} targetHint
503 * @return {boolean}
505 glsBufferTestUtil.BufferVerifierBase.prototype.verify = function(buffer, reference, offset, numBytes, targetHint) {
506 //In WebGL 2, ELEMENT_ARRAY_BUFFER and TRANSFORM_FEEDBACK_BUFFER cannot be rebound to a different
507 //type of buffer, so, let's copy their data to an ARRAY BUFFER and pass that one instead to be verified.
508 var wasReadBufferCreated = false;
509 try {
510 if (targetHint == gl.ELEMENT_ARRAY_BUFFER || targetHint == gl.TRANSFORM_FEEDBACK_BUFFER) {
511 var readBuffer = new Uint8Array(offset + numBytes);
512 gl.getBufferSubData(targetHint, 0, readBuffer);
513 buffer = gl.createBuffer();
515 wasReadBufferCreated = true;
517 gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
518 gl.bufferData(gl.ARRAY_BUFFER, readBuffer, gl.STATIC_DRAW);
521 var result = this.verifyNoTarget(buffer, reference, offset, numBytes);
523 if (wasReadBufferCreated)
524 gl.deleteBuffer(buffer);
526 return result;
527 } catch (err) {
528 if (wasReadBufferCreated)
529 gl.deleteBuffer(buffer);
530 throw err;
534 // BufferVerifier
537 * @constructor
538 * @param {glsBufferTestUtil.VerifyType} verifyType
540 glsBufferTestUtil.BufferVerifier = function(verifyType) {
541 /** @type {glsBufferTestUtil.BufferVerifierBase} */ this.m_verifier = null;
542 switch (verifyType) {
543 case glsBufferTestUtil.VerifyType.AS_VERTEX_ARRAY: this.m_verifier = new glsBufferTestUtil.VertexArrayVerifier(); break;
544 case glsBufferTestUtil.VerifyType.AS_INDEX_ARRAY: this.m_verifier = new glsBufferTestUtil.IndexArrayVerifier(); break;
545 default:
546 testFailed('Unsupported verifier type');
551 * @return {number}
553 glsBufferTestUtil.BufferVerifier.prototype.getMinSize = function() { return this.m_verifier.getMinSize(); };
556 * @return {number}
558 glsBufferTestUtil.BufferVerifier.prototype.getAlignment = function() { return this.m_verifier.getAlignment(); };
561 * @param {WebGLBuffer} buffer
562 * @param {Uint8Array} reference
563 * @param {number} numBytes
564 * @return {boolean}
566 glsBufferTestUtil.BufferVerifier.prototype.verifyNoTarget = function(buffer, reference, offset, numBytes) {
567 assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
568 assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
569 assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
570 return this.m_verifier.verifyNoTarget(buffer, reference, offset, numBytes);
574 * @param {WebGLBuffer} buffer
575 * @param {Uint8Array} reference
576 * @param {number} offset
577 * @param {number} numBytes
578 * @param {number} targetHint
579 * @return {boolean}
581 glsBufferTestUtil.BufferVerifier.prototype.verify = function(buffer, reference, offset, numBytes, targetHint) {
582 assertMsgOptions(numBytes >= this.getMinSize(), 'Number of bytes to write is smaller than the minimum size.', false, true);
583 assertMsgOptions(offset % this.getAlignment() == 0, 'Offset is not aligned.', false, true);
584 assertMsgOptions((offset + numBytes) % this.getAlignment() == 0, 'Buffer segment is not aligned', false, true);
585 return this.m_verifier.verify(buffer, reference, offset, numBytes, targetHint);
588 // VertexArrayVerifier
591 * @constructor
592 * @extends {glsBufferTestUtil.BufferVerifierBase}
594 glsBufferTestUtil.VertexArrayVerifier = function() {
595 glsBufferTestUtil.BufferVerifierBase.call(this);
596 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
597 this.m_posLoc = 0;
598 this.m_byteVecLoc = 0;
599 /** @type {WebGLVertexArrayObject} */ this.m_vao = null;
601 /** @type {gluShaderUtil.GLSLVersion} */ var glslVersion = gluShaderUtil.getGLSLVersion(gl);
603 assertMsgOptions(gluShaderUtil.isGLSLVersionSupported(gl, glslVersion), 'Unsupported GLSL version', false, true);
605 this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(
606 gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
607 'in highp vec2 a_position;\n' +
608 'in mediump vec3 a_byteVec;\n' +
609 'out mediump vec3 v_byteVec;\n' +
610 'void main (void)\n' +
611 '{\n' +
612 ' gl_Position = vec4(a_position, 0.0, 1.0);\n' +
613 ' v_byteVec = a_byteVec;\n' +
614 '}\n',
616 gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
617 'in mediump vec3 v_byteVec;\n' +
618 'layout(location = 0) out mediump vec4 o_color;\n' +
619 'void main (void)\n' +
620 '{\n' +
621 ' o_color = vec4(v_byteVec, 1.0);\n' +
622 '}\n'
625 if (!this.m_program.isOk()) {
626 testFailed('Compile failed');
629 this.m_posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
630 this.m_byteVecLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_byteVec');
632 this.m_vao = gl.createVertexArray();
633 this.m_positionBuf = gl.createBuffer();
634 this.m_indexBuf = gl.createBuffer();
637 glsBufferTestUtil.VertexArrayVerifier.prototype = Object.create(glsBufferTestUtil.BufferVerifierBase.prototype);
638 glsBufferTestUtil.VertexArrayVerifier.prototype.constructor = glsBufferTestUtil.VertexArrayVerifier;
641 * @return {number}
643 glsBufferTestUtil.VertexArrayVerifier.prototype.getMinSize = function() { return 3 * 4; };
646 * @return {number}
648 glsBufferTestUtil.VertexArrayVerifier.prototype.getAlignment = function() { return 1; };
651 * deinit
653 glsBufferTestUtil.VertexArrayVerifier.prototype.deinit = function() {
654 if (this.m_vao) gl.deleteVertexArray(this.m_vao);
655 if (this.m_positionBuf) gl.deleteBuffer(this.m_positionBuf);
656 if (this.m_indexBuf) gl.deleteBuffer(this.m_indexBuf);
660 * @param {number} gridSizeX
661 * @param {number} gridSizeY
662 * @return {Array<number>}
664 glsBufferTestUtil.computePositions = function(gridSizeX, gridSizeY) {
665 var positions = [];
667 for (var y = 0; y < gridSizeY; y++)
668 for (var x = 0; x < gridSizeX; x++) {
669 /** @type {number} */ var sx0 = (x + 0) / gridSizeX;
670 /** @type {number} */ var sy0 = (y + 0) / gridSizeY;
671 /** @type {number} */ var sx1 = (x + 1) / gridSizeX;
672 /** @type {number} */ var sy1 = (y + 1) / gridSizeY;
673 /** @type {number} */ var fx0 = 2.0 * sx0 - 1.0;
674 /** @type {number} */ var fy0 = 2.0 * sy0 - 1.0;
675 /** @type {number} */ var fx1 = 2.0 * sx1 - 1.0;
676 /** @type {number} */ var fy1 = 2.0 * sy1 - 1.0;
677 /** @type {number} */ var baseNdx = (y * gridSizeX + x) * 8;
679 positions[baseNdx + 0] = fx0; positions[baseNdx + 1] = fy0;
680 positions[baseNdx + 2] = fx0; positions[baseNdx + 3] = fy1;
681 positions[baseNdx + 4] = fx1; positions[baseNdx + 5] = fy0;
682 positions[baseNdx + 6] = fx1; positions[baseNdx + 7] = fy1;
685 return positions;
689 * @param {number} gridSizeX
690 * @param {number} gridSizeY
691 * @return {Uint16Array}
693 glsBufferTestUtil.computeIndices = function(gridSizeX, gridSizeY) {
694 var indices = new Uint16Array(3 * 2 * gridSizeX * gridSizeY);
696 for (var quadNdx = 0; quadNdx < gridSizeX * gridSizeY; quadNdx++) {
697 /** @type {number} */ var v00 = quadNdx * 4 + 0;
698 /** @type {number} */ var v01 = quadNdx * 4 + 1;
699 /** @type {number} */ var v10 = quadNdx * 4 + 2;
700 /** @type {number} */ var v11 = quadNdx * 4 + 3;
702 assertMsgOptions(v11 < (1 << 16), 'Vertex index value won\'t fit into a 16-bit number', false, true);
704 indices[quadNdx * 6 + 0] = v10;
705 indices[quadNdx * 6 + 1] = v00;
706 indices[quadNdx * 6 + 2] = v01;
708 indices[quadNdx * 6 + 3] = v10;
709 indices[quadNdx * 6 + 4] = v01;
710 indices[quadNdx * 6 + 5] = v11;
713 return indices;
717 * @param {Uint8Array} ptr
718 * @param {number} vtxNdx
719 * @return {Array<number>}
721 glsBufferTestUtil.fetchVtxColor = function(ptr, vtxNdx) {
722 return new tcuRGBA.RGBA([
723 ptr[vtxNdx * 3 + 0],
724 ptr[vtxNdx * 3 + 1],
725 ptr[vtxNdx * 3 + 2],
726 255]).toVec();
730 * @param {tcuSurface.Surface} dst
731 * @param {number} numQuads
732 * @param {number} rowLength
733 * @param {Uint8Array} inPtr
735 glsBufferTestUtil.renderQuadGridReference = function(dst, numQuads, rowLength, inPtr) {
736 dst.setSize(rowLength * glsBufferTestUtil.VERIFY_QUAD_SIZE, (Math.floor(numQuads / rowLength) + (numQuads % rowLength != 0 ? 1 : 0)) * glsBufferTestUtil.VERIFY_QUAD_SIZE);
738 /** @type {tcuTexture.PixelBufferAccess} */ var dstAccess = dst.getAccess();
739 dstAccess.clear([0, 0, 0, 1.0]);
741 for (var quadNdx = 0; quadNdx < numQuads; quadNdx++) {
742 /** @type {number} */ var x0 = (quadNdx % rowLength) * glsBufferTestUtil.VERIFY_QUAD_SIZE;
743 /** @type {number} */ var y0 = Math.floor(quadNdx / rowLength) * glsBufferTestUtil.VERIFY_QUAD_SIZE;
744 /** @type {Array<number>} */ var v00 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 0);
745 /** @type {Array<number>} */ var v10 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 1);
746 /** @type {Array<number>} */ var v01 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 2);
747 /** @type {Array<number>} */ var v11 = glsBufferTestUtil.fetchVtxColor(inPtr, quadNdx * 4 + 3);
749 for (var y = 0; y < glsBufferTestUtil.VERIFY_QUAD_SIZE; y++)
750 for (var x = 0; x < glsBufferTestUtil.VERIFY_QUAD_SIZE; x++) {
751 /** @type {number} */ var fx = (x + 0.5) / glsBufferTestUtil.VERIFY_QUAD_SIZE;
752 /** @type {number} */ var fy = (y + 0.5) / glsBufferTestUtil.VERIFY_QUAD_SIZE;
754 /** @type {boolean} */ var tri = fx + fy <= 1.0;
755 /** @type {number} */ var tx = tri ? fx : (1.0 - fx);
756 /** @type {number} */ var ty = tri ? fy : (1.0 - fy);
757 /** @type {Array<number>} */ var t0 = tri ? v00 : v11;
758 /** @type {Array<number>} */ var t1 = tri ? v01 : v10;
759 /** @type {Array<number>} */ var t2 = tri ? v10 : v01;
760 /** @type {Array<number>} */ var color = deMath.add(
761 deMath.add(t0, deMath.scale(deMath.subtract(t1, t0), tx)),
762 deMath.scale(deMath.subtract(t2, t0), ty)
765 dstAccess.setPixel(color, x0 + x, y0 + y);
771 * @param {WebGLBuffer} buffer
772 * @param {Uint8Array} refPtr
773 * @param {number} offset
774 * @param {number} numBytes
775 * @return {boolean}
777 glsBufferTestUtil.VertexArrayVerifier.prototype.verifyNoTarget = function(buffer, refPtr, offset, numBytes) {
778 var numBytesInVtx = 3;
779 var numBytesInQuad = numBytesInVtx * 4;
780 var maxQuadsX = Math.min(128, Math.floor(gl.drawingBufferWidth / glsBufferTestUtil.VERIFY_QUAD_SIZE));
781 var maxQuadsY = Math.min(128, Math.floor(gl.drawingBufferHeight / glsBufferTestUtil.VERIFY_QUAD_SIZE));
782 var maxQuadsPerBatch = maxQuadsX * maxQuadsY;
783 var numVerified = 0;
784 var program = this.m_program.getProgram();
785 /** @type {tcuRGBA.RGBA} */ var threshold = /*TODO: renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(3,3,3,3);*/ new tcuRGBA.RGBA([3, 3, 3, 3]);
786 var isOk = true;
788 /** @type {Array<number>} */ var positions = [];
789 /** @type {Uint16Array} */var indices;
791 /** @type {tcuSurface.Surface} */ var rendered = new tcuSurface.Surface();
792 /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface();
794 // Can't render full quad with smaller buffers.
795 assertMsgOptions(numBytes >= numBytesInQuad, 'Number of bytes must be bigger than number of bytes per quad', false, true);
797 positions = glsBufferTestUtil.computePositions(maxQuadsX, maxQuadsY);
798 indices = glsBufferTestUtil.computeIndices(maxQuadsX, maxQuadsY);
800 // Reset buffer bindings.
801 gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
803 // Setup rendering state.
804 gl.viewport(0, 0, maxQuadsX * glsBufferTestUtil.VERIFY_QUAD_SIZE, maxQuadsY * glsBufferTestUtil.VERIFY_QUAD_SIZE);
805 gl.clearColor(0.0, 0.0, 0.0, 1.0);
806 gl.useProgram(program);
807 gl.bindVertexArray(this.m_vao);
809 // Upload positions
810 gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuf);
811 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
812 gl.enableVertexAttribArray(this.m_posLoc);
813 gl.vertexAttribPointer(this.m_posLoc, 2, gl.FLOAT, false, 0, 0);
815 // Upload indices
816 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_indexBuf);
817 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
819 gl.enableVertexAttribArray(this.m_byteVecLoc);
821 gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
823 while (numVerified < numBytes) {
824 /** @type {number} */ var numRemaining = numBytes - numVerified;
825 var isLeftoverBatch = numRemaining < numBytesInQuad;
826 /** @type {number} */ var numBytesToVerify = isLeftoverBatch ? numBytesInQuad : Math.min(maxQuadsPerBatch * numBytesInQuad, numRemaining - numRemaining % numBytesInQuad);
827 /** @type {number} */ var curOffset = isLeftoverBatch ? (numBytes - numBytesInQuad) : numVerified;
828 /** @type {number} */ var numQuads = Math.floor(numBytesToVerify / numBytesInQuad);
829 /** @type {number} */ var numCols = Math.min(maxQuadsX, numQuads);
830 /** @type {number} */ var numRows = Math.floor(numQuads / maxQuadsX) + (numQuads % maxQuadsX != 0 ? 1 : 0);
831 /** @type {string} */ var imageSetDesc = 'Bytes ' + (offset + curOffset) + ' to ' + (offset + curOffset + numBytesToVerify - 1);
833 assertMsgOptions(numBytesToVerify > 0 && numBytesToVerify % numBytesInQuad == 0, 'Bytes to verify must be greater than zero and must be a multiple of the bytes per quad', false, true);
834 assertMsgOptions(deMath.deInBounds32(curOffset, 0, numBytes), 'Offset out of bounds', false, true);
835 assertMsgOptions(deMath.deInRange32(curOffset + numBytesToVerify, curOffset, numBytes), 'Range of bytes to verify outside of bounds', false, true);
837 // Render batch.
838 gl.clear(gl.COLOR_BUFFER_BIT);
839 gl.vertexAttribPointer(this.m_byteVecLoc, 3, gl.UNSIGNED_BYTE, true, 0, offset + curOffset);
840 gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_SHORT, 0);
842 glsBufferTestUtil.renderQuadGridReference(reference, numQuads, numCols, refPtr.subarray(offset + curOffset));
844 rendered.setSize(numCols * glsBufferTestUtil.VERIFY_QUAD_SIZE, numRows * glsBufferTestUtil.VERIFY_QUAD_SIZE);
845 rendered.readViewport(gl, [0, 0, numCols * glsBufferTestUtil.VERIFY_QUAD_SIZE, numRows * glsBufferTestUtil.VERIFY_QUAD_SIZE]);
847 if (!tcuImageCompare.pixelThresholdCompare('RenderResult', imageSetDesc, reference, rendered, threshold.toIVec(), tcuImageCompare.CompareLogMode.RESULT)) {
848 isOk = false;
849 break;
852 numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
855 gl.bindVertexArray(null);
857 return isOk;
860 // IndexArrayVerifier
863 * @constructor
864 * @extends {glsBufferTestUtil.BufferVerifierBase}
866 glsBufferTestUtil.IndexArrayVerifier = function() {
867 glsBufferTestUtil.BufferVerifierBase.call(this);
869 this.m_program = null;
870 this.m_posLoc = 0;
871 this.m_colorLoc = 0;
873 /** @type {gluShaderUtil.GLSLVersion} */ var glslVersion = gluShaderUtil.GLSLVersion.V300_ES;
875 assertMsgOptions(gluShaderUtil.isGLSLVersionSupported(gl, glslVersion), 'GLSL version not supported', false, true);
877 this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(
878 gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
879 'in highp vec2 a_position;\n' +
880 'in mediump vec3 a_color;\n' +
881 'out mediump vec3 v_color;\n' +
882 'void main (void)\n' +
883 '{\n' +
884 ' gl_Position = vec4(a_position, 0.0, 1.0);\n' +
885 ' v_color = a_color;\n' +
886 '}\n',
888 gluShaderUtil.getGLSLVersionDeclaration(glslVersion) + '\n' +
889 'in mediump vec3 v_color;\n' +
890 'layout(location = 0) out mediump vec4 o_color;\n' +
891 'void main (void)\n' +
892 '{\n' +
893 ' o_color = vec4(v_color, 1.0);\n' +
894 '}\n'));
896 if (!this.m_program.isOk()) {
897 testFailed('Compile failed');
900 this.m_posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
901 this.m_colorLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_color');
903 this.m_vao = gl.createVertexArray();
904 this.m_positionBuf = gl.createBuffer();
905 this.m_colorBuf = gl.createBuffer();
908 glsBufferTestUtil.IndexArrayVerifier.prototype = Object.create(glsBufferTestUtil.BufferVerifierBase.prototype);
909 glsBufferTestUtil.IndexArrayVerifier.prototype.constructor = glsBufferTestUtil.IndexArrayVerifier;
912 * deinit
914 glsBufferTestUtil.IndexArrayVerifier.prototype.deinit = function() {
915 if (this.m_vao) gl.deleteVertexArray(this.m_vao);
916 if (this.m_positionBuf) gl.deleteBuffer(this.m_positionBuf);
917 if (this.m_colorBuf) gl.deleteBuffer(this.m_colorBuf);
921 * @return {Array<number>}
923 glsBufferTestUtil.computeIndexVerifierPositions = function() {
924 var numPosX = 16;
925 var numPosY = 16;
927 var dst = [];
929 for (var y = 0; y < numPosY; y++) {
930 for (var x = 0; x < numPosX; x++) {
931 var xf = x / (numPosX - 1);
932 var yf = y / (numPosY - 1);
934 var offset = 2 * (y * numPosX + x);
935 dst[offset] = 2.0 * xf - 1.0;
936 dst[offset + 1] = 2.0 * yf - 1.0;
940 return dst;
944 * @return {Array<number>}
946 glsBufferTestUtil.computeIndexVerifierColors = function() {
947 /** @type {number} */ var numColors = 256;
948 /** @type {number} */ var minVal = 0.1;
949 /** @type {number} */ var maxVal = 0.5;
950 var rnd = new deRandom.Random(0xabc231);
952 var dst = [];
954 for (var i = 0; i < numColors; ++i) {
955 dst[3 * i] = rnd.getFloat(minVal, maxVal);
956 dst[3 * i + 1] = rnd.getFloat(minVal, maxVal);
957 dst[3 * i + 2] = rnd.getFloat(minVal, maxVal);
960 return dst;
964 * @param {Array<number>} dst
965 * @param {Array<number>} src
966 * @param {Uint8Array} indices
967 * @param {number} numIndices
969 glsBufferTestUtil.execVertexFetch = function(dst, src, indices, numIndices) {
970 for (var i = 0; i < numIndices; ++i)
971 dst[i] = src[indices[i]];
975 * @param {WebGLBuffer} buffer
976 * @param {Uint8Array} refPtr
977 * @param {number} offset
978 * @param {number} numBytes
979 * @return {boolean}
981 glsBufferTestUtil.IndexArrayVerifier.prototype.verify = function(buffer, refPtr, offset, numBytes) {
982 var viewportW = Math.min(glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_WIDTH, gl.drawingBufferWidth);
983 var viewportH = Math.min(glsBufferTestUtil.INDEX_ARRAY_DRAW_VIEWPORT_HEIGHT, gl.drawingBufferHeight);
984 var minBytesPerBatch = 2;
985 /** @type {tcuRGBA.RGBA} */ var threshold = new tcuRGBA.RGBA([0, 0, 0, 0]);
987 var positions = [];
988 var colors = [];
990 var fetchedPos = [];
991 var fetchedColor = [];
993 /** @type {tcuSurface.Surface} */ var indexBufferImg = new tcuSurface.Surface(viewportW, viewportH);
994 /** @type {tcuSurface.Surface} */ var referenceImg = new tcuSurface.Surface(viewportW, viewportH);
996 var numVerified = 0;
997 var isOk = true;
999 positions = glsBufferTestUtil.computeIndexVerifierPositions();
1000 colors = glsBufferTestUtil.computeIndexVerifierColors();
1002 // Reset buffer bindings.
1003 gl.bindVertexArray(this.m_vao);
1004 gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
1005 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
1007 // Setup rendering state.
1008 gl.viewport(0, 0, viewportW, viewportH);
1009 gl.clearColor(0.0, 0.0, 0.0, 1.0);
1010 gl.useProgram(this.m_program.getProgram());
1011 gl.enableVertexAttribArray(this.m_posLoc);
1012 gl.enableVertexAttribArray(this.m_colorLoc);
1013 gl.enable(gl.BLEND);
1014 gl.blendFunc(gl.ONE, gl.ONE);
1015 gl.blendEquation(gl.FUNC_ADD);
1017 while (numVerified < numBytes) {
1018 var numRemaining = numBytes - numVerified;
1019 var isLeftoverBatch = numRemaining < minBytesPerBatch;
1020 var numBytesToVerify = isLeftoverBatch ? minBytesPerBatch : Math.min(glsBufferTestUtil.MAX_LINES_PER_INDEX_ARRAY_DRAW + 1, numRemaining);
1021 var curOffset = isLeftoverBatch ? (numBytes - minBytesPerBatch) : numVerified;
1022 /** @type {string} */ var imageSetDesc = 'Bytes ' + (offset + curOffset) + ' to ' + (offset + curOffset + numBytesToVerify - 1);
1024 // Step 1: Render using index buffer.
1025 gl.clear(gl.COLOR_BUFFER_BIT);
1027 gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuf);
1028 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STREAM_DRAW);
1029 gl.vertexAttribPointer(this.m_posLoc, 2, gl.FLOAT, false, 0, 0);
1031 gl.bindBuffer(gl.ARRAY_BUFFER, this.m_colorBuf);
1032 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STREAM_DRAW);
1033 gl.vertexAttribPointer(this.m_colorLoc, 3, gl.FLOAT, false, 0, 0);
1035 gl.drawElements(gl.LINE_STRIP, numBytesToVerify, gl.UNSIGNED_BYTE, offset + curOffset);
1036 indexBufferImg.readViewport(gl);
1038 // Step 2: Do manual fetch and render without index buffer.
1039 glsBufferTestUtil.execVertexFetch(fetchedPos, positions, refPtr.subarray(offset + curOffset), numBytesToVerify);
1040 glsBufferTestUtil.execVertexFetch(fetchedColor, colors, refPtr.subarray(offset + curOffset), numBytesToVerify);
1042 gl.clear(gl.COLOR_BUFFER_BIT);
1044 gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuf);
1045 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(fetchedPos), gl.STREAM_DRAW);
1046 gl.vertexAttribPointer(this.m_posLoc, 2, gl.FLOAT, false, 0, 0);
1048 gl.bindBuffer(gl.ARRAY_BUFFER, this.m_colorBuf);
1049 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(fetchedColor), gl.STREAM_DRAW);
1050 gl.vertexAttribPointer(this.m_colorLoc, 3, gl.FLOAT, false, 0, 0);
1052 gl.drawArrays(gl.LINE_STRIP, 0, numBytesToVerify);
1053 referenceImg.readViewport(gl, [0, 0, viewportW, viewportH]);
1055 if (!tcuImageCompare.pixelThresholdCompare('RenderResult', imageSetDesc, referenceImg, indexBufferImg, threshold.toIVec(), tcuImageCompare.CompareLogMode.RESULT)) {
1056 isOk = false;
1057 break;
1060 numVerified += isLeftoverBatch ? numRemaining : numBytesToVerify;
1063 gl.bindVertexArray(null);
1065 return isOk;