Bug 1918529 - fix some subpixel misalignment issues with gfx.webrender.svg-filter...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / modules / shared / glsDrawTests.js
blobeb7a4b2935d383c642813b16c34d2964f0845fc0
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.glsDrawTests');
23 goog.require('framework.common.tcuFloat');
24 goog.require('framework.common.tcuImageCompare');
25 goog.require('framework.common.tcuPixelFormat');
26 goog.require('framework.common.tcuRGBA');
27 goog.require('framework.common.tcuSurface');
28 goog.require('framework.common.tcuTestCase');
29 goog.require('framework.common.tcuTextureUtil');
30 goog.require('framework.delibs.debase.deMath');
31 goog.require('framework.delibs.debase.deRandom');
32 goog.require('framework.opengl.gluShaderUtil');
33 goog.require('framework.opengl.gluStrUtil');
34 goog.require('framework.opengl.simplereference.sglrGLContext');
35 goog.require('framework.opengl.simplereference.sglrReferenceContext');
36 goog.require('framework.opengl.simplereference.sglrShaderProgram');
37 goog.require('framework.referencerenderer.rrFragmentOperations');
38 goog.require('framework.referencerenderer.rrGenericVector');
39 goog.require('framework.referencerenderer.rrShadingContext');
40 goog.require('framework.referencerenderer.rrVertexAttrib');
41 goog.require('framework.referencerenderer.rrVertexPacket');
43 goog.scope(function() {
45 var glsDrawTests = modules.shared.glsDrawTests;
46 var tcuTestCase = framework.common.tcuTestCase;
47 var tcuRGBA = framework.common.tcuRGBA;
48 var tcuFloat = framework.common.tcuFloat;
49 var tcuPixelFormat = framework.common.tcuPixelFormat;
50 var tcuSurface = framework.common.tcuSurface;
51 var tcuImageCompare = framework.common.tcuImageCompare;
52 var tcuTextureUtil = framework.common.tcuTextureUtil;
53 var gluShaderUtil = framework.opengl.gluShaderUtil;
54 var gluStrUtil = framework.opengl.gluStrUtil;
55 var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
56 var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
57 var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
58 var deMath = framework.delibs.debase.deMath;
59 var deRandom = framework.delibs.debase.deRandom;
60 var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
61 var rrGenericVector = framework.referencerenderer.rrGenericVector;
62 var rrShadingContext = framework.referencerenderer.rrShadingContext;
63 var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
64 var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
66 /** @const {number} */ glsDrawTests.MAX_RENDER_TARGET_SIZE = 512;
68 // Utils
70 /**
71 * @param {glsDrawTests.DrawTestSpec.Target} target
72 * @return {number}
74 glsDrawTests.targetToGL = function(target) {
75 assertMsgOptions(target != null, 'Target is null', false, true);
77 var targets = [
78 gl.ELEMENT_ARRAY_BUFFER, // TARGET_ELEMENT_ARRAY = 0,
79 gl.ARRAY_BUFFER // TARGET_ARRAY,
82 return targets[target];
85 /**
86 * @param {?glsDrawTests.DrawTestSpec.Usage} usage
87 * @return {number}
89 glsDrawTests.usageToGL = function(usage) {
90 assertMsgOptions(usage != null, 'Usage is null', false, true);
92 var usages = [
93 gl.DYNAMIC_DRAW, // USAGE_DYNAMIC_DRAW = 0,
94 gl.STATIC_DRAW, // USAGE_STATIC_DRAW,
95 gl.STREAM_DRAW, // USAGE_STREAM_DRAW,
97 gl.STREAM_READ, // USAGE_STREAM_READ,
98 gl.STREAM_COPY, // USAGE_STREAM_COPY,
100 gl.STATIC_READ, // USAGE_STATIC_READ,
101 gl.STATIC_COPY, // USAGE_STATIC_COPY,
103 gl.DYNAMIC_READ, // USAGE_DYNAMIC_READ,
104 gl.DYNAMIC_COPY // USAGE_DYNAMIC_COPY,
106 assertMsgOptions(usages.length == Object.keys(glsDrawTests.DrawTestSpec.Usage).length,
107 'Amount of usage gl vlaues is different from amount of usages', false, true);
109 return usages[usage];
113 * @param {?glsDrawTests.DrawTestSpec.InputType} type
114 * @return {number}
116 glsDrawTests.inputTypeToGL = function(type) {
117 assertMsgOptions(type != null, 'Input type is null', false, true);
119 var types = [
120 gl.FLOAT, // INPUTTYPE_FLOAT = 0,
121 gl.BYTE, // INPUTTYPE_BYTE,
122 gl.SHORT, // INPUTTYPE_SHORT,
123 gl.UNSIGNED_BYTE, // INPUTTYPE_UNSIGNED_BYTE,
124 gl.UNSIGNED_SHORT, // INPUTTYPE_UNSIGNED_SHORT,
126 gl.INT, // INPUTTYPE_INT,
127 gl.UNSIGNED_INT, // INPUTTYPE_UNSIGNED_INT,
128 gl.HALF_FLOAT, // INPUTTYPE_HALF,
129 gl.UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
130 gl.INT_2_10_10_10_REV // INPUTTYPE_INT_2_10_10_10,
132 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
133 'Amount of gl input types is different from amount of input types', false, true);
135 return types[type];
139 * @param {?glsDrawTests.DrawTestSpec.OutputType} type
140 * @return {string}
142 glsDrawTests.outputTypeToGLType = function(type) {
143 assertMsgOptions(type != null, 'Output type is null', false, true);
145 var types = [
146 'float', // OUTPUTTYPE_FLOAT = 0,
147 'vec2', // OUTPUTTYPE_VEC2,
148 'vec3', // OUTPUTTYPE_VEC3,
149 'vec4', // OUTPUTTYPE_VEC4,
151 'int', // OUTPUTTYPE_INT,
152 'uint', // OUTPUTTYPE_UINT,
154 'ivec2', // OUTPUTTYPE_IVEC2,
155 'ivec3', // OUTPUTTYPE_IVEC3,
156 'ivec4', // OUTPUTTYPE_IVEC4,
158 'uvec2', // OUTPUTTYPE_UVEC2,
159 'uvec3', // OUTPUTTYPE_UVEC3,
160 'uvec4' // OUTPUTTYPE_UVEC4,
162 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.OutputType).length,
163 'Amount of output type names is different than amount of output types', false, true);
165 return types[type];
169 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
170 * @return {number}
172 glsDrawTests.primitiveToGL = function(primitive) {
173 var primitives = [
174 gl.POINTS, // PRIMITIVE_POINTS = 0,
175 gl.TRIANGLES, // PRIMITIVE_TRIANGLES,
176 gl.TRIANGLE_FAN, // PRIMITIVE_TRIANGLE_FAN,
177 gl.TRIANGLE_STRIP, // PRIMITIVE_TRIANGLE_STRIP,
178 gl.LINES, // PRIMITIVE_LINES
179 gl.LINE_STRIP, // PRIMITIVE_LINE_STRIP
180 gl.LINE_LOOP
182 assertMsgOptions(primitives.length == Object.keys(glsDrawTests.DrawTestSpec.Primitive).length,
183 'Amount of gl primitive values is different than amount of primitives', false, true);
185 return primitives[primitive];
189 * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType
190 * @return {number}
192 glsDrawTests.indexTypeToGL = function(indexType) {
193 var indexTypes = [
194 gl.UNSIGNED_BYTE, // INDEXTYPE_BYTE = 0,
195 gl.UNSIGNED_SHORT, // INDEXTYPE_SHORT,
196 gl.UNSIGNED_INT // INDEXTYPE_INT,
198 assertMsgOptions(indexTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
199 'Amount of gl index types is different than amount of index types', false, true);
201 return indexTypes[indexType];
205 * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType
206 * @return {?glsDrawTests.DrawTestSpec.InputType}
208 glsDrawTests.indexTypeToInputType = function(indexType) {
209 var inputTypes = [
210 glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE, // INDEXTYPE_BYTE = 0,
211 glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT, // INDEXTYPE_SHORT,
212 glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT // INDEXTYPE_INT,
214 assertMsgOptions(inputTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
215 'Amount of relevant input types is different than amount of index types', false, true);
217 return inputTypes[indexType];
221 * @param {?glsDrawTests.DrawTestSpec.InputType} type
222 * @return {boolean}
224 glsDrawTests.inputTypeIsFloatType = function(type) {
225 if (type == glsDrawTests.DrawTestSpec.InputType.FLOAT)
226 return true;
227 if (type == glsDrawTests.DrawTestSpec.InputType.HALF)
228 return true;
229 return false;
233 * @param {?glsDrawTests.DrawTestSpec.OutputType} type
234 * @return {boolean}
236 glsDrawTests.outputTypeIsFloatType = function(type) {
237 if (type == glsDrawTests.DrawTestSpec.OutputType.FLOAT ||
238 type == glsDrawTests.DrawTestSpec.OutputType.VEC2 ||
239 type == glsDrawTests.DrawTestSpec.OutputType.VEC3 ||
240 type == glsDrawTests.DrawTestSpec.OutputType.VEC4)
241 return true;
243 return false;
247 * @param {?glsDrawTests.DrawTestSpec.OutputType} type
248 * @return {boolean}
250 glsDrawTests.outputTypeIsIntType = function(type) {
251 if (type == glsDrawTests.DrawTestSpec.OutputType.INT ||
252 type == glsDrawTests.DrawTestSpec.OutputType.IVEC2 ||
253 type == glsDrawTests.DrawTestSpec.OutputType.IVEC3 ||
254 type == glsDrawTests.DrawTestSpec.OutputType.IVEC4)
255 return true;
257 return false;
261 * @param {?glsDrawTests.DrawTestSpec.OutputType} type
262 * @return {boolean}
264 glsDrawTests.outputTypeIsUintType = function(type) {
265 if (type == glsDrawTests.DrawTestSpec.OutputType.UINT ||
266 type == glsDrawTests.DrawTestSpec.OutputType.UVEC2 ||
267 type == glsDrawTests.DrawTestSpec.OutputType.UVEC3 ||
268 type == glsDrawTests.DrawTestSpec.OutputType.UVEC4)
269 return true;
271 return false;
275 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
276 * @param {number} primitiveCount
277 * @return {number}
279 glsDrawTests.getElementCount = function(primitive, primitiveCount) {
280 switch (primitive) {
281 case glsDrawTests.DrawTestSpec.Primitive.POINTS: return primitiveCount;
282 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES: return primitiveCount * 3;
283 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN: return primitiveCount + 2;
284 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP: return primitiveCount + 2;
285 case glsDrawTests.DrawTestSpec.Primitive.LINES: return primitiveCount * 2;
286 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP: return primitiveCount + 1;
287 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP: return (primitiveCount == 1) ? (2) : (primitiveCount);
288 default:
289 throw new Error('Invalid primitive');
293 //MethodInfo
296 * @typedef {{indexed: boolean, instanced: boolean, ranged: boolean, first: boolean}}
298 glsDrawTests.MethodInfo = {
299 /** @type {boolean} */ indexed: false,
300 /** @type {boolean} */ instanced: false,
301 /** @type {boolean} */ ranged: false,
302 /** @type {boolean} */ first: false
306 * @param {?glsDrawTests.DrawTestSpec.DrawMethod} method
307 * @return {glsDrawTests.MethodInfo}
309 glsDrawTests.getMethodInfo = function(method) {
310 /** @type {Array<glsDrawTests.MethodInfo>} */ var infos = [{
311 indexed: false, instanced: false, ranged: false, first: true //!< DRAWMETHOD_DRAWARRAYS,
313 indexed: false, instanced: true, ranged: false, first: true //!< DRAWMETHOD_DRAWARRAYS_INSTANCED,
315 indexed: true, instanced: false, ranged: false, first: false //!< DRAWMETHOD_DRAWELEMENTS,
317 indexed: true, instanced: false, ranged: true, first: false //!< DRAWMETHOD_DRAWELEMENTS_RANGED,
319 indexed: true, instanced: true, ranged: false, first: false //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED
323 assertMsgOptions(infos.length == Object.keys(glsDrawTests.DrawTestSpec.DrawMethod).length,
324 'Number of info names', false, true);
325 assertMsgOptions(method < infos.length, 'Invalid method', false, true);
326 return /** @type {glsDrawTests.MethodInfo} */ (infos[method]);
330 * @param {glsDrawTests.DrawTestSpec} a
331 * @param {glsDrawTests.DrawTestSpec} b
332 * @return {boolean}
334 glsDrawTests.checkSpecsShaderCompatible = function(a, b) {
335 // Only the attributes matter
336 if (a.attribs.length != b.attribs.length)
337 return false;
339 for (var ndx = 0; ndx < a.attribs.length; ++ndx) {
340 // Only the output type (== shader input type) matters and the usage in the shader.
342 if (a.attribs[ndx].additionalPositionAttribute != b.attribs[ndx].additionalPositionAttribute)
343 return false;
345 // component counts need not to match
346 if (glsDrawTests.outputTypeIsFloatType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsFloatType(b.attribs[ndx].outputType))
347 continue;
348 if (glsDrawTests.outputTypeIsIntType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsIntType(b.attribs[ndx].outputType))
349 continue;
350 if (glsDrawTests.outputTypeIsUintType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsUintType(b.attribs[ndx].outputType))
351 continue;
353 return false;
356 return true;
359 // generate random vectors in a way that does not depend on argument evaluation order
362 * @param {deRandom.Random} random
363 * @return {Array<number>}
365 glsDrawTests.generateRandomVec4 = function(random) {
366 /** @type {Array<number>} */ var retVal = [];
368 for (var i = 0; i < 4; ++i)
369 retVal[i] = random.getFloat();
371 return retVal;
375 * @param {deRandom.Random} random
376 * @return {Array<number>}
378 glsDrawTests.generateRandomIVec4 = function(random) {
379 /** @type {Array<number>} */ var retVal = [];
381 for (var i = 0; i < 4; ++i)
382 retVal[i] = random.getInt();
384 return retVal;
388 * @param {deRandom.Random} random
389 * @return {Array<number>}
391 glsDrawTests.generateRandomUVec4 = function(random) {
392 /** @type {Array<number>} */ var retVal = [];
394 for (var i = 0; i < 4; ++i)
395 retVal[i] = Math.abs(random.getInt());
397 return retVal;
400 //GLValue
403 * glsDrawTests.GLValue class
404 * @constructor
406 glsDrawTests.GLValue = function() {
407 /** @type {goog.NumberArray} */ this.m_value = [0];
408 /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.m_type;
412 * @param {goog.TypedArray} dst
413 * @param {glsDrawTests.GLValue} val
415 glsDrawTests.copyGLValueToArray = function(dst, val) {
416 /** @type {Uint8Array} */ var dst8 = new Uint8Array(dst.buffer).subarray(dst.byteOffset, dst.byteOffset + dst.byteLength);
417 /** @type {Uint8Array} */ var val8 = new Uint8Array(val.m_value.buffer); // TODO: Fix encapsulation issue
418 dst8.set(val8);
422 * @param {goog.TypedArray} dst
423 * @param {goog.TypedArray} src
425 glsDrawTests.copyArray = function(dst, src) {
426 /** @type {Uint8Array} */ var dst8 = new Uint8Array(dst.buffer).subarray(dst.byteOffset, dst.byteOffset + dst.byteLength);
427 /** @type {Uint8Array} */ var src8 = new Uint8Array(src.buffer).subarray(src.byteOffset, src.byteOffset + src.byteLength);
428 dst8.set(src8);
432 * typeToTypedArray function. Determines which type of array will store the value, and stores it.
433 * @param {number} value
434 * @param {?glsDrawTests.DrawTestSpec.InputType} type
436 glsDrawTests.GLValue.typeToTypedArray = function(value, type) {
437 var array;
439 switch (type) {
440 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
441 array = new Float32Array(1);
442 break;
444 case glsDrawTests.DrawTestSpec.InputType.BYTE:
445 array = new Int8Array(1);
446 break;
447 case glsDrawTests.DrawTestSpec.InputType.SHORT:
448 array = new Int16Array(1);
449 break;
451 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
452 array = new Uint8Array(1);
453 break;
454 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
455 array = new Uint16Array(1);
456 break;
458 case glsDrawTests.DrawTestSpec.InputType.INT:
459 array = new Int32Array(1);
460 break;
461 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
462 array = new Uint32Array(1);
463 break;
464 case glsDrawTests.DrawTestSpec.InputType.HALF:
465 array = new Uint16Array(1);
466 value = glsDrawTests.GLValue.floatToHalf(value);
467 break;
468 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10:
469 array = new Uint32Array(1);
470 break;
471 case glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10:
472 array = new Int32Array(1);
473 break;
474 default:
475 throw new Error('glsDrawTests.GLValue.typeToTypedArray - Invalid InputType');
478 array[0] = value;
479 return array;
483 * glsDrawTests.GLValue.create
484 * @param {number} value
485 * @param {?glsDrawTests.DrawTestSpec.InputType} type
487 glsDrawTests.GLValue.create = function(value, type) {
488 var v = new glsDrawTests.GLValue();
489 v.m_value = glsDrawTests.GLValue.typeToTypedArray(value, type);
490 v.m_type = type;
491 return v;
495 * glsDrawTests.GLValue.halfToFloat
496 * @param {number} value
497 * @return {number}
499 glsDrawTests.GLValue.halfToFloat = function(value) {
500 return tcuFloat.halfFloatToNumberNoDenorm(value);
504 * @param {number} f
505 * @return {number}
507 glsDrawTests.GLValue.floatToHalf = function(f) {
508 // No denorm support.
509 return tcuFloat.numberToHalfFloatNoDenorm(f);
513 * glsDrawTests.GLValue.getMaxValue
514 * @param {?glsDrawTests.DrawTestSpec.InputType} type
515 * @return {glsDrawTests.GLValue}
517 glsDrawTests.GLValue.getMaxValue = function(type) {
518 var value = 0;
520 assertMsgOptions(type >= 0 && type < Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
521 'Invalid type for GLValue', false, true);
523 switch (type) {
524 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
525 value = 127;
526 break;
527 case glsDrawTests.DrawTestSpec.InputType.BYTE:
528 value = 127;
529 break;
530 case glsDrawTests.DrawTestSpec.InputType.SHORT:
531 value = 32760;
532 break;
533 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
534 value = 255;
535 break;
536 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
537 value = 65530;
538 break;
539 case glsDrawTests.DrawTestSpec.InputType.INT:
540 value = 2147483647;
541 break;
542 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
543 value = 4294967295;
544 break;
545 case glsDrawTests.DrawTestSpec.InputType.HALF:
546 value = 256;
547 break;
548 default: //For any other valid type, return 0
549 value = 0;
552 return glsDrawTests.GLValue.create(value, type);
556 * glsDrawTests.GLValue.getMinValue
557 * @param {?glsDrawTests.DrawTestSpec.InputType} type
558 * @return {glsDrawTests.GLValue}
560 glsDrawTests.GLValue.getMinValue = function(type) {
561 var value = 0;
563 assertMsgOptions(type >= 0 && type < Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
564 'Invalid type for GLValue', false, true);
566 switch (type) {
567 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
568 value = -127;
569 break;
570 case glsDrawTests.DrawTestSpec.InputType.BYTE:
571 value = -127;
572 break;
573 case glsDrawTests.DrawTestSpec.InputType.SHORT:
574 value = -32760;
575 break;
576 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
577 value = 0;
578 break;
579 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
580 value = 0;
581 break;
582 case glsDrawTests.DrawTestSpec.InputType.INT:
583 value = -2147483647;
584 break;
585 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
586 value = 0;
587 break;
588 case glsDrawTests.DrawTestSpec.InputType.HALF:
589 value = -256;
590 break;
591 default: //For any other valid type, return 0
592 value = 0;
595 return glsDrawTests.GLValue.create(value, type);
599 * glsDrawTests.GLValue.getRandom
600 * @param {deRandom.Random} rnd
601 * @param {glsDrawTests.GLValue} min
602 * @param {glsDrawTests.GLValue} max
603 * @return {glsDrawTests.GLValue}
605 glsDrawTests.GLValue.getRandom = function(rnd, min, max) {
606 assertMsgOptions(min.getType() == max.getType(), 'Min and max types differ', false, true);
608 var minv = min.interpret();
609 var maxv = max.interpret();
610 var type = min.getType();
611 var value;
613 if (maxv < minv)
614 return min;
616 switch (type) {
617 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
618 case glsDrawTests.DrawTestSpec.InputType.HALF: {
619 return glsDrawTests.GLValue.create(minv + rnd.getFloat() * (maxv - minv), type);
620 break;
623 case glsDrawTests.DrawTestSpec.InputType.SHORT:
624 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
625 case glsDrawTests.DrawTestSpec.InputType.BYTE:
626 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
627 case glsDrawTests.DrawTestSpec.InputType.INT:
628 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: {
629 return glsDrawTests.GLValue.create(minv + rnd.getInt() % (maxv - minv), type);
630 break;
633 default:
634 throw new Error('glsDrawTests.GLValue.getRandom - Invalid input type');
635 break;
639 // Minimum difference required between coordinates
642 * @param {?glsDrawTests.DrawTestSpec.InputType} type
643 * @return {glsDrawTests.GLValue}
645 glsDrawTests.GLValue.minValue = function(type) {
646 switch (type) {
647 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
648 case glsDrawTests.DrawTestSpec.InputType.BYTE:
649 case glsDrawTests.DrawTestSpec.InputType.HALF:
650 return glsDrawTests.GLValue.create(4, type);
651 case glsDrawTests.DrawTestSpec.InputType.SHORT:
652 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
653 return glsDrawTests.GLValue.create(4 * 256, type);
654 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
655 return glsDrawTests.GLValue.create(4 * 2, type);
656 case glsDrawTests.DrawTestSpec.InputType.INT:
657 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
658 return glsDrawTests.GLValue.create(4 * 16777216, type);
660 default:
661 throw new Error('glsDrawTests.GLValue.minValue - Invalid input type');
666 * @param {glsDrawTests.GLValue} val
667 * @return {glsDrawTests.GLValue}
669 glsDrawTests.GLValue.abs = function(val) {
670 var type = val.getType();
671 switch (type) {
672 case glsDrawTests.DrawTestSpec.InputType.SHORT:
673 return glsDrawTests.GLValue.create(0x7FFF & val.getValue(), type);
674 case glsDrawTests.DrawTestSpec.InputType.BYTE:
675 return glsDrawTests.GLValue.create(0x7F & val.getValue(), type);
676 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
677 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
678 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
679 return val;
680 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
681 case glsDrawTests.DrawTestSpec.InputType.HALF:
682 return glsDrawTests.GLValue.create(Math.abs(val.interpret()), type);
683 case glsDrawTests.DrawTestSpec.InputType.INT:
684 return glsDrawTests.GLValue.create(0x7FFFFFFF & val.getValue(), type);
685 default:
686 throw new Error('glsDrawTests.GLValue.abs - Invalid input type');
691 * @return {?glsDrawTests.DrawTestSpec.InputType}
693 glsDrawTests.GLValue.prototype.getType = function() {
694 return this.m_type;
698 * glsDrawTests.GLValue.toFloat
699 * @return {number}
701 glsDrawTests.GLValue.prototype.toFloat = function() {
702 return this.interpret();
706 * glsDrawTests.GLValue.getValue
707 * @return {number}
709 glsDrawTests.GLValue.prototype.getValue = function() {
710 return this.m_value[0];
714 * interpret function. Returns the m_value as a quantity so arithmetic operations can be performed on it
715 * Only some types require this.
716 * @return {number}
718 glsDrawTests.GLValue.prototype.interpret = function() {
719 if (this.m_type == glsDrawTests.DrawTestSpec.InputType.HALF)
720 return glsDrawTests.GLValue.halfToFloat(this.m_value[0]);
722 return this.m_value[0];
726 * @param {glsDrawTests.GLValue} other
727 * @return {glsDrawTests.GLValue}
729 glsDrawTests.GLValue.prototype.add = function(other) {
730 return glsDrawTests.GLValue.create(this.interpret() + other.interpret(), this.m_type);
734 * @param {glsDrawTests.GLValue} other
735 * @return {glsDrawTests.GLValue}
737 glsDrawTests.GLValue.prototype.mul = function(other) {
738 return glsDrawTests.GLValue.create(this.interpret() * other.interpret(), this.m_type);
742 * @param {glsDrawTests.GLValue} other
743 * @return {glsDrawTests.GLValue}
745 glsDrawTests.GLValue.prototype.div = function(other) {
746 return glsDrawTests.GLValue.create(this.interpret() / other.interpret(), this.m_type);
750 * @param {glsDrawTests.GLValue} other
751 * @return {glsDrawTests.GLValue}
753 glsDrawTests.GLValue.prototype.sub = function(other) {
754 return glsDrawTests.GLValue.create(this.interpret() - other.interpret(), this.m_type);
758 * @param {glsDrawTests.GLValue} other
759 * @return {glsDrawTests.GLValue}
761 glsDrawTests.GLValue.prototype.addToSelf = function(other) {
762 this.m_value[0] = this.interpret() + other.interpret();
763 return this;
767 * @param {glsDrawTests.GLValue} other
768 * @return {glsDrawTests.GLValue}
770 glsDrawTests.GLValue.prototype.subToSelf = function(other) {
771 this.m_value[0] = this.interpret() - other.interpret();
772 return this;
776 * @param {glsDrawTests.GLValue} other
777 * @return {glsDrawTests.GLValue}
779 glsDrawTests.GLValue.prototype.mulToSelf = function(other) {
780 this.m_value[0] = this.interpret() * other.interpret();
781 return this;
785 * @param {glsDrawTests.GLValue} other
786 * @return {glsDrawTests.GLValue}
788 glsDrawTests.GLValue.prototype.divToSelf = function(other) {
789 this.m_value[0] = this.interpret() / other.interpret();
790 return this;
794 * @param {glsDrawTests.GLValue} other
795 * @return {boolean}
797 glsDrawTests.GLValue.prototype.equals = function(other) {
798 return this.m_value[0] == other.getValue();
802 * @param {glsDrawTests.GLValue} other
803 * @return {boolean}
805 glsDrawTests.GLValue.prototype.lessThan = function(other) {
806 return this.interpret() < other.interpret();
810 * @param {glsDrawTests.GLValue} other
811 * @return {boolean}
813 glsDrawTests.GLValue.prototype.greaterThan = function(other) {
814 return this.interpret() > other.interpret();
818 * @param {glsDrawTests.GLValue} other
819 * @return {boolean}
821 glsDrawTests.GLValue.prototype.lessOrEqualThan = function(other) {
822 return this.interpret() <= other.interpret();
826 * @param {glsDrawTests.GLValue} other
827 * @return {boolean}
829 glsDrawTests.GLValue.prototype.greaterOrEqualThan = function(other) {
830 return this.interpret() >= other.interpret();
833 // AttriuteArray
836 * AttributeArray
837 * @constructor
838 * @param {?glsDrawTests.DrawTestSpec.Storage} storage
839 * @param {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} context
841 glsDrawTests.AttributeArray = function(storage, context) {
842 /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.m_storage = storage;
843 /** @type {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} */ this.m_ctx = context;
844 /** @type {WebGLBuffer|sglrReferenceContext.DataBuffer|null} */ this.m_glBuffer;
846 /** @type {number} */ this.m_size = 0;
847 /** @type {Uint8Array} */ this.m_data; //NOTE: Used in unsupported user storage
848 /** @type {number} */ this.m_componentCount;
849 /** @type {boolean} */ this.m_bound = false;
850 /** @type {glsDrawTests.DrawTestSpec.Target} */ this.m_target = glsDrawTests.DrawTestSpec.Target.ARRAY;
851 /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.m_inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT;
852 /** @type {?glsDrawTests.DrawTestSpec.OutputType} */ this.m_outputType = glsDrawTests.DrawTestSpec.OutputType.VEC4;
853 /** @type {boolean} */ this.m_normalize = false;
854 /** @type {number} */ this.m_stride = 0;
855 /** @type {number} */ this.m_offset = 0;
856 /** @type {Array<number>} */ this.m_defaultAttrib;
857 /** @type {number} */ this.m_instanceDivisor = 0;
858 /** @type {boolean} */ this.m_isPositionAttr = false;
860 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
861 this.m_glBuffer = this.m_ctx.createBuffer();
865 /** @return {number} */ glsDrawTests.AttributeArray.prototype.getComponentCount = function() {return this.m_componentCount;};
867 /** @return {?glsDrawTests.DrawTestSpec.Target} */ glsDrawTests.AttributeArray.prototype.getTarget = function() {return this.m_target;};
869 /** @return {?glsDrawTests.DrawTestSpec.InputType} */ glsDrawTests.AttributeArray.prototype.getInputType = function() {return this.m_inputType;};
871 /** @return {?glsDrawTests.DrawTestSpec.OutputType} */ glsDrawTests.AttributeArray.prototype.getOutputType = function() {return this.m_outputType;};
873 /** @return {?glsDrawTests.DrawTestSpec.Storage} */ glsDrawTests.AttributeArray.prototype.getStorageType = function() {return this.m_storage;};
875 /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.getNormalized = function() {return this.m_normalize;};
877 /** @return {number} */ glsDrawTests.AttributeArray.prototype.getStride = function() {return this.m_stride;};
879 /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.isBound = function() {return this.m_bound;};
881 /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.isPositionAttribute = function() {return this.m_isPositionAttr;};
884 * @param {glsDrawTests.DrawTestSpec.Target} target
885 * @param {number} size
886 * @param {goog.TypedArray} ptr
887 * @param {?glsDrawTests.DrawTestSpec.Usage} usage
889 glsDrawTests.AttributeArray.prototype.data = function(target, size, ptr, usage) {
890 this.m_size = size;
891 this.m_target = target;
893 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
894 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer);
895 this.m_ctx.bufferData(glsDrawTests.targetToGL(target), ptr, glsDrawTests.usageToGL(usage));
896 } else
897 throw new Error('Wrong storage type');
901 * @param {glsDrawTests.DrawTestSpec.Target} target
902 * @param {number} offset
903 * @param {number} size
904 * @param {goog.TypedArray} ptr
906 glsDrawTests.AttributeArray.prototype.subdata = function(target, offset, size, ptr) {
907 this.m_target = target;
909 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
910 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer);
912 this.m_ctx.bufferSubData(glsDrawTests.targetToGL(target), offset, size, ptr);
913 } else
914 throw new Error('Wrong storage type');
918 * @param {boolean} bound
919 * @param {number} offset
920 * @param {number} size
921 * @param {?glsDrawTests.DrawTestSpec.InputType} inputType
922 * @param {?glsDrawTests.DrawTestSpec.OutputType} outType
923 * @param {boolean} normalized
924 * @param {number} stride
925 * @param {number} instanceDivisor
926 * @param {Array<number>} defaultAttrib
927 * @param {boolean} isPositionAttr
929 glsDrawTests.AttributeArray.prototype.setupArray = function(bound, offset, size, inputType, outType,
930 normalized, stride, instanceDivisor, defaultAttrib, isPositionAttr) {
931 this.m_componentCount = size;
932 this.m_bound = bound;
933 this.m_inputType = inputType;
934 this.m_outputType = outType;
935 this.m_normalize = normalized;
936 this.m_stride = stride;
937 this.m_offset = offset;
938 this.m_defaultAttrib = defaultAttrib;
939 this.m_instanceDivisor = instanceDivisor;
940 this.m_isPositionAttr = isPositionAttr;
944 * @param {number} loc (32-bit)
946 glsDrawTests.AttributeArray.prototype.bindAttribute = function(loc) {
947 if (!this.isBound()) {
948 /** @type {Array<number>} */ var attr = this.m_defaultAttrib;
949 switch (this.m_inputType) {
950 case glsDrawTests.DrawTestSpec.InputType.FLOAT: {
951 switch (this.m_componentCount) {
952 case 1: this.m_ctx.vertexAttrib1f(loc, attr[0]); break;
953 case 2: this.m_ctx.vertexAttrib2f(loc, attr[0], attr[1]); break;
954 case 3: this.m_ctx.vertexAttrib3f(loc, attr[0], attr[1], attr[2]); break;
955 case 4: this.m_ctx.vertexAttrib4f(loc, attr[0], attr[1], attr[2], attr[3]); break;
956 default: throw new Error('Invalid component count'); break;
958 break;
960 case glsDrawTests.DrawTestSpec.InputType.INT: {
961 this.m_ctx.vertexAttribI4i(loc, attr[0], attr[1], attr[2], attr[3]);
962 break;
964 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: {
965 this.m_ctx.vertexAttribI4ui(loc, attr[0], attr[1], attr[2], attr[3]);
966 break;
968 default:
969 throw new Error('Invalid input type');
970 break;
972 } else {
973 /** @type {Uint8Array} */ var basePtr = null;
975 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
976 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(this.m_target), this.m_glBuffer);
978 basePtr = null;
979 } else
980 throw new Error('Invalid storage type');
982 if (!glsDrawTests.inputTypeIsFloatType(this.m_inputType)) {
983 // Input is not float type
985 if (glsDrawTests.outputTypeIsFloatType(this.m_outputType)) {
986 var size = this.m_componentCount;
988 // Output type is float type
989 this.m_ctx.vertexAttribPointer(loc, size, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_offset);
990 } else {
991 // Output type is int type
992 this.m_ctx.vertexAttribIPointer(loc, this.m_componentCount, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_stride, this.m_offset);
994 } else {
995 // Input type is float type
997 // Output type must be float type
998 assertMsgOptions(glsDrawTests.outputTypeIsFloatType(this.m_outputType), 'Output type is not float', false, true);
1000 this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_normalize,
1001 this.m_stride, this.m_offset);
1004 if (this.m_instanceDivisor)
1005 this.m_ctx.vertexAttribDivisor(loc, this.m_instanceDivisor);
1010 * @param {glsDrawTests.DrawTestSpec.Target} target
1012 glsDrawTests.AttributeArray.prototype.bindIndexArray = function(target) {
1013 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
1014 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer);
1018 // DrawTestShaderProgram
1021 * @constructor
1022 * @extends {sglrShaderProgram.ShaderProgram}
1023 * @param {Array<glsDrawTests.AttributeArray>} arrays
1025 glsDrawTests.DrawTestShaderProgram = function(arrays) {
1026 sglrShaderProgram.ShaderProgram.call(this, this.createProgramDeclaration(arrays));
1028 this.m_componentCount = [];
1029 this.m_isCoord = [];
1030 this.m_attrType = [];
1032 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
1033 this.m_componentCount[arrayNdx] = this.getComponentCount(arrays[arrayNdx].getOutputType());
1034 this.m_isCoord[arrayNdx] = arrays[arrayNdx].isPositionAttribute();
1035 this.m_attrType[arrayNdx] = this.mapOutputType(arrays[arrayNdx].getOutputType());
1039 glsDrawTests.DrawTestShaderProgram.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
1040 glsDrawTests.DrawTestShaderProgram.prototype.constructor = glsDrawTests.DrawTestShaderProgram;
1043 * @param {Array<number>} color
1044 * @param {goog.NumberArray} attribValue
1045 * @param {number} numComponents
1046 * @return {Array<number>}
1048 glsDrawTests.calcShaderColor = function(color, attribValue, numComponents) {
1049 switch (numComponents) {
1050 case 1:
1051 color[0] = deMath.scale(color, attribValue[0])[0];
1052 break;
1054 case 2:
1055 color[0] = color[0] * attribValue[0];
1056 color[1] = color[1] * attribValue[1];
1057 break;
1059 case 3:
1060 color[0] = color[0] * attribValue[0];
1061 color[1] = color[1] * attribValue[1];
1062 color[2] = color[2] * attribValue[2];
1063 break;
1065 case 4:
1066 color[0] = color[0] * attribValue[0] * attribValue[3];
1067 color[1] = color[1] * attribValue[1] * attribValue[3];
1068 color[2] = color[2] * attribValue[2] * attribValue[3];
1069 break;
1071 default:
1072 throw new Error('Invalid component count');
1075 return color;
1079 * @param {Array<number>} coord
1080 * @param {goog.NumberArray} attribValue
1081 * @param {number} numComponents
1082 * @return {Array<number>}
1084 glsDrawTests.calcShaderCoord = function(coord, attribValue, numComponents) {
1085 switch (numComponents) {
1086 case 1:
1088 coord = deMath.add(coord, [attribValue[0], attribValue[0]]);
1089 coord[0] = coord[0];
1090 coord[1] = coord[1];
1091 break;
1092 case 2:
1093 coord = deMath.add(coord, [attribValue[0], attribValue[1]]);
1094 coord[0] = coord[0];
1095 coord[1] = coord[1];
1096 break;
1097 case 3:
1098 coord = deMath.add(coord, [attribValue[0] + attribValue[2], attribValue[1]]);
1099 coord[0] = coord[0];
1100 coord[1] = coord[1];
1101 coord[2] = coord[2];
1102 break;
1103 case 4:
1104 coord = deMath.add(coord, [attribValue[0] + attribValue[2], attribValue[1] + attribValue[3]]);
1105 coord[0] = coord[0];
1106 coord[1] = coord[1];
1107 coord[2] = coord[2];
1108 coord[3] = coord[3];
1109 break;
1111 default:
1112 throw new Error('Invalid component count');
1115 return coord;
1119 * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
1120 * @param {Array<rrVertexPacket.VertexPacket>} packets
1121 * @param {number} numPackets
1123 glsDrawTests.DrawTestShaderProgram.prototype.shadeVertices = function(inputs, packets, numPackets) {
1124 var u_coordScale = this.getUniformByName('u_coordScale').value;
1125 var u_colorScale = this.getUniformByName('u_colorScale').value;
1127 for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
1128 var varyingLocColor = 0;
1130 /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
1132 // Calc output color
1133 /** @type {Array<number>} */ var coord = [0.0, 0.0];
1134 /** @type {Array<number>} */ var color = [1.0, 1.0, 1.0];
1136 for (var attribNdx = 0; attribNdx < this.m_attrType.length; attribNdx++) {
1137 var numComponents = this.m_componentCount[attribNdx];
1138 /** @type {boolean} */ var isCoord = this.m_isCoord[attribNdx];
1140 var attrib = rrVertexAttrib.readVertexAttrib(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx, this.m_attrType[attribNdx]);
1142 if (isCoord) {
1143 coord = glsDrawTests.calcShaderCoord(
1144 coord,
1145 attrib,
1146 numComponents
1148 } else {
1149 color = glsDrawTests.calcShaderColor(
1150 color,
1151 attrib,
1152 numComponents
1157 // Transform position
1158 packet.position = [u_coordScale * coord[0], u_coordScale * coord[1], 1.0, 1.0];
1159 packet.pointSize = 1.0;
1161 // Pass color to FS
1162 packet.outputs[varyingLocColor] = deMath.add(deMath.scale([u_colorScale * color[0], u_colorScale * color[1], u_colorScale * color[2], 1.0], 0.5), [0.5, 0.5, 0.5, 0.5]);
1167 * @param {Array<rrFragmentOperations.Fragment>} packets
1168 * @param {rrShadingContext.FragmentShadingContext} context
1170 glsDrawTests.DrawTestShaderProgram.prototype.shadeFragments = function(packets, context) {
1171 var varyingLocColor = 0;
1173 for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx) {
1174 /** @type {rrFragmentOperations.Fragment} */ var packet = packets[packetNdx];
1175 packet.value = rrShadingContext.readVarying(packet, context, varyingLocColor);
1180 * @param {Array<glsDrawTests.AttributeArray>} arrays
1181 * @return {string}
1183 glsDrawTests.DrawTestShaderProgram.prototype.genVertexSource = function(arrays) {
1184 /** @type {Array<string>}*/ var params;
1185 var vertexShaderTmpl = '';
1187 params = this.generateShaderParams();
1189 vertexShaderTmpl += params['VTX_HDR'];
1191 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
1192 vertexShaderTmpl += params['VTX_IN'] + ' highp ' + glsDrawTests.outputTypeToGLType(arrays[arrayNdx].getOutputType()) + ' a_' + arrayNdx + ';\n';
1195 vertexShaderTmpl +=
1196 'uniform highp float u_coordScale;\n' +
1197 'uniform highp float u_colorScale;\n' +
1198 params['VTX_OUT'] + ' ' + params['COL_PRECISION'] + ' vec4 v_color;\n' +
1199 'void main(void)\n' +
1200 '{\n' +
1201 '\tgl_PointSize = 1.0;\n' +
1202 '\thighp vec2 coord = vec2(0.0, 0.0);\n' +
1203 '\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n';
1205 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
1206 var isPositionAttr = arrays[arrayNdx].isPositionAttribute();
1208 if (isPositionAttr) {
1209 switch (arrays[arrayNdx].getOutputType()) {
1210 case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
1211 case glsDrawTests.DrawTestSpec.OutputType.INT:
1212 case glsDrawTests.DrawTestSpec.OutputType.UINT:
1213 vertexShaderTmpl +=
1214 '\tcoord += vec2(float(a_' + arrayNdx + '), float(a_' + arrayNdx + '));\n';
1215 break;
1217 case glsDrawTests.DrawTestSpec.OutputType.VEC2:
1218 case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
1219 case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
1220 vertexShaderTmpl +=
1221 '\tcoord += vec2(a_' + arrayNdx + '.xy);\n';
1222 break;
1224 case glsDrawTests.DrawTestSpec.OutputType.VEC3:
1225 case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
1226 case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
1227 vertexShaderTmpl +=
1228 '\tcoord += vec2(a_' + arrayNdx + '.xy);\n' +
1229 '\tcoord.x += float(a_' + arrayNdx + '.z);\n';
1230 break;
1232 case glsDrawTests.DrawTestSpec.OutputType.VEC4:
1233 case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
1234 case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
1235 vertexShaderTmpl +=
1236 '\tcoord += vec2(a_' + arrayNdx + '.xy);\n' +
1237 '\tcoord += vec2(a_' + arrayNdx + '.zw);\n';
1238 break;
1240 default:
1241 throw new Error('Invalid output type');
1242 break;
1244 } else {
1245 switch (arrays[arrayNdx].getOutputType()) {
1246 case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
1247 case glsDrawTests.DrawTestSpec.OutputType.INT:
1248 case glsDrawTests.DrawTestSpec.OutputType.UINT:
1249 vertexShaderTmpl +=
1250 '\tcolor = color * float(a_' + arrayNdx + ');\n';
1251 break;
1253 case glsDrawTests.DrawTestSpec.OutputType.VEC2:
1254 case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
1255 case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
1256 vertexShaderTmpl +=
1257 '\tcolor.rg = color.rg * vec2(a_' + arrayNdx + '.xy);\n';
1258 break;
1260 case glsDrawTests.DrawTestSpec.OutputType.VEC3:
1261 case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
1262 case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
1263 vertexShaderTmpl +=
1264 '\tcolor = color.rgb * vec3(a_' + arrayNdx + '.xyz);\n';
1265 break;
1267 case glsDrawTests.DrawTestSpec.OutputType.VEC4:
1268 case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
1269 case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
1270 vertexShaderTmpl +=
1271 '\tcolor = color.rgb * vec3(a_' + arrayNdx + '.xyz) * float(a_' + arrayNdx + '.w);\n';
1272 break;
1274 default:
1275 throw new Error('Invalid output type');
1276 break;
1281 vertexShaderTmpl +=
1282 '\tv_color = vec4(u_colorScale * color, 1.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);\n' +
1283 '\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n' +
1284 '}\n';
1286 return vertexShaderTmpl;
1290 * @return {string}
1292 glsDrawTests.DrawTestShaderProgram.prototype.genFragmentSource = function() {
1293 /** @type {Array<string>} */ var params;
1295 params = this.generateShaderParams();
1297 var fragmentShaderTmpl = params['FRAG_HDR'] +
1298 params['FRAG_IN'] + ' ' + params['COL_PRECISION'] + ' vec4 v_color;\n' +
1299 'void main(void)\n' +
1300 '{\n' +
1301 '\t' + params['FRAG_COLOR'] + '= v_color;\n' +
1302 '}\n';
1304 return fragmentShaderTmpl;
1308 * @return {Array<string>}
1310 glsDrawTests.DrawTestShaderProgram.prototype.generateShaderParams = function() {
1311 /** @type {Array<string>} */ var params = [];
1312 if (gluShaderUtil.isGLSLVersionSupported(gl, gluShaderUtil.GLSLVersion.V300_ES)) {
1313 params['VTX_IN'] = 'in';
1314 params['VTX_OUT'] = 'out';
1315 params['FRAG_IN'] = 'in';
1316 params['FRAG_COLOR'] = 'dEQP_FragColor';
1317 params['VTX_HDR'] = '#version 300 es\n';
1318 params['FRAG_HDR'] = '#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
1319 params['COL_PRECISION'] = 'mediump';
1320 } else if (gluShaderUtil.isGLSLVersionSupported(gl, gluShaderUtil.GLSLVersion.V100_ES)) {
1321 params['VTX_IN'] = 'attribute';
1322 params['VTX_OUT'] = 'varying';
1323 params['FRAG_IN'] = 'varying';
1324 params['FRAG_COLOR'] = 'gl_FragColor';
1325 params['VTX_HDR'] = '';
1326 params['FRAG_HDR'] = '';
1327 params['COL_PRECISION'] = 'mediump';
1328 } else
1329 throw new Error('Invalid GL version');
1331 return params;
1335 * @param {?glsDrawTests.DrawTestSpec.OutputType} type
1336 * @return {rrGenericVector.GenericVecType}
1338 glsDrawTests.DrawTestShaderProgram.prototype.mapOutputType = function(type) {
1339 switch (type) {
1340 case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
1341 case glsDrawTests.DrawTestSpec.OutputType.VEC2:
1342 case glsDrawTests.DrawTestSpec.OutputType.VEC3:
1343 case glsDrawTests.DrawTestSpec.OutputType.VEC4:
1344 return rrGenericVector.GenericVecType.FLOAT;
1346 case glsDrawTests.DrawTestSpec.OutputType.INT:
1347 case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
1348 case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
1349 case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
1350 return rrGenericVector.GenericVecType.INT32;
1352 case glsDrawTests.DrawTestSpec.OutputType.UINT:
1353 case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
1354 case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
1355 case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
1356 return rrGenericVector.GenericVecType.UINT32;
1358 default:
1359 throw new Error('Invalid output type');
1364 * @param {?glsDrawTests.DrawTestSpec.OutputType} type
1365 * @return {number}
1367 glsDrawTests.DrawTestShaderProgram.prototype.getComponentCount = function(type) {
1368 switch (type) {
1369 case glsDrawTests.DrawTestSpec.OutputType.FLOAT:
1370 case glsDrawTests.DrawTestSpec.OutputType.INT:
1371 case glsDrawTests.DrawTestSpec.OutputType.UINT:
1372 return 1;
1374 case glsDrawTests.DrawTestSpec.OutputType.VEC2:
1375 case glsDrawTests.DrawTestSpec.OutputType.IVEC2:
1376 case glsDrawTests.DrawTestSpec.OutputType.UVEC2:
1377 return 2;
1379 case glsDrawTests.DrawTestSpec.OutputType.VEC3:
1380 case glsDrawTests.DrawTestSpec.OutputType.IVEC3:
1381 case glsDrawTests.DrawTestSpec.OutputType.UVEC3:
1382 return 3;
1384 case glsDrawTests.DrawTestSpec.OutputType.VEC4:
1385 case glsDrawTests.DrawTestSpec.OutputType.IVEC4:
1386 case glsDrawTests.DrawTestSpec.OutputType.UVEC4:
1387 return 4;
1389 default:
1390 throw new Error('Invalid output type');
1395 * @param {Array<glsDrawTests.AttributeArray>} arrays
1396 * @return {sglrShaderProgram.ShaderProgramDeclaration}
1398 glsDrawTests.DrawTestShaderProgram.prototype.createProgramDeclaration = function(arrays) {
1399 /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
1401 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++)
1402 decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_' + arrayNdx, this.mapOutputType(arrays[arrayNdx].getOutputType())));
1404 decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
1405 decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
1407 decl.pushVertexSource(new sglrShaderProgram.VertexSource(this.genVertexSource(arrays)));
1408 decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(this.genFragmentSource()));
1410 decl.pushUniform(new sglrShaderProgram.Uniform('u_coordScale', gluShaderUtil.DataType.FLOAT));
1411 decl.pushUniform(new sglrShaderProgram.Uniform('u_colorScale', gluShaderUtil.DataType.FLOAT));
1413 return decl;
1417 * @typedef {glsDrawTests.RandomArrayGenerator}
1419 glsDrawTests.RandomArrayGenerator = {};
1422 * @param {goog.TypedArray} data
1423 * @param {?glsDrawTests.DrawTestSpec.InputType} type
1424 * @param {deRandom.Random} rnd
1425 * @param {glsDrawTests.GLValue} min
1426 * @param {glsDrawTests.GLValue} max
1428 glsDrawTests.RandomArrayGenerator.setData = function(data, type, rnd, min, max) {
1429 switch (type) {
1430 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
1431 case glsDrawTests.DrawTestSpec.InputType.SHORT:
1432 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT:
1433 case glsDrawTests.DrawTestSpec.InputType.BYTE:
1434 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE:
1435 case glsDrawTests.DrawTestSpec.InputType.INT:
1436 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
1437 case glsDrawTests.DrawTestSpec.InputType.HALF:
1438 glsDrawTests.copyGLValueToArray(data, glsDrawTests.GLValue.getRandom(rnd, min, max));
1439 break;
1440 default:
1441 throw new Error('Invalid input type');
1446 * createBasicArray
1447 * @param {number} seed
1448 * @param {number} elementCount
1449 * @param {number} componentCount
1450 * @param {number} offset
1451 * @param {number} stride
1452 * @param {?glsDrawTests.DrawTestSpec.InputType} type
1453 * @param {number} first
1454 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
1455 * @param {?goog.TypedArray} indices
1456 * @param {number} indexSize
1457 * @return {goog.TypedArray}
1459 glsDrawTests.RandomArrayGenerator.createArray = function(seed, elementCount, componentCount, offset, stride, type, first, primitive, indices, indexSize) {
1460 assertMsgOptions(componentCount >= 1 && componentCount <= 4, 'Unacceptable number of components', false, true);
1462 /** @type {glsDrawTests.GLValue} */ var min = glsDrawTests.GLValue.getMinValue(type);
1463 /** @type {glsDrawTests.GLValue} */ var max = glsDrawTests.GLValue.getMaxValue(type);
1465 var packed = type == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10 ||
1466 type == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10;
1467 /** @type {number} */ var limit10 = (1 << 10);
1468 /** @type {number} */ var limit2 = (1 << 2);
1471 /** @type {number} */ var componentSize = glsDrawTests.DrawTestSpec.inputTypeSize(type);
1472 /** @type {number} */ var elementSize = componentSize * componentCount;
1473 /** @type {number} */ var bufferSize = offset + Math.max(elementCount * stride, elementCount * elementSize);
1475 var data = new ArrayBuffer(bufferSize);
1476 var writePtr = new Uint8Array(data, offset);
1478 var previousComponentsFloat = [0, 0, 0, 0];
1479 var rnd = new deRandom.Random(seed);
1481 for (var vertexNdx = 0; vertexNdx < elementCount; vertexNdx++) {
1482 var components = [];
1484 for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
1485 var getRandomComponent = function() {
1486 // For packed formats we can't use GLValue
1487 if (packed) {
1488 if (componentNdx == 3) {
1489 return rnd.getInt() % limit2;
1490 } else {
1491 return rnd.getInt() % limit10;
1493 } else {
1494 return glsDrawTests.GLValue.getRandom(rnd, min, max);
1498 var component = getRandomComponent();
1499 var componentFloat = (component instanceof glsDrawTests.GLValue) ? component.toFloat() : component;
1501 // Try to not create vertex near previous
1502 if (vertexNdx != 0 && Math.abs(componentFloat - previousComponentsFloat[componentNdx]) < min.toFloat()) {
1503 // Too close, try again (but only once)
1504 component = getRandomComponent();
1505 componentFloat = (component instanceof glsDrawTests.GLValue) ? component.toFloat() : component;
1508 components.push(component);
1509 previousComponentsFloat[componentNdx] = componentFloat;
1512 if (packed) {
1513 var packedValue = deMath.binaryOp(
1514 deMath.shiftLeft(/** @type {Array<number>} */ (components)[3], 30), deMath.binaryOp(
1515 deMath.shiftLeft(/** @type {Array<number>} */ (components)[2], 20), deMath.binaryOp(
1516 deMath.shiftLeft(/** @type {Array<number>} */ (components)[1], 10), /** @type {Array<number>} */ (components)[0], deMath.BinaryOp.OR
1517 ), deMath.BinaryOp.OR
1518 ), deMath.BinaryOp.OR
1520 glsDrawTests.copyArray(writePtr, new Uint32Array([packedValue]));
1521 } else {
1522 for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
1523 glsDrawTests.copyGLValueToArray(writePtr.subarray(componentNdx * componentSize), components[componentNdx]);
1527 writePtr = writePtr.subarray(stride);
1530 return new Uint8Array(data);
1534 * @param {number} seed
1535 * @param {number} elementCount
1536 * @param {?glsDrawTests.DrawTestSpec.IndexType} type
1537 * @param {number} offset
1538 * @param {number} min
1539 * @param {number} max
1540 * @return {goog.TypedArray}
1542 glsDrawTests.RandomArrayGenerator.generateIndices = function(seed, elementCount, type, offset, min, max) {
1543 return glsDrawTests.RandomArrayGenerator.createIndices(seed, elementCount, offset, min, max, type);
1547 * @param {number} seed
1548 * @param {number} elementCount
1549 * @param {number} offset
1550 * @param {number} min
1551 * @param {number} max
1552 * @param {?glsDrawTests.DrawTestSpec.IndexType} type
1553 * @return {goog.TypedArray}
1555 glsDrawTests.RandomArrayGenerator.createIndices = function(seed, elementCount, offset, min, max, type) {
1556 /** @type {number}*/ var elementSize = glsDrawTests.DrawTestSpec.indexTypeSize(type);
1557 /** @type {number}*/ var bufferSize = offset + elementCount * elementSize;
1559 var data = new ArrayBuffer(bufferSize);
1560 var writePtr = new Uint8Array(data).subarray(offset);
1562 var rnd = new deRandom.Random(seed);
1564 /* TODO: get limits for given index type --> if (min < 0 || min > std::numeric_limits<T>::max() ||
1565 max < 0 || max > std::numeric_limits<T>::max() ||
1566 min > max)
1567 DE_ASSERT(!"Invalid range");*/
1569 // JS refrast requires shuffled unique keys
1570 var keys = [];
1571 for (var key = 0; key < elementCount; key++)
1572 keys.push(glsDrawTests.GLValue.create(key, glsDrawTests.indexTypeToInputType(type)));
1574 for (var elementNdx = 0; elementNdx < elementCount; ++elementNdx) {
1575 var randomkey = rnd.getInt(0, keys.length - 1);
1576 var ndx = keys[randomkey];
1578 keys.splice(randomkey, 1);
1580 glsDrawTests.copyArray(
1581 writePtr.subarray(elementSize * elementNdx),
1582 new Uint8Array(ndx.m_value.buffer)
1586 return new Uint8Array(data);
1590 * @param {number} seed
1591 * @param {?glsDrawTests.DrawTestSpec.InputType} type
1592 * @return {Array<number>}
1594 glsDrawTests.RandomArrayGenerator.generateAttributeValue = function(seed, type) {
1595 var random = new deRandom.Random(seed);
1597 switch (type) {
1598 case glsDrawTests.DrawTestSpec.InputType.FLOAT:
1599 return glsDrawTests.generateRandomVec4(random);
1601 case glsDrawTests.DrawTestSpec.InputType.INT:
1602 return glsDrawTests.generateRandomIVec4(random);
1604 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT:
1605 return glsDrawTests.generateRandomUVec4(random);
1607 default:
1608 throw new Error('Invalid attribute type');
1612 // AttributePack
1615 * @param {sglrReferenceContext.ReferenceContext | sglrGLContext.GLContext} drawContext
1616 * @param {Array<number>} screenSize (2 positive elements in array)
1617 * @param {boolean} useVao
1618 * @param {boolean} logEnabled
1619 * @constructor
1621 glsDrawTests.AttributePack = function(drawContext, screenSize, useVao, logEnabled) {
1622 /** @type {sglrReferenceContext.ReferenceContext | sglrGLContext.GLContext} */ this.m_ctx = drawContext;
1624 /** @type {Array<glsDrawTests.AttributeArray>} */ this.m_arrays = [];
1625 /** @type {sglrShaderProgram.ShaderProgram} */ this.m_program;
1626 /** @type {tcuSurface.Surface} */ this.m_screen = new tcuSurface.Surface(screenSize[0], screenSize[1]);
1627 /** @type {boolean} */ this.m_useVao = useVao;
1628 /** @type {boolean} */ this.m_logEnabled = logEnabled;
1629 /** @type {WebGLProgram | sglrShaderProgram.ShaderProgram | null} */ this.m_programID = null;
1630 /** @type {WebGLVertexArrayObject|sglrReferenceContext.VertexArray|null} */ this.m_vaoID = null;
1632 if (this.m_useVao)
1633 this.m_vaoID = this.m_ctx.createVertexArray();
1637 * @return {tcuSurface.Surface}
1639 glsDrawTests.AttributePack.prototype.getSurface = function() {
1640 return this.m_screen;
1644 * @param {number} i
1645 * @return {glsDrawTests.AttributeArray}
1647 glsDrawTests.AttributePack.prototype.getArray = function(i) {
1648 return this.m_arrays[i];
1652 * @return number
1654 glsDrawTests.AttributePack.prototype.getArrayCount = function() {
1655 return this.m_arrays.length;
1659 * @param {?glsDrawTests.DrawTestSpec.Storage} storage
1661 glsDrawTests.AttributePack.prototype.newArray = function(storage) {
1662 this.m_arrays.push(new glsDrawTests.AttributeArray(storage, this.m_ctx));
1666 * clearArrays
1668 glsDrawTests.AttributePack.prototype.clearArrays = function() {
1669 this.m_arrays.length = 0;
1673 * updateProgram
1675 glsDrawTests.AttributePack.prototype.updateProgram = function() {
1676 if (this.m_programID)
1677 this.m_ctx.deleteProgram(this.m_programID);
1679 this.m_program = new glsDrawTests.DrawTestShaderProgram(this.m_arrays);
1680 this.m_programID = this.m_ctx.createProgram(this.m_program);
1684 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive
1685 * @param {?glsDrawTests.DrawTestSpec.DrawMethod} drawMethod
1686 * @param {number} firstVertex
1687 * @param {number} vertexCount
1688 * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType
1689 * @param {number} indexOffset
1690 * @param {number} rangeStart
1691 * @param {number} rangeEnd
1692 * @param {number} instanceCount
1693 * @param {number} coordScale
1694 * @param {number} colorScale
1695 * @param {glsDrawTests.AttributeArray} indexArray
1697 glsDrawTests.AttributePack.prototype.render = function(primitive, drawMethod, firstVertex, vertexCount, indexType,
1698 indexOffset, rangeStart, rangeEnd, instanceCount, coordScale, colorScale, indexArray) {
1699 assertMsgOptions(this.m_program != null, 'Program is null', false, true);
1700 assertMsgOptions(this.m_programID != null, 'No context created program', false, true);
1702 this.m_ctx.viewport(0, 0, this.m_screen.getWidth(), this.m_screen.getHeight());
1703 this.m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
1704 this.m_ctx.clear(gl.COLOR_BUFFER_BIT);
1706 this.m_ctx.useProgram(this.m_programID);
1708 this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(this.m_programID, 'u_coordScale'), coordScale);
1709 this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(this.m_programID, 'u_colorScale'), colorScale);
1711 if (this.m_useVao)
1712 this.m_ctx.bindVertexArray(this.m_vaoID);
1714 if (indexArray)
1715 indexArray.bindIndexArray(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY);
1717 for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
1718 var attribName = '';
1719 attribName += 'a_' + arrayNdx;
1721 var loc = this.m_ctx.getAttribLocation(this.m_programID, attribName);
1723 if (this.m_arrays[arrayNdx].isBound())
1724 this.m_ctx.enableVertexAttribArray(loc);
1726 this.m_arrays[arrayNdx].bindAttribute(loc);
1729 if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS)
1730 this.m_ctx.drawArrays(glsDrawTests.primitiveToGL(primitive), firstVertex, vertexCount);
1731 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED)
1732 this.m_ctx.drawArraysInstanced(glsDrawTests.primitiveToGL(primitive), firstVertex, vertexCount, instanceCount);
1733 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS)
1734 this.m_ctx.drawElements(glsDrawTests.primitiveToGL(primitive), vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset);
1735 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED)
1736 this.m_ctx.drawRangeElements(glsDrawTests.primitiveToGL(primitive), rangeStart, rangeEnd, vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset);
1737 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED)
1738 this.m_ctx.drawElementsInstanced(glsDrawTests.primitiveToGL(primitive), vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset, instanceCount);
1739 else
1740 throw new Error('Invalid draw method');
1742 for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
1743 if (this.m_arrays[arrayNdx].isBound()) {
1744 var attribName = '';
1745 attribName += 'a_' + arrayNdx;
1747 var loc = this.m_ctx.getAttribLocation(this.m_programID, attribName);
1749 this.m_ctx.disableVertexAttribArray(loc);
1753 if (this.m_useVao)
1754 this.m_ctx.bindVertexArray(null);
1756 this.m_ctx.useProgram(null);
1757 this.m_screen.readViewport(this.m_ctx, [0 , 0, this.m_screen.getWidth(), this.m_screen.getHeight()]);
1760 // DrawTestSpec
1763 * @constructor
1765 glsDrawTests.DrawTestSpec = function() {
1766 /** @type {?glsDrawTests.DrawTestSpec.Primitive} */ this.primitive = null;
1767 /** @type {number} */ this.primitiveCount = 0; //!< number of primitives to draw (per instance)
1769 /** @type {?glsDrawTests.DrawTestSpec.DrawMethod} */ this.drawMethod = null;
1770 /** @type {?glsDrawTests.DrawTestSpec.IndexType} */ this.indexType = null; //!< used only if drawMethod = DrawElements*
1771 /** @type {number} */ this.indexPointerOffset = 0; //!< used only if drawMethod = DrawElements*
1772 /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.indexStorage = null; //!< used only if drawMethod = DrawElements*
1773 /** @type {number} */ this.first = 0; //!< used only if drawMethod = DrawArrays*
1774 /** @type {number} */ this.indexMin = 0; //!< used only if drawMethod = Draw*Ranged
1775 /** @type {number} */ this.indexMax = 0; //!< used only if drawMethod = Draw*Ranged
1776 /** @type {number} */ this.instanceCount = 0; //!< used only if drawMethod = Draw*Instanced or Draw*Indirect
1777 /** @type {number} */ this.indirectOffset = 0; //!< used only if drawMethod = Draw*Indirect
1778 /** @type {number} */ this.baseVertex = 0; //!< used only if drawMethod = DrawElementsIndirect or *BaseVertex
1780 /** @type {Array<glsDrawTests.DrawTestSpec.AttributeSpec>} */ this.attribs = [];
1784 * @param {glsDrawTests.DrawTestSpec.Target} target
1785 * @return {string}
1787 glsDrawTests.DrawTestSpec.targetToString = function(target) {
1788 assertMsgOptions(target != null, 'Target is null', false, true);
1790 var targets = [
1791 'element_array', // TARGET_ELEMENT_ARRAY = 0,
1792 'array' // TARGET_ARRAY,
1794 assertMsgOptions(targets.length == Object.keys(glsDrawTests.DrawTestSpec.Target).length,
1795 'The amount of target names is different than the amount of targets', false, true);
1797 return targets[target];
1801 * @param {?glsDrawTests.DrawTestSpec.InputType} type
1802 * @return {string}
1804 glsDrawTests.DrawTestSpec.inputTypeToString = function(type) {
1805 assertMsgOptions(type != null, 'Type is null', false, true);
1807 var types = [
1808 'float', // INPUTTYPE_FLOAT = 0,
1810 'byte', // INPUTTYPE_BYTE,
1811 'short', // INPUTTYPE_SHORT,
1813 'unsigned_byte', // INPUTTYPE_UNSIGNED_BYTE,
1814 'unsigned_short', // INPUTTYPE_UNSIGNED_SHORT,
1816 'int', // INPUTTYPE_INT,
1817 'unsigned_int', // INPUTTYPE_UNSIGNED_INT,
1818 'half', // INPUTTYPE_HALF,
1819 'unsigned_int2_10_10_10', // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
1820 'int2_10_10_10' // INPUTTYPE_INT_2_10_10_10,
1822 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
1823 'The amount of type names is different than the amount of types', false, true);
1825 return types[type];
1829 * @param {?glsDrawTests.DrawTestSpec.OutputType} type
1830 * @return {string}
1832 glsDrawTests.DrawTestSpec.outputTypeToString = function(type) {
1833 assertMsgOptions(type != null, 'Type is null', false, true);
1835 var types = [
1836 'float', // OUTPUTTYPE_FLOAT = 0,
1837 'vec2', // OUTPUTTYPE_VEC2,
1838 'vec3', // OUTPUTTYPE_VEC3,
1839 'vec4', // OUTPUTTYPE_VEC4,
1841 'int', // OUTPUTTYPE_INT,
1842 'uint', // OUTPUTTYPE_UINT,
1844 'ivec2', // OUTPUTTYPE_IVEC2,
1845 'ivec3', // OUTPUTTYPE_IVEC3,
1846 'ivec4', // OUTPUTTYPE_IVEC4,
1848 'uvec2', // OUTPUTTYPE_UVEC2,
1849 'uvec3', // OUTPUTTYPE_UVEC3,
1850 'uvec4' // OUTPUTTYPE_UVEC4,
1852 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.OutputType).length,
1853 'The amount of type names is different than the amount of types', false, true);
1855 return types[type];
1859 * @param {?glsDrawTests.DrawTestSpec.Usage} usage
1860 * @return {string}
1862 glsDrawTests.DrawTestSpec.usageTypeToString = function(usage) {
1863 assertMsgOptions(usage != null, 'Usage is null', false, true);
1865 var usages = [
1866 'dynamic_draw', // USAGE_DYNAMIC_DRAW = 0,
1867 'static_draw', // USAGE_STATIC_DRAW,
1868 'stream_draw', // USAGE_STREAM_DRAW,
1870 'stream_read', // USAGE_STREAM_READ,
1871 'stream_copy', // USAGE_STREAM_COPY,
1873 'static_read', // USAGE_STATIC_READ,
1874 'static_copy', // USAGE_STATIC_COPY,
1876 'dynamic_read', // USAGE_DYNAMIC_READ,
1877 'dynamic_copy' // USAGE_DYNAMIC_COPY,
1879 assertMsgOptions(usages.length == Object.keys(glsDrawTests.DrawTestSpec.Usage).length,
1880 'The amount of usage names is different than the amount of usages', false, true);
1882 return usages[usage];
1886 * @param {?glsDrawTests.DrawTestSpec.Storage} storage
1887 * @return {string}
1889 glsDrawTests.DrawTestSpec.storageToString = function(storage) {
1890 assertMsgOptions(storage != null, 'Storage is null', false, true);
1892 var storages = [
1893 'user_ptr', // STORAGE_USER = 0,
1894 'buffer' // STORAGE_BUFFER,
1896 assertMsgOptions(storages.length == Object.keys(glsDrawTests.DrawTestSpec.Storage).length,
1897 'The amount of storage names is different than the amount of storages', false, true);
1899 return storages[storage];
1903 * @param {glsDrawTests.DrawTestSpec.Primitive} primitive
1904 * @return {string}
1906 glsDrawTests.DrawTestSpec.primitiveToString = function(primitive) {
1907 assertMsgOptions(primitive != null, 'Primitive is null', false, true);
1909 var primitives = [
1910 'points', // PRIMITIVE_POINTS ,
1911 'triangles', // PRIMITIVE_TRIANGLES,
1912 'triangle_fan', // PRIMITIVE_TRIANGLE_FAN,
1913 'triangle_strip', // PRIMITIVE_TRIANGLE_STRIP,
1914 'lines', // PRIMITIVE_LINES
1915 'line_strip', // PRIMITIVE_LINE_STRIP
1916 'line_loop'
1918 assertMsgOptions(primitives.length == Object.keys(glsDrawTests.DrawTestSpec.Primitive).length,
1919 'The amount of primitive names is different than the amount of primitives', false, true);
1921 return primitives[primitive];
1925 * @param {?glsDrawTests.DrawTestSpec.IndexType} type
1926 * @return {string}
1928 glsDrawTests.DrawTestSpec.indexTypeToString = function(type) {
1929 assertMsgOptions(type != null, 'Index type is null', false, true);
1931 var indexTypes = [
1932 'byte', // INDEXTYPE_BYTE = 0,
1933 'short', // INDEXTYPE_SHORT,
1934 'int' // INDEXTYPE_INT,
1936 assertMsgOptions(indexTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
1937 'The amount of index type names is different than the amount of index types', false, true);
1939 return indexTypes[type];
1943 * @param {?glsDrawTests.DrawTestSpec.DrawMethod} method
1944 * @return {string}
1946 glsDrawTests.DrawTestSpec.drawMethodToString = function(method) {
1947 assertMsgOptions(method != null, 'Method is null', false, true);
1949 var methods = [
1950 'draw_arrays', //!< DRAWMETHOD_DRAWARRAYS
1951 'draw_arrays_instanced', //!< DRAWMETHOD_DRAWARRAYS_INSTANCED
1952 'draw_elements', //!< DRAWMETHOD_DRAWELEMENTS
1953 'draw_range_elements', //!< DRAWMETHOD_DRAWELEMENTS_RANGED
1954 'draw_elements_instanced' //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED
1956 assertMsgOptions(methods.length == Object.keys(glsDrawTests.DrawTestSpec.DrawMethod).length,
1957 'The amount of method names is different than the amount of methods', false, true);
1959 return methods[method];
1963 * @param {?glsDrawTests.DrawTestSpec.InputType} type
1964 * @return {number}
1966 glsDrawTests.DrawTestSpec.inputTypeSize = function(type) {
1967 assertMsgOptions(type != null, 'Input type is null', false, true);
1969 var size = [
1970 4, // INPUTTYPE_FLOAT = 0,
1972 1, // INPUTTYPE_BYTE,
1973 2, // INPUTTYPE_SHORT,
1975 1, // INPUTTYPE_UNSIGNED_BYTE,
1976 2, // INPUTTYPE_UNSIGNED_SHORT,
1978 4, // INPUTTYPE_INT,
1979 4, // INPUTTYPE_UNSIGNED_INT,
1980 2, // INPUTTYPE_HALF,
1981 4 / 4, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
1982 4 / 4 // INPUTTYPE_INT_2_10_10_10,
1984 assertMsgOptions(size.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length,
1985 'The amount of type names is different than the amount of types', false, true);
1987 return size[type];
1991 * @param {?glsDrawTests.DrawTestSpec.IndexType} type
1992 * @return {number}
1994 glsDrawTests.DrawTestSpec.indexTypeSize = function(type) {
1995 assertMsgOptions(type != null, 'Type is null', false, true);
1997 var size = [
1998 1, // INDEXTYPE_BYTE,
1999 2, // INDEXTYPE_SHORT,
2000 4 // INDEXTYPE_INT,
2002 assertMsgOptions(size.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length,
2003 'The amount of type names is different than the amount of types', false, true);
2005 return size[type];
2009 * @return {string}
2011 glsDrawTests.DrawTestSpec.prototype.getName = function() {
2012 /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
2013 /** @type {boolean} */ var hasFirst = methodInfo.first;
2014 /** @type {boolean} */ var instanced = methodInfo.instanced;
2015 /** @type {boolean} */ var ranged = methodInfo.ranged;
2016 /** @type {boolean} */ var indexed = methodInfo.indexed;
2018 var name = '';
2020 for (var ndx = 0; ndx < this.attribs.length; ++ndx) {
2021 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec}*/ var attrib = this.attribs[ndx];
2023 if (this.attribs.length > 1)
2024 name += 'attrib' + ndx + '_';
2026 if (ndx == 0 || attrib.additionalPositionAttribute)
2027 name += 'pos_';
2028 else
2029 name += 'col_';
2031 if (attrib.useDefaultAttribute) {
2032 name += 'non_array_' +
2033 glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '_' +
2034 attrib.componentCount + '_' +
2035 glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '_';
2036 } else {
2037 name += glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + '_' +
2038 attrib.offset + '_' +
2039 attrib.stride + '_' +
2040 glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType));
2041 if (attrib.inputType != glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 && attrib.inputType != glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10)
2042 name += attrib.componentCount;
2043 name += '_' +
2044 (attrib.normalize ? 'normalized_' : '') +
2045 glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '_' +
2046 glsDrawTests.DrawTestSpec.usageTypeToString(attrib.usage) + '_' +
2047 attrib.instanceDivisor + '_';
2051 if (indexed)
2052 name += 'index_' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '_' +
2053 glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '_' +
2054 'offset' + this.indexPointerOffset + '_';
2055 if (hasFirst)
2056 name += 'first' + this.first + '_';
2057 if (ranged)
2058 name += 'ranged_' + this.indexMin + '_' + this.indexMax + '_';
2059 if (instanced)
2060 name += 'instances' + this.instanceCount + '_';
2062 switch (this.primitive) {
2063 case glsDrawTests.DrawTestSpec.Primitive.POINTS:
2064 name += 'points_';
2065 break;
2066 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
2067 name += 'triangles_';
2068 break;
2069 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
2070 name += 'triangle_fan_';
2071 break;
2072 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
2073 name += 'triangle_strip_';
2074 break;
2075 case glsDrawTests.DrawTestSpec.Primitive.LINES:
2076 name += 'lines_';
2077 break;
2078 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
2079 name += 'line_strip_';
2080 break;
2081 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
2082 name += 'line_loop_';
2083 break;
2084 default:
2085 throw new Error('Invalid primitive');
2086 break;
2089 name += this.primitiveCount;
2091 return name;
2095 * @return {string}
2097 glsDrawTests.DrawTestSpec.prototype.getDesc = function() {
2098 var desc = '';
2100 for (var ndx = 0; ndx < this.attribs.length; ++ndx) {
2101 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attrib = this.attribs[ndx];
2103 if (attrib.useDefaultAttribute) {
2104 desc += 'Attribute ' + ndx + ': default, ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position ,') : ('color ,')) +
2105 'input datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + ', ' +
2106 'input component count ' + attrib.componentCount + ', ' +
2107 'used as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + ', ';
2108 } else {
2109 desc += 'Attribute ' + ndx + ': ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position ,') : ('color ,')) +
2110 'Storage in ' + glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + ', ' +
2111 'stride ' + attrib.stride + ', ' +
2112 'input datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + ', ' +
2113 'input component count ' + attrib.componentCount + ', ' +
2114 (attrib.normalize ? 'normalized, ' : '') +
2115 'used as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + ', ' +
2116 'instance divisor ' + attrib.instanceDivisor + ', ';
2120 if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) {
2121 desc += 'drawArrays(), ' +
2122 'first ' + this.first + ', ';
2123 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED) {
2124 desc += 'drawArraysInstanced(), ' +
2125 'first ' + this.first + ', ' +
2126 'instance count ' + this.instanceCount + ', ';
2127 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) {
2128 desc += 'drawElements(), ' +
2129 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' +
2130 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' +
2131 'index offset ' + this.indexPointerOffset + ', ';
2132 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED) {
2133 desc += 'drawElementsRanged(), ' +
2134 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' +
2135 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' +
2136 'index offset ' + this.indexPointerOffset + ', ' +
2137 'range start ' + this.indexMin + ', ' +
2138 'range end ' + this.indexMax + ', ';
2139 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) {
2140 desc += 'drawElementsInstanced(), ' +
2141 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' +
2142 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' +
2143 'index offset ' + this.indexPointerOffset + ', ' +
2144 'instance count ' + this.instanceCount + ', ';
2145 } else
2146 throw new Error('Invalid draw method');
2148 desc += this.primitiveCount;
2150 switch (this.primitive) {
2151 case glsDrawTests.DrawTestSpec.Primitive.POINTS:
2152 desc += 'points';
2153 break;
2154 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
2155 desc += 'triangles';
2156 break;
2157 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
2158 desc += 'triangles (fan)';
2159 break;
2160 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
2161 desc += 'triangles (strip)';
2162 break;
2163 case glsDrawTests.DrawTestSpec.Primitive.LINES:
2164 desc += 'lines';
2165 break;
2166 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
2167 desc += 'lines (strip)';
2168 break;
2169 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
2170 desc += 'lines (loop)';
2171 break;
2172 default:
2173 throw new Error('Invalid primitive');
2174 break;
2177 return desc;
2181 * @return {string}
2183 glsDrawTests.DrawTestSpec.prototype.getMultilineDesc = function() {
2184 var desc = '';
2186 for (var ndx = 0; ndx < this.attribs.length; ++ndx) {
2187 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attrib = this.attribs[ndx];
2189 if (attrib.useDefaultAttribute) {
2190 desc += 'Attribute ' + ndx + ': default, ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position\n') : ('color\n')) +
2191 '\tinput datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '\n' +
2192 '\tinput component count ' + attrib.componentCount + '\n' +
2193 '\tused as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '\n';
2194 } else {
2195 desc += 'Attribute ' + ndx + ': ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position\n') : ('color\n')) +
2196 '\tStorage in ' + glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + '\n' +
2197 '\tstride ' + attrib.stride + '\n' +
2198 '\tinput datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '\n' +
2199 '\tinput component count ' + attrib.componentCount + '\n' +
2200 (attrib.normalize ? '\tnormalized\n' : '') +
2201 '\tused as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '\n' +
2202 '\tinstance divisor ' + attrib.instanceDivisor + '\n';
2206 if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) {
2207 desc += 'drawArrays()\n' +
2208 '\tfirst ' + this.first + '\n';
2209 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED) {
2210 desc += 'drawArraysInstanced()\n' +
2211 '\tfirst ' + this.first + '\n' +
2212 '\tinstance count ' + this.instanceCount + '\n';
2213 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) {
2214 desc += 'drawElements()\n' +
2215 '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' +
2216 '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' +
2217 '\tindex offset ' + this.indexPointerOffset + '\n';
2218 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED) {
2219 desc += 'drawElementsRanged()\n' +
2220 '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' +
2221 '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' +
2222 '\tindex offset ' + this.indexPointerOffset + '\n' +
2223 '\trange start ' + this.indexMin + '\n' +
2224 '\trange end ' + this.indexMax + '\n';
2225 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) {
2226 desc += 'drawElementsInstanced()\n' +
2227 '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' +
2228 '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' +
2229 '\tindex offset ' + this.indexPointerOffset + '\n' +
2230 '\tinstance count ' + this.instanceCount + '\n';
2231 } else
2232 throw new Error('Invalid draw method');
2234 desc += '\t' + this.primitiveCount + ' ';
2236 switch (this.primitive) {
2237 case glsDrawTests.DrawTestSpec.Primitive.POINTS:
2238 desc += 'points';
2239 break;
2240 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
2241 desc += 'triangles';
2242 break;
2243 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
2244 desc += 'triangles (fan)';
2245 break;
2246 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
2247 desc += 'triangles (strip)';
2248 break;
2249 case glsDrawTests.DrawTestSpec.Primitive.LINES:
2250 desc += 'lines';
2251 break;
2252 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
2253 desc += 'lines (strip)';
2254 break;
2255 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
2256 desc += 'lines (loop)';
2257 break;
2258 default:
2259 throw new Error('Invalid primitive');
2260 break;
2263 desc += '\n';
2265 return desc;
2269 * @enum {number}
2271 glsDrawTests.DrawTestSpec.Target = {
2272 ELEMENT_ARRAY: 0,
2273 ARRAY: 1
2277 * @enum {number}
2279 glsDrawTests.DrawTestSpec.InputType = {
2280 FLOAT: 0,
2282 BYTE: 1,
2283 SHORT: 2,
2285 UNSIGNED_BYTE: 3,
2286 UNSIGNED_SHORT: 4,
2288 INT: 5,
2289 UNSIGNED_INT: 6,
2290 HALF: 7,
2291 UNSIGNED_INT_2_10_10_10: 8,
2292 INT_2_10_10_10: 9
2296 * @enum {number}
2298 glsDrawTests.DrawTestSpec.OutputType = {
2299 FLOAT: 0,
2300 VEC2: 1,
2301 VEC3: 2,
2302 VEC4: 3,
2304 INT: 4,
2305 UINT: 5,
2307 IVEC2: 6,
2308 IVEC3: 7,
2309 IVEC4: 8,
2311 UVEC2: 9,
2312 UVEC3: 10,
2313 UVEC4: 11
2317 * @enum {number}
2319 glsDrawTests.DrawTestSpec.Usage = {
2320 DYNAMIC_DRAW: 0,
2321 STATIC_DRAW: 1,
2322 STREAM_DRAW: 2,
2324 STREAM_READ: 3,
2325 STREAM_COPY: 4,
2327 STATIC_READ: 5,
2328 STATIC_COPY: 6,
2330 DYNAMIC_READ: 7,
2331 DYNAMIC_COPY: 8
2335 * @enum {number}
2337 glsDrawTests.DrawTestSpec.Storage = {
2338 USER: 0,
2339 BUFFER: 1
2343 * @enum {number}
2345 glsDrawTests.DrawTestSpec.Primitive = {
2346 POINTS: 0,
2347 TRIANGLES: 1,
2348 TRIANGLE_FAN: 2,
2349 TRIANGLE_STRIP: 3,
2350 LINES: 4,
2351 LINE_STRIP: 5,
2352 LINE_LOOP: 6
2356 * @enum {number}
2358 glsDrawTests.DrawTestSpec.IndexType = {
2359 BYTE: 0,
2360 SHORT: 1,
2361 INT: 2
2365 * @enum {number}
2367 glsDrawTests.DrawTestSpec.DrawMethod = {
2368 DRAWARRAYS: 0,
2369 DRAWARRAYS_INSTANCED: 1,
2370 DRAWELEMENTS: 2,
2371 DRAWELEMENTS_RANGED: 3,
2372 DRAWELEMENTS_INSTANCED: 4
2376 * @enum {number}
2378 glsDrawTests.DrawTestSpec.CompatibilityTestType = {
2379 NONE: 0,
2380 UNALIGNED_OFFSET: 1,
2381 UNALIGNED_STRIDE: 2
2385 * @return {number}
2387 glsDrawTests.DrawTestSpec.prototype.hash = function() {
2388 // Use only drawmode-relevant values in "hashing" as the unrelevant values might not be set (causing non-deterministic behavior).
2389 /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
2390 /** @type {boolean} */ var arrayed = methodInfo.first;
2391 /** @type {boolean} */ var instanced = methodInfo.instanced;
2392 /** @type {boolean} */ var ranged = methodInfo.ranged;
2393 /** @type {boolean} */ var indexed = methodInfo.indexed;
2395 /** @type {number} */ var indexHash = (!indexed) ? (0) : (this.indexType + 10 * this.indexPointerOffset + 100 * this.indexStorage);
2396 /** @type {number} */ var arrayHash = (!arrayed) ? (0) : (this.first);
2397 /** @type {number} */ var indexRangeHash = (!ranged) ? (0) : (this.indexMin + 10 * this.indexMax);
2398 /** @type {number} */ var instanceHash = (!instanced) ? (0) : (this.instanceCount);
2399 /** @type {number} */ var basicHash = this.primitive + 10 * this.primitiveCount + 100 * this.drawMethod;
2401 return indexHash + 3 * arrayHash + 5 * indexRangeHash + 7 * instanceHash + 13 * basicHash + 17 * this.attribs.length + 19 * this.primitiveCount;
2405 * @return {boolean}
2407 glsDrawTests.DrawTestSpec.prototype.valid = function() {
2408 assertMsgOptions(this.primitive != null, 'Primitive is null', false, true);
2409 assertMsgOptions(this.drawMethod != null, 'Draw method is null', false, true);
2411 var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
2413 if (methodInfo.ranged) {
2414 var maxIndexValue = 0;
2415 if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.BYTE)
2416 maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE).interpret();
2417 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.SHORT)
2418 maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT).interpret();
2419 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.INT)
2420 maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT).interpret();
2421 else
2422 throw new Error('Invalid index type');
2424 if (this.indexMin > this.indexMax)
2425 return false;
2426 if (this.indexMin < 0 || this.indexMax < 0)
2427 return false;
2428 if (this.indexMin > maxIndexValue || this.indexMax > maxIndexValue)
2429 return false;
2432 if (methodInfo.first && this.first < 0)
2433 return false;
2435 return true;
2439 * @return {glsDrawTests.DrawTestSpec.CompatibilityTestType}
2441 glsDrawTests.DrawTestSpec.prototype.isCompatibilityTest = function() {
2442 var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod);
2444 var bufferAlignmentBad = false;
2445 var strideAlignmentBad = false;
2447 // Attribute buffer alignment
2448 for (var ndx = 0; ndx < this.attribs.length; ++ndx)
2449 if (!this.attribs[ndx].isBufferAligned())
2450 bufferAlignmentBad = true;
2452 // Attribute stride alignment
2453 for (var ndx = 0; ndx < this.attribs.length; ++ndx)
2454 if (!this.attribs[ndx].isBufferStrideAligned())
2455 strideAlignmentBad = true;
2457 // Index buffer alignment
2458 if (methodInfo.indexed) {
2459 if (this.indexStorage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
2460 var indexSize = 0;
2461 if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.BYTE)
2462 indexSize = 1;
2463 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.SHORT)
2464 indexSize = 2;
2465 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.INT)
2466 indexSize = 4;
2467 else
2468 throw new Error('');
2470 if (this.indexPointerOffset % indexSize != 0)
2471 bufferAlignmentBad = true;
2475 // \note combination bad alignment & stride is treated as bad offset
2476 if (bufferAlignmentBad)
2477 return glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET;
2478 else if (strideAlignmentBad)
2479 return glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE;
2480 else
2481 return glsDrawTests.DrawTestSpec.CompatibilityTestType.NONE;
2484 // DrawTestSpec.AttributeSpec
2487 * @constructor
2489 glsDrawTests.DrawTestSpec.AttributeSpec = function() {
2490 /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.inputType = null;
2491 /** @type {?glsDrawTests.DrawTestSpec.OutputType} */ this.outputType = null;
2492 /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.storage = glsDrawTests.DrawTestSpec.Storage.BUFFER; //Always BUFFER in WebGL up to 2
2493 /** @type {?glsDrawTests.DrawTestSpec.Usage} */ this.usage = null;
2494 /** @type {number} */ this.componentCount = 0;
2495 /** @type {number} */ this.offset = 0;
2496 /** @type {number} */ this.stride = 0;
2497 /** @type {boolean} */ this.normalize = false;
2498 /** @type {number} */ this.instanceDivisor = 0; //!< used only if drawMethod = Draw*Instanced
2499 /** @type {boolean} */ this.useDefaultAttribute = false;
2501 /** @type {boolean} */ this.additionalPositionAttribute = false; //!< treat this attribute as position attribute. Attribute at index 0 is alway treated as such. False by default
2505 * @param {?glsDrawTests.DrawTestSpec.InputType} inputType
2506 * @param {?glsDrawTests.DrawTestSpec.OutputType} outputType
2507 * @param {?glsDrawTests.DrawTestSpec.Storage} storage
2508 * @param {?glsDrawTests.DrawTestSpec.Usage} usage
2509 * @param {number} componentCount
2510 * @param {number} offset
2511 * @param {number} stride
2512 * @param {boolean} normalize
2513 * @param {number} instanceDivisor
2514 * @return {glsDrawTests.DrawTestSpec.AttributeSpec}
2516 glsDrawTests.DrawTestSpec.AttributeSpec.createAttributeArray = function(inputType, outputType, storage, usage, componentCount,
2517 offset, stride, normalize, instanceDivisor) {
2518 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var spec;
2520 spec.inputType = inputType;
2521 spec.outputType = outputType;
2522 spec.storage = storage;
2523 spec.usage = usage;
2524 spec.componentCount = componentCount;
2525 spec.offset = offset;
2526 spec.stride = stride;
2527 spec.normalize = normalize;
2528 spec.instanceDivisor = instanceDivisor;
2530 spec.useDefaultAttribute = false;
2532 return spec;
2536 * @param {?glsDrawTests.DrawTestSpec.InputType} inputType
2537 * @param {?glsDrawTests.DrawTestSpec.OutputType} outputType
2538 * @param {number} componentCount
2539 * @return {glsDrawTests.DrawTestSpec.AttributeSpec}
2541 glsDrawTests.DrawTestSpec.AttributeSpec.createDefaultAttribute = function(inputType, outputType, componentCount) {
2542 assertMsgOptions(inputType == glsDrawTests.DrawTestSpec.InputType.INT || inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT || inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT, 'Invalid input type', false, true);
2543 assertMsgOptions(inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT || componentCount == 4, 'If not float, input type should have 4 components', false, true);
2545 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var spec;
2547 spec.inputType = inputType;
2548 spec.outputType = outputType;
2549 spec.storage = glsDrawTests.DrawTestSpec.Storage.BUFFER; //Always BUFFER in WebGL up to 2
2550 spec.usage = null;
2551 spec.componentCount = componentCount;
2552 spec.offset = 0;
2553 spec.stride = 0;
2554 spec.normalize = false;
2555 spec.instanceDivisor = 0;
2557 spec.useDefaultAttribute = true;
2559 return spec;
2563 * @return {number}
2565 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.hash = function() {
2566 if (this.useDefaultAttribute) {
2567 return 1 * this.inputType + 7 * this.outputType + 13 * this.componentCount;
2568 } else {
2569 return 1 * this.inputType + 2 * this.outputType + 3 * this.storage + 5 * this.usage + 7 * this.componentCount + 11 * this.offset + 13 * this.stride + 17 * (this.normalize ? 0 : 1) + 19 * this.instanceDivisor;
2574 * @return {boolean}
2576 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.valid = function(/*ctxType*/) {
2577 /** @type {boolean} */ var inputTypeFloat = this.inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT || this.inputType == glsDrawTests.DrawTestSpec.InputType.HALF;
2578 /** @type {boolean} */ var inputTypeUnsignedInteger = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10;
2579 /** @type {boolean} */ var inputTypeSignedInteger = this.inputType == glsDrawTests.DrawTestSpec.InputType.BYTE || this.inputType == glsDrawTests.DrawTestSpec.InputType.SHORT || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
2580 /** @type {boolean} */ var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
2582 /** @type {boolean} */ var outputTypeFloat = this.outputType == glsDrawTests.DrawTestSpec.OutputType.FLOAT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4;
2583 /** @type {boolean} */ var outputTypeSignedInteger = this.outputType == glsDrawTests.DrawTestSpec.OutputType.INT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4;
2584 /** @type {boolean} */ var outputTypeUnsignedInteger = this.outputType == glsDrawTests.DrawTestSpec.OutputType.UINT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4;
2586 if (this.useDefaultAttribute) {
2587 if (this.inputType != glsDrawTests.DrawTestSpec.InputType.INT && this.inputType != glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT && this.inputType != glsDrawTests.DrawTestSpec.InputType.FLOAT)
2588 return false;
2590 if (this.inputType != glsDrawTests.DrawTestSpec.InputType.FLOAT && this.componentCount != 4)
2591 return false;
2593 // no casting allowed (undefined results)
2594 if (this.inputType == glsDrawTests.DrawTestSpec.InputType.INT && !outputTypeSignedInteger)
2595 return false;
2596 if (this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT && !outputTypeUnsignedInteger)
2597 return false;
2600 if (inputTypePacked && this.componentCount != 4)
2601 return false;
2603 // Invalid conversions:
2605 // float -> [u]int
2606 if (inputTypeFloat && !outputTypeFloat)
2607 return false;
2609 // uint -> int (undefined results)
2610 if (inputTypeUnsignedInteger && outputTypeSignedInteger)
2611 return false;
2613 // int -> uint (undefined results)
2614 if (inputTypeSignedInteger && outputTypeUnsignedInteger)
2615 return false;
2617 // packed -> non-float (packed formats are converted to floats)
2618 if (inputTypePacked && !outputTypeFloat)
2619 return false;
2621 // Invalid normalize. Normalize is only valid if output type is float
2622 if (this.normalize && !outputTypeFloat)
2623 return false;
2625 return true;
2629 * @return {boolean}
2631 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.isBufferAligned = function() {
2632 var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
2634 // Buffer alignment, offset is a multiple of underlying data type size?
2635 if (this.storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
2636 var dataTypeSize = glsDrawTests.DrawTestSpec.inputTypeSize(this.inputType);
2637 if (inputTypePacked)
2638 dataTypeSize = 4;
2640 if (this.offset % dataTypeSize != 0)
2641 return false;
2644 return true;
2648 * @return {boolean}
2650 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.isBufferStrideAligned = function() {
2651 var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10;
2653 // Buffer alignment, offset is a multiple of underlying data type size?
2654 if (this.storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) {
2655 var dataTypeSize = glsDrawTests.DrawTestSpec.inputTypeSize(this.inputType);
2656 if (inputTypePacked)
2657 dataTypeSize = 4;
2659 if (this.stride % dataTypeSize != 0)
2660 return false;
2663 return true;
2667 * @constructor
2668 * @extends {tcuTestCase.DeqpTest}
2669 * @param {glsDrawTests.DrawTestSpec} spec
2670 * @param {string} name
2671 * @param {string} desc
2673 glsDrawTests.DrawTest = function(spec, name, desc) {
2674 tcuTestCase.DeqpTest.call(this, name, desc, spec);
2676 /** @type {WebGL2RenderingContext} */ this.m_renderCtx = gl;
2677 /** @type {tcuPixelFormat.PixelFormat} */ this.m_pixelformat = new tcuPixelFormat.PixelFormat(
2678 /** @type {number} */ (gl.getParameter(gl.RED_BITS)), /** @type {number} */ (gl.getParameter(gl.GREEN_BITS)),
2679 /** @type {number} */ (gl.getParameter(gl.BLUE_BITS)), /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS))
2682 /** @type {sglrReferenceContext.ReferenceContextBuffers} */ this.m_refBuffers = null;
2683 /** @type {sglrReferenceContext.ReferenceContext} */ this.m_refContext = null;
2684 /** @type {sglrGLContext.GLContext} */ this.m_glesContext = null;
2686 /** @type {glsDrawTests.AttributePack} */ this.m_glArrayPack = null;
2687 /** @type {glsDrawTests.AttributePack} */ this.m_rrArrayPack = null;
2689 /** @type {number} */ this.m_maxDiffRed = -1;
2690 /** @type {number} */ this.m_maxDiffGreen = -1;
2691 /** @type {number} */ this.m_maxDiffBlue = -1;
2693 /** @type {Array<glsDrawTests.DrawTestSpec>} */ this.m_specs = [];
2694 /** @type {Array<string>} */this.m_iteration_descriptions = [];
2695 /** @type {number} */ this.m_iteration = 0;
2697 if (spec)
2698 this.addIteration(spec);
2701 glsDrawTests.DrawTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
2702 glsDrawTests.DrawTest.prototype.constructor = glsDrawTests.DrawTest;
2705 * @param {glsDrawTests.DrawTestSpec} spec
2706 * @param {string=} description
2708 glsDrawTests.DrawTest.prototype.addIteration = function(spec, description) {
2709 // Validate spec
2710 /** @type {boolean} */ var validSpec = spec.valid();
2712 if (!validSpec)
2713 return;
2715 this.m_specs.push(spec);
2717 if (description)
2718 this.m_iteration_descriptions.push(description);
2719 else
2720 this.m_iteration_descriptions.push('');
2724 * init
2726 glsDrawTests.DrawTest.prototype.init = function() {
2727 var renderTargetWidth = Math.min(glsDrawTests.MAX_RENDER_TARGET_SIZE, gl.canvas.width);
2728 var renderTargetHeight = Math.min(glsDrawTests.MAX_RENDER_TARGET_SIZE, gl.canvas.height);
2729 /** @type {sglrReferenceContext.ReferenceContextLimits} */ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
2730 /** @type {boolean} */ var useVao = true;
2732 this.m_glesContext = new sglrGLContext.GLContext(gl);
2734 assertMsgOptions(this.m_specs.length > 0, 'Specs is empty', false, true);
2736 this.m_refBuffers = new sglrReferenceContext.ReferenceContextBuffers(this.m_pixelformat, 0, 0, renderTargetWidth, renderTargetHeight);
2737 this.m_refContext = new sglrReferenceContext.ReferenceContext(limits, this.m_refBuffers.getColorbuffer(), this.m_refBuffers.getDepthbuffer(), this.m_refBuffers.getStencilbuffer());
2739 this.m_glArrayPack = new glsDrawTests.AttributePack(this.m_glesContext, [renderTargetWidth, renderTargetHeight], useVao, true);
2740 this.m_rrArrayPack = new glsDrawTests.AttributePack(this.m_refContext, [renderTargetWidth, renderTargetHeight], useVao, false);
2742 this.m_maxDiffRed = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.redBits)));
2743 this.m_maxDiffGreen = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.greenBits)));
2744 this.m_maxDiffBlue = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.blueBits)));
2748 * @return {tcuTestCase.IterateResult}
2750 glsDrawTests.DrawTest.prototype.iterate = function() {
2751 var specNdx = Math.floor(this.m_iteration / 2);
2752 var drawStep = (this.m_iteration % 2) == 0;
2753 var compareStep = (this.m_iteration % 2) == 1;
2754 /** @type {tcuTestCase.IterateResult} */ var iterateResult = (this.m_iteration + 1 == this.m_specs.length * 2) ? (tcuTestCase.IterateResult.STOP) : (tcuTestCase.IterateResult.CONTINUE);
2755 /** @type {glsDrawTests.DrawTestSpec} */ var spec = this.m_specs[specNdx];
2756 var updateProgram = (this.m_iteration == 0) || (drawStep && !glsDrawTests.checkSpecsShaderCompatible(this.m_specs[specNdx], this.m_specs[specNdx - 1])); // try to use the same shader in all iterations
2758 if (drawStep && this.m_specs.length != 1)
2759 debug('Iteration ' + specNdx + ' of ' + (this.m_specs.length - 1) + ': ' + this.m_iteration_descriptions[specNdx]);
2761 this.m_iteration++;
2763 if (drawStep) {
2764 /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(spec.drawMethod);
2765 /** @type {boolean} */ var indexed = methodInfo.indexed;
2766 /** @type {boolean} */ var instanced = methodInfo.instanced;
2767 /** @type {boolean} */ var ranged = methodInfo.ranged;
2768 /** @type {boolean} */ var hasFirst = methodInfo.first;
2770 /** @type {number} */ var primitiveElementCount = glsDrawTests.getElementCount(spec.primitive, spec.primitiveCount); // !< elements to be drawn
2771 /** @type {number} */ var indexMin = (ranged) ? (spec.indexMin) : (0);
2772 /** @type {number} */ var firstAddition = (hasFirst) ? (spec.first) : (0);
2773 /** @type {number} */ var elementCount = primitiveElementCount + indexMin + firstAddition; // !< elements in buffer (buffer should have at least primitiveElementCount ACCESSIBLE (index range, first) elements)
2774 /** @type {number} */ var maxElementIndex = primitiveElementCount + indexMin + firstAddition - 1;
2775 /** @type {number} */ var indexMax = Math.max(0, (ranged) ? (deMath.clamp(spec.indexMax, 0, maxElementIndex)) : (maxElementIndex));
2776 /** @type {number} */ var coordScale = this.getCoordScale(spec);
2777 /** @type {number} */ var colorScale = this.getColorScale(spec);
2779 /** @type {Array<number>} */ var nullAttribValue = [];
2781 // Log info
2782 bufferedLogToConsole(spec.getMultilineDesc());
2784 // Data
2785 this.m_glArrayPack.clearArrays();
2786 this.m_rrArrayPack.clearArrays();
2788 // indices
2789 /** @type {number} */ var seed;
2790 /** @type {number} */ var indexElementSize;
2791 /** @type {number} */ var indexArraySize;
2792 /** @type {goog.TypedArray} */ var indexArray;
2793 /** @type {goog.TypedArray} */ var indexPointer;
2795 /** @type {glsDrawTests.AttributeArray}*/ var glArray;
2796 /** @type {glsDrawTests.AttributeArray}*/ var rrArray;
2798 if (indexed) {
2799 seed = spec.hash();
2800 indexElementSize = glsDrawTests.DrawTestSpec.indexTypeSize(spec.indexType);
2801 indexArraySize = spec.indexPointerOffset + indexElementSize * elementCount;
2802 indexArray = glsDrawTests.RandomArrayGenerator.generateIndices(seed, elementCount, spec.indexType, spec.indexPointerOffset, indexMin, indexMax);
2803 indexPointer = indexArray.subarray(spec.indexPointerOffset);
2805 glArray = new glsDrawTests.AttributeArray(spec.indexStorage, this.m_glesContext);
2806 rrArray = new glsDrawTests.AttributeArray(spec.indexStorage, this.m_refContext);
2808 glArray.data(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY, indexArraySize, indexArray, glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW);
2809 rrArray.data(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY, indexArraySize, indexArray, glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW);
2811 indexArray = null;
2814 // attributes
2815 for (var attribNdx = 0; attribNdx < spec.attribs.length; attribNdx++) {
2816 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[attribNdx];
2817 var isPositionAttr = (attribNdx == 0) || (attribSpec.additionalPositionAttribute);
2819 if (attribSpec.useDefaultAttribute) {
2820 seed = 10 * attribSpec.hash() + 100 * spec.hash() + attribNdx;
2821 /** @type {Array<number>} */ var attribValue = glsDrawTests.RandomArrayGenerator.generateAttributeValue(seed, attribSpec.inputType);
2823 // changed USER for BUFFER in JS version
2824 this.m_glArrayPack.newArray(glsDrawTests.DrawTestSpec.Storage.BUFFER);
2825 this.m_rrArrayPack.newArray(glsDrawTests.DrawTestSpec.Storage.BUFFER);
2827 this.m_glArrayPack.getArray(attribNdx).setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr);
2828 this.m_rrArrayPack.getArray(attribNdx).setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr);
2829 } else {
2830 seed = attribSpec.hash() + 100 * spec.hash() + attribNdx;
2831 /** @type {number} */ var elementSize = attribSpec.componentCount * glsDrawTests.DrawTestSpec.inputTypeSize(attribSpec.inputType);
2832 /** @type {number} */ var stride = (attribSpec.stride == 0) ? (elementSize) : (attribSpec.stride);
2833 /** @type {number} */ var evaluatedElementCount = (instanced && attribSpec.instanceDivisor > 0) ? (spec.instanceCount / attribSpec.instanceDivisor + 1) : (elementCount);
2834 /** @type {number} */ var referencedElementCount = (ranged) ? (Math.max(evaluatedElementCount, spec.indexMax + 1)) : (evaluatedElementCount);
2835 /** @type {number} */ var bufferSize = attribSpec.offset + stride * (referencedElementCount - 1) + elementSize;
2836 /** @type {goog.TypedArray} */ var data = glsDrawTests.RandomArrayGenerator.createArray(
2837 seed,
2838 referencedElementCount,
2839 attribSpec.componentCount,
2840 attribSpec.offset,
2841 stride,
2842 attribSpec.inputType,
2843 indexed ? 0 : spec.first,
2844 spec.primitive,
2845 indexed ? indexPointer : null,
2846 indexElementSize
2849 this.m_glArrayPack.newArray(attribSpec.storage);
2850 this.m_rrArrayPack.newArray(attribSpec.storage);
2852 this.m_glArrayPack.getArray(attribNdx).data(glsDrawTests.DrawTestSpec.Target.ARRAY, bufferSize, data, attribSpec.usage);
2853 this.m_rrArrayPack.getArray(attribNdx).data(glsDrawTests.DrawTestSpec.Target.ARRAY, bufferSize, data, attribSpec.usage);
2855 this.m_glArrayPack.getArray(attribNdx).setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr);
2856 this.m_rrArrayPack.getArray(attribNdx).setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr);
2858 data = null;
2862 // Shader program
2863 if (updateProgram) {
2864 this.m_glArrayPack.updateProgram();
2865 this.m_rrArrayPack.updateProgram();
2868 /** @type {glsDrawTests.DrawTestSpec.CompatibilityTestType} */ var ctype;
2870 // Draw
2871 try {
2872 // indices
2873 if (indexed) {
2874 this.m_glArrayPack.render(spec.primitive, spec.drawMethod, 0, primitiveElementCount, spec.indexType, spec.indexPointerOffset, spec.indexMin, spec.indexMax, spec.instanceCount, coordScale, colorScale, glArray);
2875 this.m_rrArrayPack.render(spec.primitive, spec.drawMethod, 0, primitiveElementCount, spec.indexType, spec.indexPointerOffset, spec.indexMin, spec.indexMax, spec.instanceCount, coordScale, colorScale, rrArray);
2876 } else {
2877 this.m_glArrayPack.render(spec.primitive, spec.drawMethod, spec.first, primitiveElementCount, null, 0, 0, 0, spec.instanceCount, coordScale, colorScale, null);
2878 this.m_rrArrayPack.render(spec.primitive, spec.drawMethod, spec.first, primitiveElementCount, null, 0, 0, 0, spec.instanceCount, coordScale, colorScale, null);
2880 } catch (err) {
2881 if (err instanceof wtu.GLErrorException) {
2882 // GL Errors are ok if the mode is not properly aligned
2883 ctype = spec.isCompatibilityTest();
2885 bufferedLogToConsole('Got error: ' + err.message);
2887 if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET)
2888 checkMessage(false, 'Failed to draw with unaligned buffers.');
2889 else if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE)
2890 checkMessage(false, 'Failed to draw with unaligned stride.');
2891 else
2892 throw err;
2895 } else if (compareStep) {
2896 if (!this.compare(spec.primitive)) {
2897 ctype = spec.isCompatibilityTest();
2899 if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET)
2900 checkMessage(false, 'Failed to draw with unaligned buffers.');
2901 else if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE)
2902 checkMessage(false, 'Failed to draw with unaligned stride.');
2903 else
2904 testFailedOptions('Image comparison failed.', false);
2905 return iterateResult;
2907 } else {
2908 testFailedOptions('Image comparison failed.', false);
2909 return tcuTestCase.IterateResult.STOP;
2912 if (iterateResult == tcuTestCase.IterateResult.STOP)
2913 testPassed('');
2915 return iterateResult;
2919 * @enum {number} PrimitiveClass
2921 glsDrawTests.PrimitiveClass = {
2922 POINT: 0,
2923 LINE: 1,
2924 TRIANGLE: 2
2928 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitiveType
2929 * @return {glsDrawTests.PrimitiveClass}
2931 glsDrawTests.getDrawPrimitiveClass = function(primitiveType) {
2932 switch (primitiveType) {
2933 case glsDrawTests.DrawTestSpec.Primitive.POINTS:
2934 return glsDrawTests.PrimitiveClass.POINT;
2936 case glsDrawTests.DrawTestSpec.Primitive.LINES:
2937 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP:
2938 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP:
2939 return glsDrawTests.PrimitiveClass.LINE;
2941 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES:
2942 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN:
2943 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP:
2944 return glsDrawTests.PrimitiveClass.TRIANGLE;
2946 default:
2947 throw new Error('Invalid primitive type');
2952 * @param {number} c1
2953 * @param {number} c2
2954 * @param {Array<number>} threshold
2955 * @return {boolean}
2957 glsDrawTests.compareUintRGB8 = function(c1, c2, threshold) {
2958 return (Math.abs(((c1 >> 16) & 0xff) - ((c2 >> 16) & 0xff)) <= threshold[0] && // Red
2959 Math.abs(((c1 >> 8) & 0xff) - ((c2 >> 8) & 0xff)) <= threshold[1] && // Green
2960 Math.abs((c1 & 0xff) - (c2 & 0xff)) <= threshold[2]); // Blue
2964 * @param {number} c1
2965 * @param {number} c2
2966 * @param {number} c3
2967 * @param {number} renderTargetDifference
2968 * @return {boolean}
2970 glsDrawTests.isEdgeTripletComponent = function(c1, c2, c3, renderTargetDifference) {
2971 /** @type {number} */ var roundingDifference = 2 * renderTargetDifference; // src and dst pixels rounded to different directions
2972 /** @type {number} */ var d1 = c2 - c1;
2973 /** @type {number} */ var d2 = c3 - c2;
2974 /** @type {number} */ var rampDiff = Math.abs(d2 - d1);
2976 return rampDiff > roundingDifference;
2980 * @param {tcuRGBA.RGBA} c1
2981 * @param {tcuRGBA.RGBA} c2
2982 * @param {tcuRGBA.RGBA} c3
2983 * @param {Array<number>} renderTargetThreshold
2984 * @return {boolean}
2986 glsDrawTests.isEdgeTriplet = function(c1, c2, c3, renderTargetThreshold) {
2987 // black (background color) and non-black is always an edge
2988 /** @type {boolean} */ var b1 = c1 == 0x000000;
2989 /** @type {boolean} */ var b2 = c2 == 0x000000;
2990 /** @type {boolean} */ var b3 = c3 == 0x000000;
2992 // both pixels with coverage and pixels without coverage
2993 if ((b1 && b2 && b3) == false && (b1 || b2 || b3) == true)
2994 return true;
2995 // all black
2996 if (b1 && b2 && b3)
2997 return false;
2998 // all with coverage
2999 assertMsgOptions(!b1 && !b2 && !b3, 'All colors with coverage', false, true);
3001 // Color is always linearly interpolated => component values change nearly linearly
3002 // in any constant direction on triangle hull. (df/dx ~= C).
3004 // Edge detection (this function) is run against the reference image
3005 // => no dithering to worry about
3007 return glsDrawTests.isEdgeTripletComponent((c1 >> 16) && 0xff, (c2 >> 16) && 0xff, (c3 >> 16) && 0xff, renderTargetThreshold[0]) ||
3008 glsDrawTests.isEdgeTripletComponent((c1 >> 8) && 0xff, (c2 >> 8) && 0xff, (c3 >> 8) && 0xff, renderTargetThreshold[1]) ||
3009 glsDrawTests.isEdgeTripletComponent(c1 && 0xff, c2 && 0xff, c3 && 0xff, renderTargetThreshold[2]);
3013 * @param {number} x
3014 * @param {number} y
3015 * @param {tcuSurface.Surface} ref
3016 * @param {Array<number>} renderTargetThreshold
3017 * @return {boolean}
3019 glsDrawTests.pixelNearEdge = function(x, y, ref, renderTargetThreshold) {
3020 // should not be called for edge pixels
3021 assertMsgOptions(x >= 1 && x <= ref.getWidth() - 2, 'The pixel was on the edge', false, true);
3022 assertMsgOptions(y >= 1 && y <= ref.getHeight() - 2, 'The pixel was on the edge', false, true);
3024 // horizontal
3026 /** @type {number} */ var c1;
3027 /** @type {number} */ var c2;
3028 /** @type {number} */ var c3;
3030 for (var dy = -1; dy < 2; ++dy) {
3031 c1 = ref.getPixelUintRGB8(x - 1, y + dy);
3032 c2 = ref.getPixelUintRGB8(x, y + dy);
3033 c3 = ref.getPixelUintRGB8(x + 1, y + dy);
3034 if (glsDrawTests.isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
3035 return true;
3038 // vertical
3040 for (var dx = -1; dx < 2; ++dx) {
3041 c1 = ref.getPixelUintRGB8(x + dx, y - 1);
3042 c2 = ref.getPixelUintRGB8(x + dx, y);
3043 c3 = ref.getPixelUintRGB8(x + dx, y + 1);
3044 if (glsDrawTests.isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
3045 return true;
3048 return false;
3052 * @param {number} c
3053 * @return {number}
3055 glsDrawTests.getVisualizationGrayscaleColorUintRGB8 = function(c) {
3056 // make triangle coverage and error pixels obvious by converting coverage to grayscale
3057 if (c == 0x000000)
3058 return 0;
3059 else
3060 return 50 + Math.floor((((c >> 16) & 0xff) + ((c >> 8) & 0xff) + (c & 0xff)) / 8);
3064 * @param {number} x
3065 * @param {number} y
3066 * @param {tcuSurface.Surface} target
3067 * @return {boolean}
3069 glsDrawTests.pixelNearLineIntersection = function(x, y, target) {
3070 // should not be called for edge pixels
3071 assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true);
3072 assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true);
3074 var coveredPixels = 0;
3076 for (var dy = -1; dy < 2; dy++)
3077 for (var dx = -1; dx < 2; dx++) {
3078 var targetCoverage = target.getPixelUintRGB8(x + dx, y + dy);
3079 if (targetCoverage) {
3080 ++coveredPixels;
3082 // A single thin line cannot have more than 3 covered pixels in a 3x3 area
3083 if (coveredPixels >= 4)
3084 return true;
3088 return false;
3091 // search 3x3 are for matching color
3093 * @param {tcuSurface.Surface} target
3094 * @param {number} x
3095 * @param {number} y
3096 * @param {tcuRGBA.RGBA} color
3097 * @param {Array<number>} compareThreshold
3098 * @return {boolean}
3100 glsDrawTests.pixelNeighborhoodContainsColor = function(target, x, y, color, compareThreshold) {
3101 // should not be called for edge pixels
3102 assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true);
3103 assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true);
3105 for (var dy = -1; dy < 2; dy++)
3106 for (var dx = -1; dx < 2; dx++) {
3107 if (glsDrawTests.compareUintRGB8(color, target.getPixelUintRGB8(x + dx, y + dy), compareThreshold))
3108 return true;
3111 return false;
3114 // search 3x3 are for matching coverage (coverage == (color != background color))
3116 * @param {tcuSurface.Surface} target
3117 * @param {number} x
3118 * @param {number} y
3119 * @param {boolean} coverage
3120 * @return {boolean}
3122 glsDrawTests.pixelNeighborhoodContainsCoverage = function(target, x, y, coverage) {
3123 // should not be called for edge pixels
3124 assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true);
3125 assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true);
3127 for (var dy = -1; dy < 2; dy++)
3128 for (var dx = -1; dx < 2; dx++) {
3129 var targetCmpCoverage = target.getPixelUintRGB8(x + dx, y + dy) != 0x000000; // Pixel is not black
3130 if (targetCmpCoverage == coverage)
3131 return true;
3134 return false;
3138 * @param {string} imageSetName
3139 * @param {string} imageSetDesc
3140 * @param {tcuSurface.Surface} reference
3141 * @param {tcuSurface.Surface} result
3142 * @param {Array<number>} compareThreshold
3143 * @param {Array<number>} renderTargetThreshold
3144 * @param {number} maxAllowedInvalidPixels
3145 * @return {boolean}
3147 glsDrawTests.edgeRelaxedImageCompare = function(imageSetName, imageSetDesc, reference, result, compareThreshold, renderTargetThreshold, maxAllowedInvalidPixels) {
3148 assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Reference and result images have different dimensions', false, true);
3150 /** @type {Array<number>} */ var green = [0, 255, 0, 255];
3151 /** @type {Array<number>} */ var errorColor = [255, 0, 0, 255];
3152 /** @type {number} */ var width = reference.getWidth();
3153 /** @type {number} */ var height = reference.getHeight();
3154 /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
3155 /** @type {number} */ var numFailingPixels = 0;
3157 // clear errormask edges which would otherwise be transparent
3159 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, width, 1, 1).clear(green);
3160 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, height - 1, 0, width, 1, 1).clear(green);
3161 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, 1, height, 1).clear(green);
3162 tcuTextureUtil.getSubregion(errorMask.getAccess(), width - 1, 0, 0, 1, height, 1).clear(green);
3164 // skip edge pixels since coverage on edge cannot be verified
3166 for (var y = 1; y < height - 1; ++y)
3167 for (var x = 1; x < width - 1; ++x) {
3168 /** @type {number} */ var refPixel = reference.getPixelUintRGB8(x, y);
3169 /** @type {number} */ var screenPixel = result.getPixelUintRGB8(x, y);
3170 /** @type {boolean} */ var isOkReferencePixel = glsDrawTests.pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
3171 /** @type {boolean} */ var isOkScreenPixel = glsDrawTests.pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
3173 if (isOkScreenPixel && isOkReferencePixel) {
3174 // pixel valid, write greenish pixels to make the result image easier to read
3175 /** @type {number} */ var grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
3176 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
3177 } else if (!glsDrawTests.pixelNearEdge(x, y, reference, renderTargetThreshold)) {
3178 // non-edge pixel values must be within threshold of the reference values
3179 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
3180 ++numFailingPixels;
3181 } else {
3182 // we are on/near an edge, verify only coverage (coverage == not background colored)
3183 /** @type {boolean} */ var referenceCoverage = refPixel != 0x000000; // Not black
3184 /** @type {boolean} */ var screenCoverage = screenPixel != 0x000000; // Not black
3185 /** @type {boolean} */ var isOkReferenceCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel
3186 /** @type {boolean} */ var isOkScreenCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel
3188 if (isOkScreenCoverage && isOkReferenceCoverage) {
3189 // pixel valid, write greenish pixels to make the result image easier to read
3190 var grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
3191 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
3192 } else {
3193 // coverage does not match
3194 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
3195 ++numFailingPixels;
3200 bufferedLogToConsole(
3201 'Comparing images:</br>' +
3202 '<span> </span>allowed deviation in pixel positions = 1</br>' +
3203 '<span> </span>number of allowed invalid pixels = ' + maxAllowedInvalidPixels + '</br>' +
3204 '<span> </span>number of invalid pixels = ' + numFailingPixels
3207 if (numFailingPixels > maxAllowedInvalidPixels) {
3208 debug('Image comparison failed. Color threshold = (' + compareThreshold[0] + ', ' + compareThreshold[1] + ', ' + compareThreshold[2] + ')');
3209 tcuImageCompare.displayImages(result.getAccess(), reference.getAccess(), errorMask.getAccess());
3211 return false;
3212 } else {
3213 return true;
3218 * @param {string} imageSetName
3219 * @param {string} imageSetDesc
3220 * @param {tcuSurface.Surface} reference
3221 * @param {tcuSurface.Surface} result
3222 * @param {Array<number>} compareThreshold
3223 * @param {number} maxAllowedInvalidPixels
3224 * @return {boolean}
3226 glsDrawTests.intersectionRelaxedLineImageCompare = function(imageSetName, imageSetDesc, reference, result, compareThreshold, maxAllowedInvalidPixels) {
3227 assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Reference and result images have different dimensions', false, true);
3229 /** @type {Array<number>} */ var green = [0, 255, 0, 255];
3230 /** @type {Array<number>} */ var errorColor = [255, 0, 0, 255];
3231 var width = reference.getWidth();
3232 var height = reference.getHeight();
3233 /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
3234 /** @type {number} */ var numFailingPixels = 0;
3236 // clear errormask edges which would otherwise be transparent
3238 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, width, 1, 1).clear(green);
3239 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, height - 1, 0, width, 1, 1).clear(green);
3240 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, 1, height, 1).clear(green);
3241 tcuTextureUtil.getSubregion(errorMask.getAccess(), width - 1, 0, 0, 1, height, 1).clear(green);
3243 // skip edge pixels since coverage on edge cannot be verified
3245 for (var y = 1; y < height - 1; ++y)
3246 for (var x = 1; x < width - 1; ++x) {
3247 /** @type {number} */ var refPixel = reference.getPixelUintRGB8(x, y);
3248 /** @type {number} */ var screenPixel = result.getPixelUintRGB8(x, y);
3249 /** @type {boolean} */ var isOkScreenPixel = glsDrawTests.pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
3250 /** @type {boolean} */ var isOkReferencePixel = glsDrawTests.pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
3252 /** @type {number} */ var grayscaleValue;
3254 if (isOkScreenPixel && isOkReferencePixel) {
3255 // pixel valid, write greenish pixels to make the result image easier to read
3256 grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
3257 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
3258 } else if (!glsDrawTests.pixelNearLineIntersection(x, y, reference) &&
3259 !glsDrawTests.pixelNearLineIntersection(x, y, result)) {
3260 // non-intersection pixel values must be within threshold of the reference values
3261 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
3262 ++numFailingPixels;
3263 } else {
3264 // pixel is near a line intersection
3265 // we are on/near an edge, verify only coverage (coverage == not background colored)
3266 /** @type {boolean} */ var referenceCoverage = refPixel != 0x000000; // Not Black
3267 /** @type {boolean} */ var screenCoverage = screenPixel != 0x000000; // Not Black
3268 /** @type {boolean} */ var isOkScreenCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel
3269 /** @type {boolean} */ var isOkReferenceCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel
3271 if (isOkScreenCoverage && isOkReferenceCoverage) {
3272 // pixel valid, write greenish pixels to make the result image easier to read
3273 grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel);
3274 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y);
3275 } else {
3276 // coverage does not match
3277 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y);
3278 ++numFailingPixels;
3283 bufferedLogToConsole(
3284 'Comparing images:</br>' +
3285 '<span> </span>allowed deviation in pixel positions = 1</br>' +
3286 '<span> </span>number of allowed invalid pixels = ' + maxAllowedInvalidPixels + '</br>' +
3287 '<span> </span>number of invalid pixels = ' + numFailingPixels
3290 if (numFailingPixels > maxAllowedInvalidPixels) {
3291 debug('Image comparison failed. Color threshold = (' + compareThreshold[0] + ', ' + compareThreshold[1] + ', ' + compareThreshold[2] + ')');
3292 tcuImageCompare.displayImages(result.getAccess(), reference.getAccess(), errorMask.getAccess());
3294 return false;
3295 } else {
3296 return true;
3301 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitiveType
3302 * @return {boolean}
3304 glsDrawTests.DrawTest.prototype.compare = function(primitiveType) {
3305 /** @type {tcuSurface.Surface} */ var ref = this.m_rrArrayPack.getSurface();
3306 /** @type {tcuSurface.Surface} */ var screen = this.m_glArrayPack.getSurface();
3308 if (/** @type {number} */ (gl.getParameter(gl.SAMPLES)) > 1) {
3309 // \todo [mika] Improve compare when using multisampling
3310 bufferedLogToConsole('Warning: Comparision of result from multisample render targets are not as strict as without multisampling. Might produce false positives!');
3311 return tcuImageCompare.fuzzyCompare('Compare Results', 'Compare Results', ref.getAccess(), screen.getAccess(), 0.3, tcuImageCompare.CompareLogMode.RESULT);
3312 } else {
3313 /** @type {glsDrawTests.PrimitiveClass} */ var primitiveClass = glsDrawTests.getDrawPrimitiveClass(primitiveType);
3315 switch (primitiveClass) {
3316 case glsDrawTests.PrimitiveClass.POINT: {
3317 // Point are extremely unlikely to have overlapping regions, don't allow any no extra / missing pixels
3318 /**@type {number} */ var maxAllowedInvalidPixelsWithPoints = 0;
3319 return tcuImageCompare.intThresholdPositionDeviationErrorThresholdCompare(
3320 'CompareResult',
3321 'Result of rendering',
3322 ref.getAccess(),
3323 screen.getAccess(),
3324 [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue, 256],
3325 [1, 1, 0], //!< 3x3 search kernel
3326 true, //!< relax comparison on the image boundary
3327 maxAllowedInvalidPixelsWithPoints //!< error threshold
3331 case glsDrawTests.PrimitiveClass.LINE: {
3332 // Lines can potentially have a large number of overlapping pixels. Pixel comparison may potentially produce
3333 // false negatives in such pixels if for example the pixel in question is overdrawn by another line in the
3334 // reference image but not in the resultin image. Relax comparison near line intersection points (areas) and
3335 // compare only coverage, not color, in such pixels
3336 /**@type {number} */ var maxAllowedInvalidPixelsWithLines = 15; // line are allowed to have a few bad pixels
3337 return glsDrawTests.intersectionRelaxedLineImageCompare(
3338 'CompareResult',
3339 'Result of rendering',
3340 ref,
3341 screen,
3342 [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue],
3343 maxAllowedInvalidPixelsWithLines
3347 case glsDrawTests.PrimitiveClass.TRIANGLE: {
3348 // Triangles are likely to partially or fully overlap. Pixel difference comparison is fragile in pixels
3349 // where there could be potential overlapping since the pixels might be covered by one triangle in the
3350 // reference image and by the other in the result image. Relax comparsion near primitive edges and
3351 // compare only coverage, not color, in such pixels.
3352 /** @type {number} */ var maxAllowedInvalidPixelsWithTriangles = 10;
3354 /* TODO: Implement
3355 var renderTargetThreshold = //TODO: get color threshold from the pixel format --> m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold().toIVec().xyz();
3358 /** @type {Array<number>} */ var renderTargetThreshold = [3, 3, 3, 3];
3360 return glsDrawTests.edgeRelaxedImageCompare(
3361 'CompareResult',
3362 'Result of rendering',
3363 ref,
3364 screen,
3365 [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue],
3366 renderTargetThreshold,
3367 maxAllowedInvalidPixelsWithTriangles
3371 default:
3372 throw new Error('Invalid primitive class');
3378 * @param {glsDrawTests.DrawTestSpec} spec
3379 * @return {number}
3381 glsDrawTests.DrawTest.prototype.getCoordScale = function(spec) {
3382 var maxValue = 1.0;
3384 for (var arrayNdx = 0; arrayNdx < spec.attribs.length; arrayNdx++) {
3385 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[arrayNdx];
3386 /** @type {boolean} */ var isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
3387 /** @type {number} */ var attrMaxValue = 0;
3389 if (!isPositionAttr)
3390 continue;
3392 if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10) {
3393 if (attribSpec.normalize)
3394 attrMaxValue += 1.0;
3395 else
3396 attrMaxValue += 1024.0;
3397 } else if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10) {
3398 if (attribSpec.normalize)
3399 attrMaxValue += 1.0;
3400 else
3401 attrMaxValue += 512.0;
3402 } else {
3403 var max = glsDrawTests.GLValue.getMaxValue(attribSpec.inputType).getValue();
3405 attrMaxValue += (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType)) ? (1.0) : (max * 1.1);
3408 if (attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4 ||
3409 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4 ||
3410 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4)
3411 attrMaxValue *= 2;
3413 maxValue += attrMaxValue;
3416 return 1.0 / maxValue;
3420 * @param {glsDrawTests.DrawTestSpec} spec
3421 * @return {number}
3423 glsDrawTests.DrawTest.prototype.getColorScale = function(spec) {
3424 var colorScale = 1.0;
3426 for (var arrayNdx = 1; arrayNdx < spec.attribs.length; arrayNdx++) {
3427 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[arrayNdx];
3428 /** @type {boolean} */ var isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
3430 if (isPositionAttr)
3431 continue;
3433 if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10) {
3434 if (!attribSpec.normalize)
3435 colorScale *= 1.0 / 1024.0;
3436 } else if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10) {
3437 if (!attribSpec.normalize)
3438 colorScale *= 1.0 / 512.0;
3439 } else {
3440 var max = glsDrawTests.GLValue.getMaxValue(attribSpec.inputType).toFloat();
3442 colorScale *= (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType) ? 1.0 : (1.0 / max));
3443 if (attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4 ||
3444 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4 ||
3445 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4)
3446 colorScale *= (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType) ? 1.0 : 1.0 / max);
3450 return colorScale;