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.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;
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;
61 * @extends {tcuTestCase.DeqpTest}
62 * @param {string} name
63 * @param {string} description
64 * @param {gluShaderProgram.shaderType} shaderType
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;
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');
83 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.deinit = function() {
84 this.m_executor = null;
88 * @param {gluShaderUtil.precision} precision
91 es3fShaderPackingFunctionTests.getPrecisionPostfix = function(precision) {
92 /** @type {Array<string>} */ var s_postfix = [
97 assertMsgOptions(0 <= precision && precision < s_postfix.length, 'Error: Out of range', false, true);
98 return s_postfix[precision];
102 * @param {gluShaderProgram.shaderType} shaderType
105 es3fShaderPackingFunctionTests.getShaderTypePostfix = function(shaderType) {
106 /** @type {Array<string>} */ var s_postfix = [
110 assertMsgOptions(0 <= shaderType && shaderType < s_postfix.length, 'Error Out of range', false, true);
111 return s_postfix[shaderType];
116 * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
117 * @param {gluShaderProgram.shaderType} shaderType
118 * @param {gluShaderUtil.precision} precision
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);';
132 es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
133 es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackSnorm2x16Case;
136 * @return {tcuTestCase.IterateResult}
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;
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;
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);
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);
202 else if (numFailed == maxPrints)
203 bufferedLogToConsole('...');
209 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
211 /** @type {boolean} */ var isOk = numFailed === 0;
213 testFailedOptions('Result comparison failed', false);
215 testPassedOptions('Pass', true);
217 return tcuTestCase.IterateResult.STOP;
223 * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
224 * @param {gluShaderProgram.shaderType} shaderType
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);';
235 es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
236 es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackSnorm2x16Case;
239 * @return {tcuTestCase.IterateResult}
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);
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);
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('...');
306 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
308 /** @type {boolean} */ var isOk = numFailed === 0;
310 testFailedOptions('Result comparison failed', false);
312 testPassedOptions('Pass', true);
314 return tcuTestCase.IterateResult.STOP;
319 * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
320 * @param {gluShaderProgram.shaderType} shaderType
321 * @param {gluShaderUtil.precision} precision
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);';
335 es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
336 es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackUnorm2x16Case;
339 * @return {tcuTestCase.IterateResult}
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;
365 // Large random values.
366 for (var ndx = 0; ndx < 80; ndx++) {
367 x = rnd.getFloat() * 1e6 - 1e5;
368 y = rnd.getFloat() * 1e6 - 1e5;
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);
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('...');
410 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
412 /** @type {boolean} */ var isOk = numFailed === 0;
414 testFailedOptions('Result comparison failed', false);
416 testPassedOptions('Pass', true);
418 return tcuTestCase.IterateResult.STOP;
423 * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
424 * @param {gluShaderProgram.shaderType} shaderType
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);';
436 es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
437 es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackUnorm2x16Case;
440 * @return {tcuTestCase.IterateResult}
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);
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);
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('...');
499 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
501 /** @type {boolean} */ var isOk = numFailed === 0;
503 testFailedOptions('Result comparison failed', false);
505 testPassedOptions('Pass', true);
507 return tcuTestCase.IterateResult.STOP;
512 * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
513 * @param {gluShaderProgram.shaderType} shaderType
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);';
525 es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
526 es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackHalf2x16Case;
529 * @return {tcuTestCase.IterateResult}
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]);
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();
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);
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('...');
603 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
605 /** @type {boolean} */ var isOk = numFailed === 0;
607 testFailedOptions('Result comparison failed', false);
609 testPassedOptions('Pass', true);
611 return tcuTestCase.IterateResult.STOP;
617 * @extends {es3fShaderPackingFunctionTests.ShaderPackingFunctionCase}
618 * @param {gluShaderProgram.shaderType} shaderType
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);';
630 es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype);
631 es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackHalf2x16Case;
634 * @return {tcuTestCase.IterateResult}
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;
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);
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);
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))
699 if (isNaN(ref1) && isNaN(res1))
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('...');
716 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed');
718 /** @type {boolean} */ var isOk = numFailed === 0;
720 testFailedOptions('Result comparison failed', false);
722 testPassedOptions('Pass', true);
724 return tcuTestCase.IterateResult.STOP;
729 * @extends {tcuTestCase.DeqpTest}
731 es3fShaderPackingFunctionTests.ShaderPackingFunctionTests = function() {
732 tcuTestCase.DeqpTest.call(this, 'pack_unpack', 'Floating-point pack and unpack function tests');
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));
769 * @param {WebGL2RenderingContext} context
771 es3fShaderPackingFunctionTests.run = function(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());
783 tcuTestCase.runTestCases();
786 testFailedOptions('Failed to es3fShaderPackingFunctionTests.run tests', false);
787 tcuTestCase.runner.terminate();