summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js791
1 files changed, 791 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js
new file mode 100644
index 0000000000..3e4233db4c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderPackingFunctionTests.js
@@ -0,0 +1,791 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderPackingFunctionTests');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuMatrixUtil');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.delibs.debase.deRandom');
+goog.require('framework.delibs.debase.deString');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluVarType');
+goog.require('modules.shared.glsShaderExecUtil');
+
+
+
+goog.scope(function() {
+ var es3fShaderPackingFunctionTests = functional.gles3.es3fShaderPackingFunctionTests;
+ var tcuFloat = framework.common.tcuFloat;
+ var tcuTestCase = framework.common.tcuTestCase;
+ var deMath = framework.delibs.debase.deMath;
+ var deRandom = framework.delibs.debase.deRandom;
+ var deString = framework.delibs.debase.deString;
+ var gluShaderProgram = framework.opengl.gluShaderProgram;
+ var gluShaderUtil = framework.opengl.gluShaderUtil;
+ var gluVarType = framework.opengl.gluVarType;
+ var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
+ var tcuMatrixUtil = framework.common.tcuMatrixUtil;
+ /**
+ * @param {number} a
+ * @param {number} b
+ * @return {number}
+ */
+ es3fShaderPackingFunctionTests.getUlpDiff = function(a, b) {
+ /** @type {number} */ var aBits = tcuFloat.newFloat32(a).bits();
+ /** @type {number} */ var bBits = tcuFloat.newFloat32(b).bits();
+ return aBits > bBits ? aBits - bBits : bBits - aBits;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ * @param {string} name
+ * @param {string} description
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase = function(name, description, shaderType) {
+ tcuTestCase.DeqpTest.call(this, name, description);
+ /** @type {gluShaderProgram.shaderType} */ this.m_shaderType = shaderType;
+ /** @type {?glsShaderExecUtil.ShaderSpec} */ this.m_spec = new glsShaderExecUtil.ShaderSpec();
+ /** @type {?glsShaderExecUtil.ShaderExecutor} */ this.m_executor = null;
+ };
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionCase;
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.init = function() {
+ assertMsgOptions(!this.m_executor, 'Error: Executor is not null.', false, true);
+ this.m_executor = glsShaderExecUtil.createExecutor(this.m_shaderType, this.m_spec);
+ if (!this.m_executor.isOk())
+ throw new Error('Compile failed');
+ };
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.deinit = function() {
+ this.m_executor = null;
+ };
+
+ /**
+ * @param {gluShaderUtil.precision} precision
+ * @return {string}
+ */
+ es3fShaderPackingFunctionTests.getPrecisionPostfix = function(precision) {
+ /** @type {Array<string>} */ var s_postfix = [
+ '_lowp',
+ '_mediump',
+ '_highp'
+ ];
+ assertMsgOptions(0 <= precision && precision < s_postfix.length, 'Error: Out of range', false, true);
+ return s_postfix[precision];
+ };
+
+ /**
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @return {string}
+ */
+ es3fShaderPackingFunctionTests.getShaderTypePostfix = function(shaderType) {
+ /** @type {Array<string>} */ var s_postfix = [
+ '_vertex',
+ '_fragment'
+ ];
+ assertMsgOptions(0 <= shaderType && shaderType < s_postfix.length, 'Error Out of range', false, true);
+ return s_postfix[shaderType];
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {gluShaderUtil.precision} precision
+ */
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case = function(shaderType, precision) {
+ /** @const {string} */ var name = 'packsnorm2x16' +
+ es3fShaderPackingFunctionTests.getPrecisionPostfix(precision) +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packSnorm2x16', shaderType);
+ this.m_precision = precision;
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = packSnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackSnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.iterate = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<Array<number>>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var outputs; // deUint32
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {number} */ var maxDiff = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : // Rounding only.
+ this.m_precision == gluShaderUtil.precision.PRECISION_MEDIUMP ? 33 : // (2^-10) * (2^15) + 1
+ this.m_precision == gluShaderUtil.precision.PRECISION_LOWP ? 129 : 0; // (2^-8) * (2^15) + 1
+ /** @type {number} */ var x;
+ /** @type {number} */ var y;
+ // Special values to check.
+ inputs.push([0.0, 0.0]);
+ inputs.push([-1.0, 1.0]);
+ inputs.push([0.5, -0.5]);
+ inputs.push([-1.5, 1.5]);
+ inputs.push([0.25, -0.75]);
+
+ // Random values, mostly in range.
+ for (var ndx = 0; ndx < 15; ndx++) {
+ x = rnd.getFloat() * 2.5 - 1.25;
+ y = rnd.getFloat() * 2.5 - 1.25;
+ inputs.push([x, y]);
+ }
+
+ // Large random values.
+ for (var ndx = 0; ndx < 80; ndx++) {
+ x = rnd.getFloat() * 1e6 - 0.5e6;
+ y = rnd.getFloat() * 1e6 - 0.5e6;
+ inputs.push([x, y]);
+ }
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Uint32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < numValues; valNdx++) {
+ /** @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;
+ /** @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;
+ /** @type {number} */ var ref = (ref1 << 16) | ref0;
+ /** @type {number} */ var res = outputs[valNdx];
+ /** @type {number} */ var res0 = (res & 0xffff);
+ /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
+ /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
+ /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints) {
+ bufferedLogToConsole(
+ 'ERROR: Mismatch in value ' + valNdx +
+ ', expected packSnorm2x16(' + inputs[valNdx] + ') = ' + ref + //tcu::toHex(ref)
+ ', got ' + res + // tcu::toHex(res)
+ '\n diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ }
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'unpacksnorm2x16' + es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackSnorm2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = unpackSnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackSnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 1; // Rounding error.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<number>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput; //vector<vec2<float>>
+ /** @type {goog.TypedArray} */ var outputs; //vector<vec2<float>>
+
+ inputs.push(0x00000000);
+ inputs.push(0x7fff8000);
+ inputs.push(0x80007fff);
+ inputs.push(0xffffffff);
+ inputs.push(0x0001fffe);
+
+ // Random values.
+ for (var ndx = 0; ndx < 95; ndx++)
+ inputs.push(rnd.getInt());
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0]; // This test case only has one output
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Float32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var in0 = Math.floor(inputs[valNdx] & 0xffff);
+ // Convert 16-bit uint to 16-bit int
+ var view = new DataView(new ArrayBuffer(4));
+ view.setUint16(0, in0, true);
+ in0 = view.getInt16(0, true);
+ /** @type {number} */ var in1 = Math.floor(deMath.shiftRight(inputs[valNdx], 16));
+ // Convert 16-bit uint to 16-bit int
+ var view = new DataView(new ArrayBuffer(4));
+ view.setUint16(0, in1, true);
+ in1 = view.getInt16(0, true);
+ /** @type {number} */ var ref0 = deMath.clamp(in0 / 32767., -1.0, 1.0);
+ /** @type {number} */ var ref1 = deMath.clamp(in1 / 32767., -1.0, 1.0);
+ /** @type {number} */ var res0 = outputs[2 * valNdx];
+ /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
+
+ /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0);
+ /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
+ ' expected unpackSnorm2x16(' + inputs[valNdx].toString(16) + ') = ' +
+ 'vec2(' + ref0.toString(16) + ', ' + ref1.toString(16) + ')' +
+ ', got vec2(' + res0.toString(16) + ', ' + res1.toString(16) + ')' +
+ '\n ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ * @param {gluShaderUtil.precision} precision
+ */
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case = function(shaderType, precision) {
+ /** @const {string} */ var name = 'packunorm2x16' +
+ es3fShaderPackingFunctionTests.getPrecisionPostfix(precision) +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packUnorm2x16', shaderType);
+ this.m_precision = precision;
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, precision)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = packUnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackUnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.iterate = function() {
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<Array<number>>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {goog.TypedArray} */ var outputs; // deUint32
+ /** @type {number} */ var maxDiff = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : // Rounding only.
+ this.m_precision == gluShaderUtil.precision.PRECISION_MEDIUMP ? 65 : // (2^-10) * (2^16) + 1
+ this.m_precision == gluShaderUtil.precision.PRECISION_LOWP ? 257 : 0; // (2^-8) * (2^16) + 1
+ /** @type {number} */ var x;
+ /** @type {number} */ var y;
+ // Special values to check.
+ inputs.push([0.0, 0.0]);
+ inputs.push([0.5, 1.0]);
+ inputs.push([1.0, 0.5]);
+ inputs.push([-0.5, 1.5]);
+ inputs.push([0.25, 0.75]);
+
+ // Random values, mostly in range.
+ for (var ndx = 0; ndx < 15; ndx++) {
+ x = rnd.getFloat() * 1.25;
+ y = rnd.getFloat() * 1.25;
+ inputs.push([x, y]);
+ }
+
+ // Large random values.
+ for (var ndx = 0; ndx < 80; ndx++) {
+ x = rnd.getFloat() * 1e6 - 1e5;
+ y = rnd.getFloat() * 1e6 - 1e5;
+ inputs.push([x, y]);
+ }
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Uint32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var ref0 = deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][0], 0.0, 1.0) * 65535.0), 0, (1 << 16) - 1) & 0xFFFF;
+ /** @type {number} */ var ref1 = deMath.clamp(Math.floor(deMath.clamp(inputs[valNdx][1], 0.0, 1.0) * 65535.0), 0, (1 << 16) - 1) & 0xFFFF;
+ /** @type {number} */ var ref = (ref1 << 16) | ref0;
+ /** @type {number} */ var res = outputs[valNdx];
+ /** @type {number} */ var res0 = (res & 0xffff);
+ /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
+ /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
+ /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx +
+ ', expected packUnorm2x16(' + inputs[valNdx] + ') = ' + ref /*tcu::toHex(ref)*/ +
+ ', got ' + res /*tcu::toHex(res)*/ +
+ '\n diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed === maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'unpackunorm2x16' +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackUnorm2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = unpackUnorm2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackUnorm2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 1; // Rounding error.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<number>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {goog.TypedArray} */ var outputs; //vector<vec2>
+
+ inputs.push(0x00000000);
+ inputs.push(0x7fff8000);
+ inputs.push(0x80007fff);
+ inputs.push(0xffffffff);
+ inputs.push(0x0001fffe);
+
+ // Random values.
+ for (var ndx = 0; ndx < 95; ndx++)
+ inputs.push(rnd.getInt());
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Float32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var in0 = Math.floor(inputs[valNdx] & 0xffff);
+ /** @type {number} */ var in1 = Math.floor(deMath.shiftRight(inputs[valNdx], 16));
+ /** @type {number} */ var ref0 = in0 / 65535.0;
+ /** @type {number} */ var ref1 = in1 / 65535.0;
+ /** @type {number} */ var res0 = outputs[2 * valNdx];
+ /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
+
+ /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0);
+ /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
+ ' expected unpackUnorm2x16(' + inputs[valNdx].toString(16) + ') = ' +
+ 'vec2(' + ref0.toString(16) + ', ' + ref1.toString(16) + ')' +
+ ', got vec2(' + res0.toString(16) + ', ' + res1.toString(16) + ')' +
+ '\n ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed === maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.PackHalf2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'packhalf2x16' +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'packHalf2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.source = 'out0 = packHalf2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackHalf2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 0; // Values can be represented exactly in mediump.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<Array<number>>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+ /** @type {goog.TypedArray} */ var outputs; // deUint32
+
+ // Special values to check.
+ inputs.push([0.0, 0.0]);
+ inputs.push([0.5, 1.0]);
+ inputs.push([1.0, 0.5]);
+ inputs.push([-0.5, 1.5]);
+ inputs.push([0.25, 0.75]);
+
+ // Random values.
+ /** @type {number} */ var minExp = -14;
+ /** @type {number} */ var maxExp = 15;
+
+ /** @type {Array<number>} */ var v = [];
+ for (var ndx = 0; ndx < 95; ndx++) {
+ for (var c = 0; c < 2; c++) {
+ /** @type {number} */ var s = rnd.getBool() ? 1 : -1;
+ /** @type {number} */ var exp = rnd.getInt(minExp, maxExp);
+ /** @type {number} */ var mantissa = rnd.getInt(0) & ((1 << 23) - 1);
+
+ v[c] = (new tcuFloat.deFloat()).construct(s, exp ? exp : 1 /* avoid denormals */, (1 << 23) | mantissa).getValue();
+ }
+ inputs.push(v);
+ }
+
+ // Convert input values to fp16 and back to make sure they can be represented exactly in mediump.
+ for (var inVal in inputs)
+ inputs[inVal] = [tcuFloat.newFloat16(inputs[inVal][0]).getValue(), tcuFloat.newFloat16(inputs[inVal][1]).getValue()];
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Uint32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length;
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var ref0 = tcuFloat.newFloat16(inputs[valNdx][0]).bits();
+ /** @type {number} */ var ref1 = tcuFloat.newFloat16(inputs[valNdx][1]).bits();
+ /** @type {number} */ var ref = (ref1 << 16) | ref0;
+ /** @type {number} */ var res = outputs[valNdx];
+ /** @type {number} */ var res0 = (res & 0xffff);
+ /** @type {number} */ var res1 = deMath.shiftRight(res, 16);
+ /** @type {number} */ var diff0 = Math.abs(ref0 - res0);
+ /** @type {number} */ var diff1 = Math.abs(ref1 - res1);
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx +
+ ', expected packHalf2x16(' + inputs[valNdx] + ') = ' + ref /*tcu::toHex(ref)*/ +
+ ', got ' + res /*tcu::toHex(res)*/ +
+ '\n diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+
+ };
+
+ /**
+ * @constructor
+ * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
+ * @param {gluShaderProgram.shaderType} shaderType
+ */
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case = function(shaderType) {
+ /** @const {string} */ var name = 'unpackhalf2x16' +
+ es3fShaderPackingFunctionTests.getShaderTypePostfix(shaderType);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.call(this, name, 'unpackHalf2x16', shaderType);
+
+ this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(gluShaderUtil.DataType.UINT, gluShaderUtil.precision.PRECISION_HIGHP)));
+ this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.precision.PRECISION_MEDIUMP)));
+ this.m_spec.source = 'out0 = unpackHalf2x16(in0);';
+ };
+
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackHalf2x16Case;
+
+ /**
+ * @return {tcuTestCase.IterateResult}
+ */
+ es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.iterate = function() {
+ /** @type {number} */ var maxDiff = 0; // All bits must be accurate.
+ /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x776002);
+ /** @type {Array<number>} */ var inputs = [];
+ /** @type {goog.TypedArray} */ var outputs; // vector<vec2<float>>
+ /** @type {goog.TypedArray} */ var shaderExecutorOutput;
+
+ // Special values.
+ inputs.push((tcuFloat.newFloat16(0.0).bits() << 16) | tcuFloat.newFloat16(1.0).bits());
+ inputs.push((tcuFloat.newFloat16(1.0).bits() << 16) | tcuFloat.newFloat16(0.0).bits());
+ inputs.push((tcuFloat.newFloat16(-1.0).bits() << 16) | tcuFloat.newFloat16(0.5).bits());
+ inputs.push((tcuFloat.newFloat16(0.5).bits() << 16) | tcuFloat.newFloat16(-0.5).bits());
+
+ // Construct random values.
+ /** @type {number} */ var minExp = -14;
+ /** @type {number} */ var maxExp = 15;
+ /** @type {number} */ var mantBits = 10;
+
+ /** @type {number} */ var inVal = 0;
+ for (var ndx = 0; ndx < 96; ndx++) {
+ for (var c = 0; c < 2; c++) {
+ /** @type {number} */ var s = rnd.getBool() ? 1 : -1;
+ /** @type {number} */ var exp = rnd.getInt(minExp, maxExp);
+ /** @type {number} */ var mantissa = rnd.getInt(0) & ((1 << mantBits) - 1);
+ /** @type {number} */ var value = tcuFloat.newFloat16(0).construct(s, exp ? exp : 1 /* avoid denorm */, (1 << 10) | mantissa).bits();
+
+ inVal |= value << (16 * c);
+ }
+ inputs.push(inVal);
+ }
+
+ bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values');
+
+ this.m_executor.useProgram();
+ shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0];
+
+ // Convert outputs if we get them as Uint8Array.
+ // - VertexShaderExecutor.execute() returns either an array of Uint8Array
+ // - FragmentShaderExecutor.execute() returns either an array of Uint8Array or Uint32Array
+ outputs = new Float32Array(shaderExecutorOutput.buffer);
+
+ // Verify
+ /** @type {number} */ var numValues = inputs.length
+ /** @type {number} */ var maxPrints = 10;
+ /** @type {number} */ var numFailed = 0;
+
+ for (var valNdx = 0; valNdx < inputs.length; valNdx++) {
+ /** @type {number} */ var in0 = (inputs[valNdx] & 0xffff);
+ /** @type {number} */ var in1 = deMath.shiftRight(inputs[valNdx], 16);
+ /** @type {number} */ var ref0 = tcuFloat.halfFloatToNumber(in0);
+ /** @type {number} */ var ref1 = tcuFloat.halfFloatToNumber(in1);
+ /** @type {number} */ var res0 = outputs[2 * valNdx];
+ /** @type {number} */ var res1 = outputs[2 * valNdx + 1];
+ /** @type {number} */ var refBits0 = tcuFloat.newFloat32(ref0).bits();
+ /** @type {number} */ var refBits1 = tcuFloat.newFloat32(ref1).bits();
+ /** @type {number} */ var resBits0 = tcuFloat.newFloat32(res0).bits();
+ /** @type {number} */ var resBits1 = tcuFloat.newFloat32(res1).bits();
+
+ /** @type {number} */ var diff0 = Math.abs(refBits0 - resBits0);
+ /** @type {number} */ var diff1 = Math.abs(refBits1 - resBits1);
+
+ if (isNaN(ref0) && isNaN(res0))
+ diff0 = 0;
+ if (isNaN(ref1) && isNaN(res1))
+ diff1 = 0;
+
+ if (diff0 > maxDiff || diff1 > maxDiff) {
+ if (numFailed < maxPrints)
+ bufferedLogToConsole('ERROR: Mismatch in value ' + valNdx + ',\n' +
+ ' expected unpackHalf2x16(' + inputs[valNdx] /*tcu::toHex(inputs[valNdx])*/ + ') = ' +
+ 'vec2(' + ref0 + ' / ' + refBits0 /*tcu::toHex(refBits0)*/ + ', ' + ref1 + ' / ' + refBits1 /*tcu::toHex(refBits1)*/ + ')' +
+ ', got vec2(' + res0 + ' / ' + resBits0 /*tcu::toHex(resBits0)*/ + ', ' + res1 + ' / ' + resBits1 /*tcu::toHex(resBits1)*/ + ')' +
+ '\n ULP diffs = (' + diff0 + ', ' + diff1 + '), max diff = ' + maxDiff);
+ else if (numFailed == maxPrints)
+ bufferedLogToConsole('...');
+
+ numFailed += 1;
+ }
+ }
+
+ bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
+
+ /** @type {boolean} */ var isOk = numFailed === 0;
+ if (!isOk)
+ testFailedOptions('Result comparison failed', false);
+ else
+ testPassedOptions('Pass', true);
+
+ return tcuTestCase.IterateResult.STOP;
+ };
+
+ /**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'pack_unpack', 'Floating-point pack and unpack function tests');
+ };
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionTests;
+
+ es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_HIGHP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_HIGHP));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_LOWP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_MEDIUMP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX, gluShaderUtil.precision.PRECISION_HIGHP));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT, gluShaderUtil.precision.PRECISION_HIGHP));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.VERTEX));
+ testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT));
+ };
+
+ /**
+ * Run test
+ * @param {WebGL2RenderingContext} context
+ */
+ es3fShaderPackingFunctionTests.run = function(context) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderPackingFunctionTests.ShaderPackingFunctionTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+
+ try {
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderPackingFunctionTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+ };
+
+});