Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / functional / gles3 / es3fShaderPackingFunctionTests.js
blob3e4233db4cf7f79e9db3394e0d9e229f5e9c0ca3
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
3  * ------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
21 'use strict';
22 goog.provide('functional.gles3.es3fShaderPackingFunctionTests');
23 goog.require('framework.common.tcuFloat');
24 goog.require('framework.common.tcuMatrixUtil');
25 goog.require('framework.common.tcuTestCase');
26 goog.require('framework.delibs.debase.deMath');
27 goog.require('framework.delibs.debase.deRandom');
28 goog.require('framework.delibs.debase.deString');
29 goog.require('framework.opengl.gluShaderProgram');
30 goog.require('framework.opengl.gluShaderUtil');
31 goog.require('framework.opengl.gluVarType');
32 goog.require('modules.shared.glsShaderExecUtil');
36 goog.scope(function() {
37         var es3fShaderPackingFunctionTests = functional.gles3.es3fShaderPackingFunctionTests;
38         var tcuFloat = framework.common.tcuFloat;
39         var tcuTestCase = framework.common.tcuTestCase;
40         var deMath = framework.delibs.debase.deMath;
41         var deRandom = framework.delibs.debase.deRandom;
42         var deString = framework.delibs.debase.deString;
43         var gluShaderProgram = framework.opengl.gluShaderProgram;
44         var gluShaderUtil = framework.opengl.gluShaderUtil;
45         var gluVarType = framework.opengl.gluVarType;
46         var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
47         var tcuMatrixUtil = framework.common.tcuMatrixUtil;
48         /**
49          * @param {number} a
50          * @param {number} b
51          * @return {number}
52          */
53         es3fShaderPackingFunctionTests.getUlpDiff = function(a, b) {
54                 /** @type {number} */ var aBits = tcuFloat.newFloat32(a).bits();
55                 /** @type {number} */ var bBits = tcuFloat.newFloat32(b).bits();
56                 return aBits > bBits ? aBits - bBits : bBits - aBits;
57         };
59         /**
60          * @constructor
61          * @extends {tcuTestCase.DeqpTest}
62          * @param {string} name
63          * @param {string} description
64          * @param {gluShaderProgram.shaderType} shaderType
65          */
66         es3fShaderPackingFunctionTests.ShaderPackingFunctionCase = function(name, description, shaderType) {
67                 tcuTestCase.DeqpTest.call(this, name, description);
68                 /** @type {gluShaderProgram.shaderType} */ this.m_shaderType = shaderType;
69                 /** @type {?glsShaderExecUtil.ShaderSpec} */ this.m_spec = new glsShaderExecUtil.ShaderSpec();
70                 /** @type {?glsShaderExecUtil.ShaderExecutor} */ this.m_executor = null;
71         };
73         es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
74         es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionCase;
76         es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.init = function() {
77                 assertMsgOptions(!this.m_executor, 'Error: Executor is not null.', false, true);
78                 this.m_executor = glsShaderExecUtil.createExecutor(this.m_shaderType, this.m_spec);
79                 if (!this.m_executor.isOk())
80                         throw new Error('Compile failed');
81         };
83         es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.deinit = function() {
84                 this.m_executor = null;
85         };
87         /**
88          *      @param {gluShaderUtil.precision} precision
89          * @return {string}
90          */
91         es3fShaderPackingFunctionTests.getPrecisionPostfix = function(precision) {
92                 /** @type {Array<string>} */ var s_postfix = [
93                         '_lowp',
94                         '_mediump',
95                         '_highp'
96                 ];
97                 assertMsgOptions(0 <= precision && precision < s_postfix.length, 'Error: Out of range', false, true);
98                 return s_postfix[precision];
99         };
101         /**
102          *      @param {gluShaderProgram.shaderType} shaderType
103          * @return {string}
104          */
105         es3fShaderPackingFunctionTests.getShaderTypePostfix = function(shaderType) {
106                 /** @type {Array<string>} */ var s_postfix = [
107                         '_vertex',
108                         '_fragment'
109                 ];
110                 assertMsgOptions(0 <= shaderType && shaderType < s_postfix.length, 'Error Out of range', false, true);
111                 return s_postfix[shaderType];
112         };
114         /**
115          * @constructor
116          * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
117          * @param {gluShaderProgram.shaderType} shaderType
118          * @param {gluShaderUtil.precision} precision
119          */
120         es3fShaderPackingFunctionTests.PackSnorm2x16Case = function(shaderType, precision) {
121                 /** @const {string} */ var name = 'packsnorm2x16' +
122                         es3fShaderPackingFunctionTests.getPrecisionPostfix(precision) +
123                         es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
124                 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packSnorm2x16', shaderType);
125                 this.m_precision = precision;
127                 this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision)));
128                 this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
129                 this.m_spec.source = 'out0 = packSnorm2x16(in0);';
130         };
132         es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
133         es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackSnorm2x16Case;
135         /**
136          * @return {tcuTestCase.IterateResult}
137          */
138         es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.iterate = function() {
139                 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
140                 /** @type {Array<Array<number>>} */ var inputs = [];
141                 /** @type {goog.TypedArray} */ var outputs; // deUint32
142                 /** @type {goog.TypedArray} */ var shaderExecutorOutput;
143                 /** @type {number} */ var maxDiff = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : // Rounding only.
144                                                                                         this.m_precision == gluShaderUtil.precision.PRECISION_MEDIUMP ? 33 : // (2^-10) * (2^15) + 1
145                                                                                         this.m_precision == gluShaderUtil.precision.PRECISION_LOWP ? 129 : 0; // (2^-8) * (2^15) + 1
146                 /** @type {number} */ var x;
147                 /** @type {number} */ var y;
148                 // Special values to check.
149                 inputs.push([0.0, 0.0]);
150                 inputs.push([-1.0, 1.0]);
151                 inputs.push([0.5, -0.5]);
152                 inputs.push([-1.5, 1.5]);
153                 inputs.push([0.25, -0.75]);
155                 // Random values, mostly in range.
156                 for (var ndx = 0; ndx < 15; ndx++) {
157                         x = rnd.getFloat() * 2.5 - 1.25;
158                         y = rnd.getFloat() * 2.5 - 1.25;
159                         inputs.push([x, y]);
160                 }
162                 // Large random values.
163                 for (var ndx = 0; ndx < 80; ndx++) {
164                         x = rnd.getFloat() * 1e6 - 0.5e6;
165                         y = rnd.getFloat() * 1e6 - 0.5e6;
166                         inputs.push([x, y]);
167                 }
169                 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
171                 this.m_executor.useProgram();
172                 shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
174                 // Convert outputs if we get them as Uint8Array.
175                 // - VertexShaderExecutor.execute() returns either an array of Uint8Array
176                 // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
177             outputs = new Uint32Array(shaderExecutorOutput.buffer);
179                 // Verify
180                 /** @type {number} */ var numValues = inputs.length;
181                 /** @type {number} */ var maxPrints = 10;
182                 /** @type {number} */ var numFailed = 0;
184                 for (var valNdx = 0; valNdx < numValues; valNdx++) {
185                         /** @type {number} */ var ref0 = (deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][0], -1.0, 1.0) * 32767.0), -(1 << 15), (1 << 15) - 1)) & 0xFFFF;
186                         /** @type {number} */ var ref1 = (deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][1], -1.0, 1.0) * 32767.0), -(1 << 15), (1 << 15) - 1)) & 0xFFFF;
187                         /** @type {number} */ var ref = (ref1 << 16) | ref0;
188                         /** @type {number} */ var res = outputs[valNdx];
189                         /** @type {number} */ var res0 = (res & 0xffff);
190                         /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
191                         /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
192                         /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
194                         if (diff0 > maxDiff || diff1 > maxDiff) {
195                                 if (numFailed < maxPrints) {
196                                         bufferedLogToConsole(
197                                                 'ERROR: Mismatch in value ' + valNdx +
198                                                 ', expected packSnorm2x16(' + inputs[valNdx] + ') = ' + ref + //tcu::toHex(ref)
199                                                 ', got ' + res + // tcu::toHex(res)
200                                                 '\n  diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
201                                 }
202                                 else if (numFailed == maxPrints)
203                                         bufferedLogToConsole('...');
205                                 numFailed += 1;
206                         }
207                 }
209                 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
211                 /** @type {boolean} */ var isOk = numFailed === 0;
212                 if (!isOk)
213                         testFailedOptions('Result comparison failed', false);
214         else
215             testPassedOptions('Pass', true);
217                 return tcuTestCase.IterateResult.STOP;
218         };
221         /**
222          * @constructor
223          * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
224          * @param {gluShaderProgram.shaderType} shaderType
225          */
226         es3fShaderPackingFunctionTests.UnpackSnorm2x16Case = function(shaderType) {
227                 /** @const {string} */ var name = 'unpacksnorm2x16' + es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
228                 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackSnorm2x16', shaderType);
230                 this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
231                 this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
232                 this.m_spec.source = 'out0 = unpackSnorm2x16(in0);';
233         };
235         es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
236         es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackSnorm2x16Case;
238         /**
239          * @return {tcuTestCase.IterateResult}
240          */
241         es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.iterate = function() {
242                 /** @type {number} */ var maxDiff = 1; // Rounding error.
243                 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
244                 /** @type {Array<number>} */ var inputs = [];
245                 /** @type {goog.TypedArray} */ var shaderExecutorOutput; //vector<vec2<float>>
246                 /** @type {goog.TypedArray} */ var outputs; //vector<vec2<float>>
248                 inputs.push(0x00000000);
249                 inputs.push(0x7fff8000);
250                 inputs.push(0x80007fff);
251                 inputs.push(0xffffffff);
252                 inputs.push(0x0001fffe);
254                 // Random values.
255                 for (var ndx = 0; ndx < 95; ndx++)
256                         inputs.push(rnd.getInt());
258                 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
260                 this.m_executor.useProgram();
261                 shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0]; // This test case only has one output
263                 // Convert outputs if we get them as Uint8Array.
264                 // - VertexShaderExecutor.execute() returns either an array of Uint8Array
265                 // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
266                 outputs = new Float32Array(shaderExecutorOutput.buffer);
268                 // Verify
269                 /** @type {number} */ var numValues = inputs.length;
270                 /** @type {number} */ var maxPrints = 10;
271                 /** @type {number} */ var numFailed = 0;
273                 for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
274                         /** @type {number} */ var in0 = Math.floor(inputs[valNdx] & 0xffff);
275                         // Convert 16-bit uint to 16-bit int
276                         var view = new DataView(new ArrayBuffer(4));
277                         view.setUint16(0, in0, true);
278                         in0 = view.getInt16(0, true);
279                         /** @type {number} */ var in1 = Math.floor(deMath.shiftRight(inputs[valNdx], 16));
280                         // Convert 16-bit uint to 16-bit int
281                         var view = new DataView(new ArrayBuffer(4));
282                         view.setUint16(0, in1, true);
283                         in1 = view.getInt16(0, true);
284                         /** @type {number} */ var ref0 = deMath.clamp(in0 / 32767., -1.0, 1.0);
285                         /** @type {number} */ var ref1 = deMath.clamp(in1 / 32767., -1.0, 1.0);
286                         /** @type {number} */ var res0 = outputs[2 * valNdx];
287                         /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
289                         /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0);
290                         /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1);
292                         if (diff0 > maxDiff || diff1 > maxDiff) {
293                                 if (numFailed < maxPrints)
294                                         bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
295                                         '  expected unpackSnorm2x16(' + inputs[valNdx].toString(16) + ') = ' +
296                                         'vec2(' + ref0.toString(16) + ', ' + ref1.toString(16) + ')' +
297                                         ', got vec2(' + res0.toString(16) + ', ' + res1.toString(16) + ')' +
298                                         '\n  ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
299                                 else if (numFailed == maxPrints)
300                                         bufferedLogToConsole('...');
302                                 numFailed += 1;
303                         }
304                 }
306                 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
308                 /** @type {boolean} */ var isOk = numFailed === 0;
309                 if (!isOk)
310                         testFailedOptions('Result comparison failed', false);
311                 else
312                         testPassedOptions('Pass', true);
314                 return tcuTestCase.IterateResult.STOP;
315         };
317         /**
318          * @constructor
319          * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
320          * @param {gluShaderProgram.shaderType} shaderType
321          * @param {gluShaderUtil.precision} precision
322          */
323         es3fShaderPackingFunctionTests.PackUnorm2x16Case = function(shaderType, precision) {
324                 /** @const {string} */ var name = 'packunorm2x16' +
325                         es3fShaderPackingFunctionTests.getPrecisionPostfix(precision) +
326                         es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
327                 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packUnorm2x16', shaderType);
328                 this.m_precision = precision;
330                 this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision)));
331                 this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
332                 this.m_spec.source = 'out0 = packUnorm2x16(in0);';
333         };
335         es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
336         es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackUnorm2x16Case;
338         /**
339          * @return {tcuTestCase.IterateResult}
340          */
341         es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.iterate = function() {
342                 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
343                 /** @type {Array<Array<number>>} */ var inputs = [];
344                 /** @type {goog.TypedArray} */ var shaderExecutorOutput;
345                 /** @type {goog.TypedArray} */ var outputs; // deUint32
346                 /** @type {number} */ var maxDiff = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : // Rounding only.
347                                                                                         this.m_precision == gluShaderUtil.precision.PRECISION_MEDIUMP ? 65 : // (2^-10) * (2^16) + 1
348                                                                                         this.m_precision == gluShaderUtil.precision.PRECISION_LOWP ? 257 : 0; // (2^-8) * (2^16) + 1
349                 /** @type {number} */ var x;
350                 /** @type {number} */ var y;
351                 // Special values to check.
352                 inputs.push([0.0, 0.0]);
353                 inputs.push([0.5, 1.0]);
354                 inputs.push([1.0, 0.5]);
355                 inputs.push([-0.5, 1.5]);
356                 inputs.push([0.25, 0.75]);
358                 // Random values, mostly in range.
359                 for (var ndx = 0; ndx < 15; ndx++) {
360                         x = rnd.getFloat() * 1.25;
361                         y = rnd.getFloat() * 1.25;
362                         inputs.push([x, y]);
363                 }
365                 // Large random values.
366                 for (var ndx = 0; ndx < 80; ndx++) {
367                         x = rnd.getFloat() * 1e6 - 1e5;
368                         y = rnd.getFloat() * 1e6 - 1e5;
369                         inputs.push([x, y]);
370                 }
372                 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
374                 this.m_executor.useProgram();
375                 shaderExecutorOutput  = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
377                 // Convert outputs if we get them as Uint8Array.
378                 // - VertexShaderExecutor.execute() returns either an array of Uint8Array
379                 // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
380             outputs = new Uint32Array(shaderExecutorOutput.buffer);
382                 // Verify
383                 /** @type {number} */ var numValues = inputs.length;
384                 /** @type {number} */ var maxPrints = 10;
385                 /** @type {number} */ var numFailed = 0;
387                 for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
388                         /** @type {number} */ var ref0 = deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][0], 0.0, 1.0) * 65535.0), 0, (1 << 16) - 1) & 0xFFFF;
389                         /** @type {number} */ var ref1 = deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][1], 0.0, 1.0) * 65535.0), 0, (1 << 16) - 1) & 0xFFFF;
390                         /** @type {number} */ var ref = (ref1 << 16) | ref0;
391                         /** @type {number} */ var res = outputs[valNdx];
392                         /** @type {number} */ var res0 = (res & 0xffff);
393                         /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
394                         /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
395                         /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
397                         if (diff0 > maxDiff || diff1 > maxDiff) {
398                                 if (numFailed < maxPrints)
399                                         bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx +
400                                                                                  ', expected packUnorm2x16(' + inputs[valNdx] + ') = ' + ref /*tcu::toHex(ref)*/ +
401                                                                                  ', got ' + res /*tcu::toHex(res)*/ +
402                                                                                  '\n  diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
403                                 else if (numFailed === maxPrints)
404                                         bufferedLogToConsole('...');
406                                 numFailed += 1;
407                         }
408                 }
410                 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
412                 /** @type {boolean} */ var isOk = numFailed === 0;
413                 if (!isOk)
414                         testFailedOptions('Result comparison failed', false);
415                 else
416                         testPassedOptions('Pass', true);
418                 return tcuTestCase.IterateResult.STOP;
419         };
421         /**
422          * @constructor
423          * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
424          * @param {gluShaderProgram.shaderType} shaderType
425          */
426         es3fShaderPackingFunctionTests.UnpackUnorm2x16Case = function(shaderType) {
427                 /** @const {string} */ var name = 'unpackunorm2x16' +
428                         es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
429                 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackUnorm2x16', shaderType);
431                 this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
432                 this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
433                 this.m_spec.source = 'out0 = unpackUnorm2x16(in0);';
434         };
436         es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
437         es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackUnorm2x16Case;
439         /**
440          * @return {tcuTestCase.IterateResult}
441          */
442         es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.iterate = function() {
443                 /** @type {number} */ var maxDiff = 1; // Rounding error.
444                 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
445                 /** @type {Array<number>} */ var inputs = [];
446                 /** @type {goog.TypedArray} */ var shaderExecutorOutput;
447                 /** @type {goog.TypedArray} */ var outputs; //vector<vec2>
449                 inputs.push(0x00000000);
450                 inputs.push(0x7fff8000);
451                 inputs.push(0x80007fff);
452                 inputs.push(0xffffffff);
453                 inputs.push(0x0001fffe);
455                 // Random values.
456                 for (var ndx = 0; ndx < 95; ndx++)
457                         inputs.push(rnd.getInt());
459                 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
461                 this.m_executor.useProgram();
462                 shaderExecutorOutput  = this.m_executor.execute(inputs.length, [inputs])[0];
464                 // Convert outputs if we get them as Uint8Array.
465                 // - VertexShaderExecutor.execute() returns either an array of Uint8Array
466                 // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
467                 outputs = new Float32Array(shaderExecutorOutput.buffer);
469                 // Verify
470                 /** @type {number} */ var numValues = inputs.length;
471                 /** @type {number} */ var maxPrints = 10;
472                 /** @type {number} */ var numFailed = 0;
474                 for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
475                         /** @type {number} */ var in0 = Math.floor(inputs[valNdx] & 0xffff);
476                         /** @type {number} */ var in1 = Math.floor(deMath.shiftRight(inputs[valNdx], 16));
477                         /** @type {number} */ var ref0 = in0 / 65535.0;
478                         /** @type {number} */ var ref1 = in1 / 65535.0;
479                         /** @type {number} */ var res0 = outputs[2 * valNdx];
480                         /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
482                         /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0);
483                         /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1);
485                         if (diff0 > maxDiff || diff1 > maxDiff) {
486                                 if (numFailed < maxPrints)
487                                         bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
488                                                                              '  expected unpackUnorm2x16(' + inputs[valNdx].toString(16) + ') = ' +
489                                                                              'vec2(' + ref0.toString(16) + ', ' + ref1.toString(16) + ')' +
490                                                                              ', got vec2(' + res0.toString(16) + ', ' + res1.toString(16) + ')' +
491                                                                              '\n  ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
492                                 else if (numFailed === maxPrints)
493                                         bufferedLogToConsole('...');
495                                 numFailed += 1;
496                         }
497                 }
499                 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
501                 /** @type {boolean} */ var isOk = numFailed === 0;
502                 if (!isOk)
503                         testFailedOptions('Result comparison failed', false);
504                 else
505                         testPassedOptions('Pass', true);
507                 return tcuTestCase.IterateResult.STOP;
508         };
510         /**
511          * @constructor
512          * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
513          * @param {gluShaderProgram.shaderType} shaderType
514          */
515         es3fShaderPackingFunctionTests.PackHalf2x16Case = function(shaderType) {
516                 /** @const {string} */ var name = 'packhalf2x16' +
517                         es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
518                 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packHalf2x16', shaderType);
520                 this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
521                 this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
522                 this.m_spec.source = 'out0 = packHalf2x16(in0);';
523         };
525         es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
526         es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackHalf2x16Case;
528         /**
529          * @return {tcuTestCase.IterateResult}
530          */
531         es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.iterate = function() {
532                 /** @type {number} */ var maxDiff = 0; // Values can be represented exactly in mediump.
533                 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
534                 /** @type {Array<Array<number>>} */ var inputs = [];
535                 /** @type {goog.TypedArray} */ var shaderExecutorOutput;
536                 /** @type {goog.TypedArray} */ var outputs; // deUint32
538                 // Special values to check.
539                 inputs.push([0.0, 0.0]);
540                 inputs.push([0.5, 1.0]);
541                 inputs.push([1.0, 0.5]);
542                 inputs.push([-0.5, 1.5]);
543                 inputs.push([0.25, 0.75]);
545                 // Random values.
546                 /** @type {number} */ var minExp = -14;
547                 /** @type {number} */ var maxExp = 15;
549                 /** @type {Array<number>} */ var v = [];
550                 for (var ndx = 0; ndx < 95; ndx++) {
551                         for (var c = 0; c < 2; c++) {
552                                 /** @type {number} */ var s = rnd.getBool() ? 1 : -1;
553                                 /** @type {number} */ var exp = rnd.getInt(minExp, maxExp);
554                                 /** @type {number} */ var mantissa = rnd.getInt(0) & ((1 << 23) - 1);
556                                 v[c] = (new tcuFloat.deFloat()).construct(s, exp ? exp : 1 /* avoid denormals */, (1 << 23) | mantissa).getValue();
557                         }
558                         inputs.push(v);
559                 }
561                 // Convert input values to fp16 and back to make sure they can be represented exactly in mediump.
562                 for (var inVal in inputs)
563                         inputs[inVal] = [tcuFloat.newFloat16(inputs[inVal][0]).getValue(), tcuFloat.newFloat16(inputs[inVal][1]).getValue()];
565                 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
567                 this.m_executor.useProgram();
568                 shaderExecutorOutput  = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
570                 // Convert outputs if we get them as Uint8Array.
571                 // - VertexShaderExecutor.execute() returns either an array of Uint8Array
572                 // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
573             outputs = new Uint32Array(shaderExecutorOutput.buffer);
575                 // Verify
576                 /** @type {number} */ var numValues = inputs.length;
577                 /** @type {number} */ var maxPrints = 10;
578                 /** @type {number} */ var numFailed = 0;
580                 for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
581                         /** @type {number} */ var ref0 = tcuFloat.newFloat16(inputs[valNdx][0]).bits();
582                         /** @type {number} */ var ref1 = tcuFloat.newFloat16(inputs[valNdx][1]).bits();
583                         /** @type {number} */ var ref = (ref1 << 16) | ref0;
584                         /** @type {number} */ var res = outputs[valNdx];
585                         /** @type {number} */ var res0 = (res & 0xffff);
586                         /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
587                         /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
588                         /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
590                         if (diff0 > maxDiff || diff1 > maxDiff) {
591                                 if (numFailed < maxPrints)
592                                         bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx +
593                                                                              ', expected packHalf2x16(' + inputs[valNdx] + ') = ' + ref /*tcu::toHex(ref)*/ +
594                                                                              ', got ' + res /*tcu::toHex(res)*/ +
595                                                                              '\n  diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
596                                 else if (numFailed == maxPrints)
597                                         bufferedLogToConsole('...');
599                                 numFailed += 1;
600                         }
601                 }
603                 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
605                 /** @type {boolean} */ var isOk = numFailed === 0;
606                 if (!isOk)
607                         testFailedOptions('Result comparison failed', false);
608                 else
609                         testPassedOptions('Pass', true);
611                 return tcuTestCase.IterateResult.STOP;
613         };
615         /**
616          * @constructor
617          * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
618          * @param {gluShaderProgram.shaderType} shaderType
619          */
620         es3fShaderPackingFunctionTests.UnpackHalf2x16Case = function(shaderType) {
621                 /** @const {string} */ var name = 'unpackhalf2x16' +
622                         es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
623                 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackHalf2x16', shaderType);
625                 this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
626                 this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_MEDIUMP)));
627                 this.m_spec.source = 'out0 = unpackHalf2x16(in0);';
628         };
630         es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
631         es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackHalf2x16Case;
633         /**
634          * @return {tcuTestCase.IterateResult}
635          */
636         es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.iterate = function() {
637                 /** @type {number} */ var maxDiff = 0; // All bits must be accurate.
638                 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
639                 /** @type {Array<number>} */ var inputs = [];
640                 /** @type {goog.TypedArray} */ var outputs; // vector<vec2<float>>
641                 /** @type {goog.TypedArray} */ var shaderExecutorOutput;
643                 // Special values.
644                 inputs.push((tcuFloat.newFloat16(0.0).bits() << 16) | tcuFloat.newFloat16(1.0).bits());
645                 inputs.push((tcuFloat.newFloat16(1.0).bits() << 16) | tcuFloat.newFloat16(0.0).bits());
646                 inputs.push((tcuFloat.newFloat16(-1.0).bits() << 16) | tcuFloat.newFloat16(0.5).bits());
647                 inputs.push((tcuFloat.newFloat16(0.5).bits() << 16) | tcuFloat.newFloat16(-0.5).bits());
649                 // Construct random values.
650                 /** @type {number} */ var minExp = -14;
651                 /** @type {number} */ var maxExp = 15;
652                 /** @type {number} */ var mantBits = 10;
654                 /** @type {number} */ var inVal = 0;
655                 for (var ndx = 0; ndx < 96; ndx++) {
656                         for (var c = 0; c < 2; c++) {
657                                 /** @type {number} */ var s = rnd.getBool() ? 1 : -1;
658                                 /** @type {number} */ var exp = rnd.getInt(minExp, maxExp);
659                                 /** @type {number} */ var mantissa = rnd.getInt(0) & ((1 << mantBits) - 1);
660                                 /** @type {number} */ var value = tcuFloat.newFloat16(0).construct(s, exp ? exp : 1 /* avoid denorm */, (1 << 10) | mantissa).bits();
662                                 inVal |= value << (16 * c);
663                         }
664                         inputs.push(inVal);
665                 }
667                 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
669                 this.m_executor.useProgram();
670                 shaderExecutorOutput  = this.m_executor.execute(inputs.length, [inputs])[0];
672                 // Convert outputs if we get them as Uint8Array.
673                 // - VertexShaderExecutor.execute() returns either an array of Uint8Array
674                 // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
675                 outputs = new Float32Array(shaderExecutorOutput.buffer);
677                 // Verify
678                 /** @type {number} */ var numValues = inputs.length
679                 /** @type {number} */ var maxPrints = 10;
680                 /** @type {number} */ var numFailed = 0;
682                 for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
683                         /** @type {number} */ var in0 = (inputs[valNdx] & 0xffff);
684                         /** @type {number} */ var in1 = deMath.shiftRight(inputs[valNdx], 16);
685                         /** @type {number} */ var ref0 = tcuFloat.halfFloatToNumber(in0);
686                         /** @type {number} */ var ref1 = tcuFloat.halfFloatToNumber(in1);
687                         /** @type {number} */ var res0 = outputs[2 * valNdx];
688                         /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
689                         /** @type {number} */ var refBits0 = tcuFloat.newFloat32(ref0).bits();
690                         /** @type {number} */ var refBits1 = tcuFloat.newFloat32(ref1).bits();
691                         /** @type {number} */ var resBits0 = tcuFloat.newFloat32(res0).bits();
692                         /** @type {number} */ var resBits1 = tcuFloat.newFloat32(res1).bits();
694                         /** @type {number} */ var diff0 = Math.abs(refBits0 - resBits0);
695                         /** @type {number} */ var diff1 = Math.abs(refBits1 - resBits1);
697                         if (isNaN(ref0) && isNaN(res0))
698                             diff0 = 0;
699                         if (isNaN(ref1) && isNaN(res1))
700                             diff1 = 0;
702                         if (diff0 > maxDiff || diff1 > maxDiff) {
703                                 if (numFailed < maxPrints)
704                                         bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
705                                                                          '  expected unpackHalf2x16(' + inputs[valNdx] /*tcu::toHex(inputs[valNdx])*/ + ') = ' +
706                                                                          'vec2(' + ref0 + ' / ' + refBits0 /*tcu::toHex(refBits0)*/ + ', ' + ref1 + ' / ' + refBits1 /*tcu::toHex(refBits1)*/ + ')' +
707                                                                          ', got vec2(' + res0 + ' / ' + resBits0 /*tcu::toHex(resBits0)*/ + ', ' + res1 + ' / ' + resBits1 /*tcu::toHex(resBits1)*/ + ')' +
708                                                                          '\n  ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
709                                 else if (numFailed == maxPrints)
710                                         bufferedLogToConsole('...');
712                                 numFailed += 1;
713                         }
714                 }
716                 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
718                 /** @type {boolean} */ var isOk = numFailed === 0;
719                 if (!isOk)
720                         testFailedOptions('Result comparison failed', false);
721                 else
722                         testPassedOptions('Pass', true);
724                 return tcuTestCase.IterateResult.STOP;
725         };
727         /**
728          * @constructor
729          * @extends {tcuTestCase.DeqpTest}
730          */
731         es3fShaderPackingFunctionTests.ShaderPackingFunctionTests = function() {
732                 tcuTestCase.DeqpTest.call(this, 'pack_unpack', 'Floating-point pack and unpack function tests');
733         };
735         es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
736         es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionTests;
738         es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype.init = function() {
739                 var testGroup = tcuTestCase.runner.testCases;
740                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_LOWP));
741                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_LOWP));
742                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_MEDIUMP));
743                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_MEDIUMP));
744                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_HIGHP));
745                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_HIGHP));
747                 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX));
748                 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT));
750                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_LOWP));
751                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_LOWP));
752                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_MEDIUMP));
753                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_MEDIUMP));
754                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_HIGHP));
755                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_HIGHP));
757                 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX));
758                 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT));
760                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.VERTEX));
761                 testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT));
763                 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.VERTEX));
764                 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT));
765         };
767     /**
768     * Run test
769     * @param {WebGL2RenderingContext} context
770     */
771     es3fShaderPackingFunctionTests.run = function(context) {
772         gl = context;
773         //Set up Test Root parameters
774         var state = tcuTestCase.runner;
775         state.setRoot(new es3fShaderPackingFunctionTests.ShaderPackingFunctionTests());
777         //Set up name and description of this test series.
778         setCurrentTestName(state.testCases.fullName());
779         description(state.testCases.getDescription());
781         try {
782                 //Run test cases
783                 tcuTestCase.runTestCases();
784         }
785         catch (err) {
786                 testFailedOptions('Failed to es3fShaderPackingFunctionTests.run tests', false);
787                 tcuTestCase.runner.terminate();
788         }
789     };