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.
22 goog.provide('functional.gles3.es3fShaderPrecisionTests');
23 goog.require('framework.common.tcuTestCase');
24 goog.require('framework.common.tcuFloat');
25 goog.require('framework.delibs.debase.deMath');
26 goog.require('framework.delibs.debase.deRandom');
27 goog.require('framework.delibs.debase.deString');
28 goog.require('framework.opengl.gluDrawUtil');
29 goog.require('framework.opengl.gluShaderProgram');
30 goog.require('framework.opengl.gluShaderUtil');
32 goog.scope(function() {
33 var es3fShaderPrecisionTests = functional.gles3.es3fShaderPrecisionTests;
34 var deMath = framework.delibs.debase.deMath;
35 var deRandom = framework.delibs.debase.deRandom;
36 var deString = framework.delibs.debase.deString;
37 var tcuFloat = framework.common.tcuFloat;
38 var tcuTestCase = framework.common.tcuTestCase;
39 var gluDrawUtil = framework.opengl.gluDrawUtil;
40 var gluShaderUtil = framework.opengl.gluShaderUtil;
41 var gluShaderProgram = framework.opengl.gluShaderProgram;
43 /** @const {number} */ es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH = 32;
44 /** @const {number} */ es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT = 32;
46 es3fShaderPrecisionTests.add = function(a, b) { return a + b; };
47 es3fShaderPrecisionTests.sub = function(a, b) { return a - b; };
48 es3fShaderPrecisionTests.mul = function(a, b) { return a * b; };
49 // a * b = (a1 * 2^16 + a0) * (b1 * 2^16 + b0) = a1 * b1 * 2^32 + (a0 * b1 + a1 * b0) * 2^16 + a0 * b0
50 // 32bit integer multiplication may overflow in JavaScript. Only return low 32bit of the result.
51 es3fShaderPrecisionTests.mul32 = function(a, b) {
52 var sign = Math.sign(a) * Math.sign(b);
55 var a1 = deMath.split16(a)[1];
56 var a0 = deMath.split16(a)[0];
57 var b1 = deMath.split16(b)[1];
58 var b0 = deMath.split16(b)[0];
59 return sign * ((a0 * b1 + a1 * b0) * 0x10000 + a0 * b0);
61 es3fShaderPrecisionTests.div = function(a, b) { if (b !== 0) return a / b; else throw new Error('division by zero.')};
64 * @param {gluShaderUtil.precision} precision
65 * @param {string} evalOp
66 * @param {boolean} isVertexCase
67 * @return {gluShaderProgram.ShaderProgram}
69 es3fShaderPrecisionTests.createFloatPrecisionEvalProgram = function(precision, evalOp, isVertexCase) {
70 /** @type {gluShaderUtil.DataType} */ var type = gluShaderUtil.DataType.FLOAT;
71 /** @type {gluShaderUtil.DataType} */ var outType = gluShaderUtil.DataType.UINT;
72 /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(type);
73 /** @type {string} */ var outTypeName = gluShaderUtil.getDataTypeName(outType);
74 /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision);
75 /** @type {string} */ var vtx = '';
76 /** @type {string} */ var frag = '';
77 /** @type {string} */ var op = '';
79 vtx += '#version 300 es\n' +
80 'in highp vec4 a_position;\n' +
81 'in ' + precName + ' ' + typeName + ' a_in0;\n' +
82 'in ' + precName + ' ' + typeName + ' a_in1;\n';
83 frag += '#version 300 es\n' +
84 'layout(location = 0) out highp ' + outTypeName + ' o_out;\n';
87 vtx += 'flat out ' + precName + ' ' + typeName + ' v_out;\n';
88 frag += 'flat in ' + precName + ' ' + typeName + ' v_out;\n';
90 vtx += 'flat out ' + precName + ' ' + typeName + ' v_in0;\n' +
91 'flat out ' + precName + ' ' + typeName + ' v_in1;\n';
92 frag += 'flat in ' + precName + ' ' + typeName + ' v_in0;\n' +
93 'flat in ' + precName + ' ' + typeName + ' v_in1;\n';
96 vtx += '\nvoid main (void)\n{\n' +
97 ' gl_Position = a_position;\n';
98 frag += '\nvoid main (void)\n{\n';
100 op += '\t' + precName + ' ' + typeName + ' in0 = ' + (isVertexCase ? 'a_' : 'v_') + 'in0;\n' +
101 '\t' + precName + ' ' + typeName + ' in1 = ' + (isVertexCase ? 'a_' : 'v_') + 'in1;\n';
104 op += '\t' + precName + ' ' + typeName + ' res;\n';
106 op += '\t' + (isVertexCase ? 'v_out' : 'res') + ' = ' + evalOp + ';\n';
108 vtx += isVertexCase ? op : '';
109 frag += isVertexCase ? '' : op;
113 frag += ' o_out = floatBitsToUint(v_out);\n';
115 vtx += ' v_in0 = a_in0;\n' +
117 frag += ' o_out = floatBitsToUint(res);\n';
123 return new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag));
127 * @param {gluShaderUtil.DataType} type
128 * @param {gluShaderUtil.precision} precision
129 * @param {string} evalOp
130 * @param {boolean} isVertexCase
131 * @return {gluShaderProgram.ShaderProgram}
133 es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram = function(type, precision, evalOp, isVertexCase) {
134 /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(type);
135 /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision);
136 /** @type {string} */ var vtx = '';
137 /** @type {string} */ var frag = '';
138 /** @type {string} */ var op = '';
140 vtx += '#version 300 es\n' +
141 'in highp vec4 a_position;\n' +
142 'in ' + precName + ' ' + typeName + ' a_in0;\n' +
143 'in ' + precName + ' ' + typeName + ' a_in1;\n';
144 frag += '#version 300 es\n' +
145 'layout(location = 0) out ' + precName + ' ' + typeName + ' o_out;\n';
148 vtx += 'flat out ' + precName + ' ' + typeName + ' v_out;\n';
149 frag += 'flat in ' + precName + ' ' + typeName + ' v_out;\n';
151 vtx += 'flat out ' + precName + ' ' + typeName + ' v_in0;\n' +
152 'flat out ' + precName + ' ' + typeName + ' v_in1;\n';
153 frag += 'flat in ' + precName + ' ' + typeName + ' v_in0;\n' +
154 'flat in ' + precName + ' ' + typeName + ' v_in1;\n';
157 vtx += '\nvoid main (void)\n{\n'+
158 ' gl_Position = a_position;\n';
159 frag += '\nvoid main (void)\n{\n';
161 op += '\t' + precName + ' ' + typeName + ' in0 = ' + (isVertexCase ? 'a_' : 'v_') + 'in0;\n' +
162 '\t' + precName + ' ' + typeName + ' in1 = ' + (isVertexCase ? 'a_' : 'v_') + 'in1;\n';
164 op += '\t' + (isVertexCase ? 'v_' : 'o_') + 'out = ' + evalOp + ';\n';
166 vtx += isVertexCase ? op : '';
167 frag += isVertexCase ? '' : op;
171 frag += ' o_out = v_out;\n';
173 vtx += ' v_in0 = a_in0;\n' +
180 return new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag));
183 /** @typedef {function(number, number)} */ es3fShaderPrecisionTests.EvalFunc;
188 * @extends {tcuTestCase.DeqpTest}
189 * @param {string} name
190 * @param {string} desc
192 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
193 * @param {gluShaderUtil.precision} precision
194 * @param {Array<number>} rangeA
195 * @param {Array<number>} rangeB
196 * @param {boolean} isVertexCase
198 es3fShaderPrecisionTests.ShaderFloatPrecisionCase = function(name, desc, op, evalFunc, precision, rangeA, rangeB, isVertexCase) {
199 tcuTestCase.DeqpTest.call(this, name, desc);
201 /** @type {string} */ this.m_op = op;
202 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc;
203 /** @type {gluShaderUtil.precision} */ this.m_precision = precision;
204 /** @type {Array<number>} */ this.m_rangeA = rangeA;
205 /** @type {Array<number>} */ this.m_rangeB = rangeB;
206 /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
208 /** @type {number} */ this.m_numTestsPerIter = 32;
209 /** @type {number} */ this.m_numIters = 4;
210 /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
213 /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null;
214 /** @type {?WebGLFramebuffer} */ this.m_framebuffer = null;
215 /** @type {?WebGLRenderbuffer} */ this.m_renderbuffer = null;
216 /** @type {number} */ this.m_iterNdx = 0;
217 /** @type {Array<boolean>} */ this.m_iterPass = [];
220 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
221 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderFloatPrecisionCase;
223 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.init = function() {
224 assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true);
227 this.m_program = es3fShaderPrecisionTests.createFloatPrecisionEvalProgram(this.m_precision, this.m_op, this.m_isVertexCase);
229 if (!this.m_program.isOk())
230 assertMsgOptions(false, 'Compile failed', false, true);
232 // Create framebuffer.
233 this.m_framebuffer = gl.createFramebuffer();
234 this.m_renderbuffer = gl.createRenderbuffer();
236 gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer);
237 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32UI, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT);
239 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
240 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer);
242 assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true);
244 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
249 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.deinit = function() {
250 if(this.m_framebuffer)
251 gl.deleteFramebuffer(this.m_framebuffer);
252 if(this.m_renderbuffer)
253 gl.deleteRenderbuffer(this.m_renderbuffer);
254 this.m_program = null;
255 this.m_framebuffer = null;
256 this.m_renderbuffer = null;
260 * @param {number} in0
261 * @param {number} in1
262 * @param {number} reference
263 * @param {number} result
266 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.compare = function(in0, in1, reference, result) {
267 // Comparison is done using 64-bit reference value to accurately evaluate rounding mode error.
268 // If 32-bit reference value is used, 2 bits of rounding error must be allowed.
270 // For mediump and lowp types the comparison currently allows 3 bits of rounding error:
271 // two bits from conversions and one from actual operation.
273 // \todo [2013-09-30 pyry] Make this more strict: determine if rounding can actually happen.
275 /** @type {number} */ var mantissaBits = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 23 : 10;
276 /** @type {number} */ var numPrecBits = 52 - mantissaBits;
278 /** @type {number} */ var in0Exp = tcuFloat.newFloat32(in0).exponent();
279 /** @type {number} */ var in1Exp = tcuFloat.newFloat32(in1).exponent();
280 /** @type {number} */ var resExp = tcuFloat.newFloat32(result).exponent();
281 /** @type {number} */ var numLostBits = Math.max(in0Exp - resExp, in1Exp - resExp, 0); // Lost due to mantissa shift.
283 /** @type {number} */ var roundingUlpError = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : 3;
284 /** @type {number} */ var maskBits = numLostBits + numPrecBits;
286 bufferedLogToConsole("Assuming " + mantissaBits + " mantissa bits, " + numLostBits + " bits lost in operation, and " + roundingUlpError + " ULP rounding error.")
288 // These numbers should never be larger than 52 bits. An assertion in getBitRange verifies this.
289 /** @type {number} */ var accurateRefBits = tcuFloat.newFloat64(reference).getBitRange(maskBits, 64);
290 /** @type {number} */ var accurateResBits = tcuFloat.newFloat64(result).getBitRange(maskBits, 64);
291 /** @type {number} */ var ulpDiff = Math.abs(accurateRefBits - accurateResBits);
293 if (ulpDiff > roundingUlpError) {
294 bufferedLogToConsole("ERROR: comparison failed! ULP diff (ignoring lost/undefined bits) = " + ulpDiff );
302 * @return {tcuTestCase.IterateResult}
304 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.iterate = function() {
305 var testPassed = true;
306 var testPassedMsg = 'Pass';
309 /** @type {Array<number>} */ var position =[
310 -1.0, -1.0, 0.0, 1.0,
316 /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
317 /** @type {number} */ var numVertices = 4;
318 /** @type {Array<number>} */ var in0Arr = [0.0, 0.0, 0.0, 0.0];
319 /** @type {Array<number>} */ var in1Arr = [0.0, 0.0, 0.0, 0.0];
321 /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
323 // Image read from GL.
324 /** @type {goog.TypedArray} */ var pixels_uint = new Uint32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4);
326 // \todo [2012-05-03 pyry] Could be cached.
327 /** @type {WebGLProgram} */ var prog = this.m_program.getProgram();
330 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
332 vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position);
335 // Compute values and reference.
336 for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) {
337 /** @type {number} */ var in0 = this.m_rnd.getFloat(this.m_rangeA[0], this.m_rangeA[1]);
338 /** @type {number} */ var in1 = this.m_rnd.getFloat(this.m_rangeB[0], this.m_rangeB[1]);
340 // These random numbers are used in the reference computation. But
341 // highp is only 32 bits, so these float64s must be rounded to
342 // float32 first for correctness. This is needed for highp_mul_* on
343 // one Linux/NVIDIA machine.
344 in0 = tcuFloat.newFloat32(in0).getValue();
345 in1 = tcuFloat.newFloat32(in1).getValue();
347 /** @type {number} */ var refD = this.m_evalFunc(in0, in1);
349 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": "+
350 "in0 = " + in0 + " / " + tcuFloat.newFloat32(in0).bits() +
351 ", in1 = " + in1 + " / " + tcuFloat.newFloat32(in1).bits() +
352 " reference = " + refD + " / " + tcuFloat.newFloat32(refD).bits());
354 in0Arr = [in0, in0, in0, in0];
355 in1Arr = [in1, in1, in1, in1];
356 vertexArrays[1] = gluDrawUtil.newFloatVertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr);
357 vertexArrays[2] = gluDrawUtil.newFloatVertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr);
359 gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
361 gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH,
362 es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT, gl.RGBA_INTEGER, gl.UNSIGNED_INT, pixels_uint);
364 var pixels = new Float32Array(pixels_uint.buffer);
365 bufferedLogToConsole(" result = " + pixels[0] + " / " + tcuFloat.newFloat32(pixels[0]).bits());
368 /** @type {boolean} */ var firstPixelOk = this.compare(in0, in1, refD, pixels[0]);
371 // Check that rest of pixels match to first one.
372 /** @type {number} */ var firstPixelBits = tcuFloat.newFloat32(pixels[0]).bits();
373 /** @type {boolean} */ var allPixelsOk = true;
375 for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) {
376 for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) {
377 /** @type {number} */ var pixelBits = tcuFloat.newFloat32(pixels[(y * es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4]).bits();
379 if (pixelBits != firstPixelBits) {
380 bufferedLogToConsole("ERROR: Inconsistent results, got " + pixelBits + " at (" + x + ", " + y + ")")
390 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + "Inconsistent values in framebuffer");
392 testPassedMsg = 'Inconsistent values in framebuffer';
396 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + "Result comparison failed");
398 testPassedMsg = 'Result comparison failed'
402 // [dag] Aggregating test results to make the test less verbose.
403 this.m_iterPass[this.m_iterNdx] = testPassed;
405 // [dag] Show test results after the last iteration is done.
406 if (this.m_iterPass.length === this.m_numIters) {
407 if (!deMath.boolAll(this.m_iterPass))
408 testFailedOptions(testPassedMsg, false);
410 testPassedOptions(testPassedMsg, true);
412 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
415 return (this.m_iterNdx < this.m_numIters) ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
420 * @extends {tcuTestCase.DeqpTest}
421 * @param {string} name
422 * @param {string} desc
424 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
425 * @param {gluShaderUtil.precision} precision
426 * @param {number} bits
427 * @param {Array<number>} rangeA
428 * @param {Array<number>} rangeB
429 * @param {boolean} isVertexCase
431 es3fShaderPrecisionTests.ShaderIntPrecisionCase = function(name, desc, op, evalFunc, precision, bits, rangeA, rangeB, isVertexCase) {
432 tcuTestCase.DeqpTest.call(this, name, desc);
434 /** @type {string} */ this.m_op = op;
435 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc;
436 /** @type {gluShaderUtil.precision} */ this.m_precision = precision;
437 /** @type {number} */ this.m_bits = bits;
438 /** @type {Array<number>} */ this.m_rangeA = rangeA;
439 /** @type {Array<number>} */ this.m_rangeB = rangeB;
440 /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
442 /** @type {number} */ this.m_numTestsPerIter = 32;
443 /** @type {number} */ this.m_numIters = 4;
444 /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
447 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
448 /** @type {WebGLFramebuffer} */ this.m_framebuffer = null;
449 /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null;
450 /** @type {number} */ this.m_iterNdx = 0;
453 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
454 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderIntPrecisionCase;
456 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.init = function() {
457 assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true);
459 this.m_program = es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram(gluShaderUtil.DataType.INT, this.m_precision, this.m_op, this.m_isVertexCase);
461 if (!this.m_program.isOk())
462 assertMsgOptions(false, 'Compile failed', false, true);
464 // Create framebuffer.
465 this.m_framebuffer = gl.createFramebuffer();
466 this.m_renderbuffer = gl.createRenderbuffer();
468 gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer);
469 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32I, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT);
471 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
472 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer);
474 assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true);
476 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
480 bufferedLogToConsole("Number of accurate bits assumed = " + this.m_bits);
483 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.deinit = function() {
484 if(this.m_framebuffer)
485 gl.deleteFramebuffer(this.m_framebuffer);
486 if(this.m_renderbuffer)
487 gl.deleteRenderbuffer(this.m_renderbuffer);
488 this.m_program = null;
489 this.m_framebuffer = null;
490 this.m_renderbuffer = null;
494 * @param {number} value
495 * @param {number} bits
499 es3fShaderPrecisionTests.extendTo32Bit = function(value, bits) {
500 return (value & ((1 << (bits - 1)) - 1)) | ((value & (1 << (bits - 1))) << (32 - bits)) >> (32 - bits);
504 * @return {tcuTestCase.IterateResult}
506 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.iterate = function() {
507 var testPassed = true;
508 var testPassedMsg = 'Pass';
510 /** @type {Array<number>} */ var position = [
511 -1.0, -1.0, 0.0, 1.0,
516 /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
518 /** @type {number} */ var numVertices = 4;
519 /** @type {Array<number>} */ var in0Arr = [0, 0, 0, 0];
520 /** @type {Array<number>} */ var in1Arr = [0, 0, 0, 0];
522 /** @type {number} */ var mask = this.m_bits === 32 ? 0xffffffff : ((1 << this.m_bits) - 1);
523 /** @type {goog.TypedArray} */ var pixels = new Int32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4);
524 /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
526 /** @type {WebGLProgram} */ var prog = this.m_program.getProgram();
528 // \todo [2012-05-03 pyry] A bit hacky. getInt() should work fine with ranges like this.
529 /** @type {boolean} */ var isMaxRangeA = this.m_rangeA[0] === 0x80000000 && this.m_rangeA[1] === 0x7fffffff;
530 /** @type {boolean} */ var isMaxRangeB = this.m_rangeB[0] === 0x80000000 && this.m_rangeB[1] === 0x7fffffff;
533 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
535 vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position);
537 // Compute values and reference.
538 for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) {
539 /** @type {number} */ var in0 = this.m_rnd.getInt(this.m_rangeA[0], this.m_rangeA[1]); //es3fShaderPrecisionTests.extendTo32Bit(((isMaxRangeA ? Math.abs(this.m_rnd.getInt()) : this.m_rnd.getInt(this.m_rangeA[0], this.m_rangeA[1])) & mask), this.m_bits);
540 /** @type {number} */ var in1 = this.m_rnd.getInt(this.m_rangeB[0], this.m_rangeB[1]); //es3fShaderPrecisionTests.extendTo32Bit(((isMaxRangeB ? Math.abs(this.m_rnd.getInt()) : this.m_rnd.getInt(this.m_rangeB[0], this.m_rangeB[1])) & mask), this.m_bits);
541 /** @type {number} */ var refMasked = this.m_evalFunc(in0, in1) & mask;
542 /** @type {number} */ var refOut = es3fShaderPrecisionTests.extendTo32Bit(refMasked, this.m_bits);
544 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": " +
545 "in0 = " + in0 + ", in1 = " + in1 + ", ref out = " + refOut + " / " + refMasked);
547 in0Arr = [in0, in0, in0, in0];
548 in1Arr = [in1, in1, in1, in1];
550 vertexArrays[1] = gluDrawUtil.newInt32VertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr);
551 vertexArrays[2] = gluDrawUtil.newInt32VertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr);
553 gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
555 gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH,
556 es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT,
557 gl.RGBA_INTEGER, gl.INT, pixels);
560 for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) {
561 for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) {
562 /** @type {number} */ var cmpOut = pixels[(y * es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4];
563 /** @type {number} */ var cmpMasked = cmpOut & mask;
565 if (cmpMasked != refMasked) {
566 bufferedLogToConsole("Comparison failed (at " + x + ", " + y + "): " +
567 + "got " + cmpOut + " / " + cmpOut);
569 testPassedMsg = 'Comparison failed';
575 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
579 testFailedOptions(testPassedMsg, false);
580 return tcuTestCase.IterateResult.STOP;
581 } else if (testPassed && this.m_iterNdx < this.m_numIters) {
582 return tcuTestCase.IterateResult.CONTINUE;
584 testPassedOptions(testPassedMsg, true);
585 return tcuTestCase.IterateResult.STOP;
591 * @extends {tcuTestCase.DeqpTest}
592 * @param {string} name
593 * @param {string} desc
595 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
596 * @param {gluShaderUtil.precision} precision
597 * @param {number} bits
598 * @param {Array<number>} rangeA
599 * @param {Array<number>} rangeB
600 * @param {boolean} isVertexCase
602 es3fShaderPrecisionTests.ShaderUintPrecisionCase = function(name, desc, op, evalFunc, precision, bits, rangeA, rangeB, isVertexCase) {
603 tcuTestCase.DeqpTest.call(this, name, desc);
605 /** @type {string} */ this.m_op = op;
606 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc;
607 /** @type {gluShaderUtil.precision} */ this.m_precision = precision;
608 /** @type {number} */ this.m_bits = bits;
609 /** @type {Array<number>} */ this.m_rangeA = rangeA;
610 /** @type {Array<number>} */ this.m_rangeB = rangeB;
611 /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
613 /** @type {number} */ this.m_numTestsPerIter = 32;
614 /** @type {number} */ this.m_numIters = 4;
615 /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name));
618 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null;
619 /** @type {WebGLFramebuffer} */ this.m_framebuffer = null;
620 /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null;
621 /** @type {number} */ this.m_iterNdx = 0;
624 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
625 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderUintPrecisionCase;
627 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.init = function() {
628 assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true);
630 this.m_program = es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram(gluShaderUtil.DataType.UINT, this.m_precision, this.m_op, this.m_isVertexCase);
632 if (!this.m_program.isOk())
633 assertMsgOptions(false, 'Compile failed', false, true);
635 // Create framebuffer.
636 this.m_framebuffer = gl.createFramebuffer();
637 this.m_renderbuffer = gl.createRenderbuffer();
639 gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer);
640 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32UI, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT);
642 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
643 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer);
645 assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true);
647 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
651 bufferedLogToConsole("Number of accurate bits assumed = " + this.m_bits);
654 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.deinit = function() {
655 if(this.m_framebuffer)
656 gl.deleteFramebuffer(this.m_framebuffer);
657 if(this.m_renderbuffer)
658 gl.deleteRenderbuffer(this.m_renderbuffer);
659 this.m_program = null;
660 this.m_framebuffer = null;
661 this.m_renderbuffer = null;
665 * @return {tcuTestCase.IterateResult}
667 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.iterate = function() {
668 var testPassed = true;
669 var testPassedMsg = 'Pass';
672 /** @type {Array<number>} */ var position = [
673 -1.0, -1.0, 0.0, 1.0,
678 /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
680 /** @type {number} */ var numVertices = 4;
681 /** @type {Array<number>} */ var in0Arr = [0, 0, 0, 0];
682 /** @type {Array<number>} */ var in1Arr = [0, 0, 0, 0];
684 /** @type {number} */ var mask = this.m_bits === 32 ? 0xffffffff : ((1 << this.m_bits) - 1);
685 /** @type {goog.TypedArray} */ var pixels = new Uint32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4);
686 /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [];
688 /** @type {WebGLProgram} */ var prog = this.m_program.getProgram();
690 // \todo [2012-05-03 pyry] A bit hacky.
691 /** @type {boolean} */ var isMaxRangeA = this.m_rangeA[0] === 0 && this.m_rangeA[1] === 0xffffffff;
692 /** @type {boolean} */ var isMaxRangeB = this.m_rangeB[0] === 0 && this.m_rangeB[1] === 0xffffffff;
695 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
697 vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position);
699 // Compute values and reference.
700 for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) {
701 /** @type {number} */ var in0 = (isMaxRangeA ? Math.abs(this.m_rnd.getInt()) : (this.m_rangeA[0] + Math.abs(this.m_rnd.getInt()) % (this.m_rangeA[1] - this.m_rangeA[0] + 1))) & mask;
702 /** @type {number} */ var in1 = (isMaxRangeB ? Math.abs(this.m_rnd.getInt()) : (this.m_rangeB[0] + Math.abs(this.m_rnd.getInt()) % (this.m_rangeB[1] - this.m_rangeB[0] + 1))) & mask;
703 /** @type {number} */ var refOut = this.m_evalFunc(in0, in1) & mask;
705 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": " +
706 + "in0 = " + in0 + ", in1 = " + in1 + ", ref out = " + refOut)
708 in0Arr = [in0, in0, in0, in0];
709 in1Arr = [in1, in1, in1, in1];
710 vertexArrays[1] = gluDrawUtil.newUint32VertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr);
711 vertexArrays[2] = gluDrawUtil.newUint32VertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr);
713 gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
715 gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH,
716 es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT, gl.RGBA_INTEGER, gl.UNSIGNED_INT, pixels);
719 for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) {
720 for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) {
721 /** @type {number} */ var cmpOut = pixels[(y*es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4];
722 /** @type {number} */ var cmpMasked = cmpOut & mask;
724 if (cmpMasked != refOut) {
725 bufferedLogToConsole("Comparison failed (at " + x + ", " + y + "): " + "got " + cmpOut)
727 testPassedMsg = 'Comparison failed';
734 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
738 testFailedOptions(testPassedMsg, false);
739 return tcuTestCase.IterateResult.STOP;
740 } else if (testPassed && this.m_iterNdx < this.m_numIters) {
741 return tcuTestCase.IterateResult.CONTINUE;
743 testPassedOptions(testPassedMsg, true);
744 return tcuTestCase.IterateResult.STOP;
750 * @extends {tcuTestCase.DeqpTest}
752 es3fShaderPrecisionTests.ShaderPrecisionTests = function() {
753 tcuTestCase.DeqpTest.call(this, 'precision', 'Shader precision requirements validation tests');
756 es3fShaderPrecisionTests.ShaderPrecisionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
757 es3fShaderPrecisionTests.ShaderPrecisionTests.prototype.constructor = es3fShaderPrecisionTests.ShaderPrecisionTests;
759 es3fShaderPrecisionTests.ShaderPrecisionTests.prototype.init = function() {
760 var testGroup = tcuTestCase.runner.testCases;
761 // Exp = Emax-2, Mantissa = 0
762 // /** @type {number} */ var minF32 = tcuFloat.newFloat32((1 << 31) | (0xfd << 23) | 0x0).getValue();
763 // /** @type {number} */ var maxF32 = tcuFloat.newFloat32((0 << 31) | (0xfd << 23) | 0x0).getValue();
764 // [dag] Workaround for float32 numbers
765 /** @type {number} */ var minF32 = new Float32Array(new Uint32Array([1<<31|0xfd<<23|0x0]).buffer)[0];
766 /** @type {number} */ var maxF32 = new Float32Array(new Uint32Array([0<<31|0xfd<<23|0x0]).buffer)[0];
768 // /** @type {number} */ var minF16 = tcuFloat.newFloat16(((1 << 15) | (0x1d << 10) | 0x0)).getValue();
769 // /** @type {number} */ var maxF16 = tcuFloat.newFloat16(((0 << 15) | (0x1d << 10) | 0x0)).getValue();
770 /** @type {number} */ var minF16 = -16384; //-1 << 14; // 1 << 15 | 0x1d | 0x0 == 0b1111010000000000; -1 * (2**(29-15)) * 1
771 /** @type {number} */ var maxF16 = 16384; //1 << 14; // 0 << 15 | 0x1d | 0x0 == 0b0111010000000000; +1 * (2**(29-15)) * 1
773 /** @type {Array<number>} */ var fullRange32F = [minF32, maxF32];
774 /** @type {Array<number>} */ var fullRange16F = [minF16, maxF16];
775 /** @type {Array<number>} */ var fullRange32I = [-2147483648, 2147483647]; // [0x80000000|0, 0x7fffffff|0]; // |0 to force the number as a 32-bit integer
776 /** @type {Array<number>} */ var fullRange16I = [minF16, maxF16 - 1]; //[-(1 << 15), (1 << 15) - 1]; // Added the negative sign to index 0
777 /** @type {Array<number>} */ var fullRange8I = [-128, 127]; //[-(1 << 7), (1 << 7) - 1]; // Added the negative sign to index 0
778 /** @type {Array<number>} */ var fullRange32U = [0, 0xffffffff];
779 /** @type {Array<number>} */ var fullRange16U = [0, 0xffff];
780 /** @type {Array<number>} */ var fullRange8U = [0, 0xff];
782 // \note Right now it is not programmatically verified that the results shouldn't end up being inf/nan but
783 // actual values used are ok.
788 * @param {string} name
790 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
791 * @param {gluShaderUtil.precision} precision
792 * @param {Array<number>} rangeA
793 * @param {Array<number>} rangeB
795 var FloatCase = function(name, op, evalFunc, precision, rangeA, rangeB) {
796 /** @type {string} */ this.name = name;
797 /** @type {string} */ this.op = op;
798 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc;
799 /** @type {gluShaderUtil.precision} */ this.precision = precision;
800 /** @type {Array<number>} */ this.rangeA = rangeA;
801 /** @type {Array<number>} */ this.rangeB = rangeB;
804 /** @type {Array<FloatCase>} */ var floatCases = [
805 new FloatCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, fullRange32F, fullRange32F),
806 new FloatCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, fullRange32F, fullRange32F),
807 new FloatCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_HIGHP, [-1e5, 1e5], [-1e5, 1e5]),
808 new FloatCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, [-1e5, 1e5], [-1e5, 1e5]),
809 new FloatCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, fullRange16F, fullRange16F),
810 new FloatCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, fullRange16F, fullRange16F),
811 new FloatCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, [-1e2, 1e2], [-1e2, 1e2]),
812 new FloatCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, [-1e2, 1e2], [-1e2, 1e2])
818 * @param {string} name
820 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
821 * @param {gluShaderUtil.precision} precision
822 * @param {number} bits
823 * @param {Array<number>} rangeA
824 * @param {Array<number>} rangeB
826 var IntCase = function(name, op, evalFunc, precision, bits, rangeA, rangeB) {
827 /** @type {string} */ this.name = name;
828 /** @type {string} */ this.op = op;
829 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc;
830 /** @type {gluShaderUtil.precision} */ this.precision = precision;
831 /** @type {number} */ this.bits = bits;
832 /** @type {Array<number>} */ this.rangeA = rangeA;
833 /** @type {Array<number>} */ this.rangeB = rangeB;
836 /** @type {Array<IntCase>} */ var intCases = [
837 new IntCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I),
838 new IntCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I),
839 new IntCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul32, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I),
840 new IntCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, [-10000, -1]),
841 new IntCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I),
842 new IntCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I),
843 new IntCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I),
844 new IntCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, [1, 1000]),
845 new IntCase('lowp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I),
846 new IntCase('lowp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I),
847 new IntCase('lowp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I),
848 new IntCase('lowp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, [-50, -1])
854 * @param {string} name
856 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc
857 * @param {gluShaderUtil.precision} precision
858 * @param {number} bits
859 * @param {Array<number>} rangeA
860 * @param {Array<number>} rangeB
862 var UintCase = function(name, op, evalFunc, precision, bits, rangeA, rangeB) {
863 /** @type {string} */ this.name = name;
864 /** @type {string} */ this.op = op;
865 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc;
866 /** @type {gluShaderUtil.precision} */ this.precision = precision;
867 /** @type {number} */ this.bits = bits;
868 /** @type {Array<number>} */ this.rangeA = rangeA;
869 /** @type {Array<number>} */ this.rangeB = rangeB;
872 /** @type {Array<UintCase>} */ var uintCases = [
873 new UintCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U),
874 new UintCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U),
875 new UintCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul32, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U),
876 new UintCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, [1, 10000]),
877 new UintCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U),
878 new UintCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U),
879 new UintCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U),
880 new UintCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, [1, 1000]),
881 new UintCase('lowp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U),
882 new UintCase('lowp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U),
883 new UintCase('lowp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U),
884 new UintCase('lowp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, [1, 50])
887 /** @type {tcuTestCase.DeqpTest} */ var floatGroup = tcuTestCase.newTest('float', 'Floating-point precision tests');
888 testGroup.addChild(floatGroup);
889 for (var ndx = 0; ndx < floatCases.length; ndx++) {
890 floatGroup.addChild(new es3fShaderPrecisionTests.ShaderFloatPrecisionCase(
891 floatCases[ndx].name + '_vertex', '', floatCases[ndx].op, floatCases[ndx].evalFunc,
892 floatCases[ndx].precision, floatCases[ndx].rangeA, floatCases[ndx].rangeB, true));
893 floatGroup.addChild(new es3fShaderPrecisionTests.ShaderFloatPrecisionCase(
894 floatCases[ndx].name + '_fragment', '', floatCases[ndx].op, floatCases[ndx].evalFunc,
895 floatCases[ndx].precision, floatCases[ndx].rangeA, floatCases[ndx].rangeB, false));
898 /** @type {tcuTestCase.DeqpTest} */ var intGroup = tcuTestCase.newTest('int', 'Integer precision tests');
899 testGroup.addChild(intGroup);
900 for (var ndx = 0; ndx < intCases.length; ndx++) {
901 intGroup.addChild(new es3fShaderPrecisionTests.ShaderIntPrecisionCase(
902 intCases[ndx].name + '_vertex', '', intCases[ndx].op, intCases[ndx].evalFunc,
903 intCases[ndx].precision, intCases[ndx].bits, intCases[ndx].rangeA, intCases[ndx].rangeB, true));
904 intGroup.addChild(new es3fShaderPrecisionTests.ShaderIntPrecisionCase(
905 intCases[ndx].name + '_fragment', '', intCases[ndx].op, intCases[ndx].evalFunc,
906 intCases[ndx].precision, intCases[ndx].bits, intCases[ndx].rangeA, intCases[ndx].rangeB, false));
909 /** @type {tcuTestCase.DeqpTest} */ var uintGroup = tcuTestCase.newTest('uint', 'Unsigned integer precision tests');
910 testGroup.addChild(uintGroup);
911 for (var ndx = 0; ndx < uintCases.length; ndx++) {
912 uintGroup.addChild(new es3fShaderPrecisionTests.ShaderUintPrecisionCase(
913 uintCases[ndx].name + '_vertex', '', uintCases[ndx].op, uintCases[ndx].evalFunc,
914 uintCases[ndx].precision, uintCases[ndx].bits, uintCases[ndx].rangeA, uintCases[ndx].rangeB, true));
915 uintGroup.addChild(new es3fShaderPrecisionTests.ShaderUintPrecisionCase(
916 uintCases[ndx].name + '_fragment', '', uintCases[ndx].op, uintCases[ndx].evalFunc,
917 uintCases[ndx].precision, uintCases[ndx].bits, uintCases[ndx].rangeA, uintCases[ndx].rangeB, false));
923 * @param {WebGL2RenderingContext} context
925 es3fShaderPrecisionTests.run = function(context, range) {
927 //Set up Test Root parameters
928 var state = tcuTestCase.runner;
929 state.setRoot(new es3fShaderPrecisionTests.ShaderPrecisionTests());
931 //Set up name and description of this test series.
932 setCurrentTestName(state.testCases.fullName());
933 description(state.testCases.getDescription());
937 state.setRange(range);
939 tcuTestCase.runTestCases();
942 testFailedOptions('Failed to es3fShaderPrecisionTests.run tests', false);
943 tcuTestCase.runner.terminate();