es3fShaderPackingFunctionTests.js (36071B)
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 */ 20 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'); 33 34 35 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 }; 58 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 }; 72 73 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 74 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionCase; 75 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 }; 82 83 es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype.deinit = function() { 84 this.m_executor = null; 85 }; 86 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 }; 100 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 }; 113 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; 126 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 }; 131 132 es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype); 133 es3fShaderPackingFunctionTests.PackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackSnorm2x16Case; 134 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]); 154 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 } 161 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 } 168 169 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values'); 170 171 this.m_executor.useProgram(); 172 shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0]; 173 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); 178 179 // Verify 180 /** @type {number} */ var numValues = inputs.length; 181 /** @type {number} */ var maxPrints = 10; 182 /** @type {number} */ var numFailed = 0; 183 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); 193 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('...'); 204 205 numFailed += 1; 206 } 207 } 208 209 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed'); 210 211 /** @type {boolean} */ var isOk = numFailed === 0; 212 if (!isOk) 213 testFailedOptions('Result comparison failed', false); 214 else 215 testPassedOptions('Pass', true); 216 217 return tcuTestCase.IterateResult.STOP; 218 }; 219 220 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); 229 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 }; 234 235 es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype); 236 es3fShaderPackingFunctionTests.UnpackSnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackSnorm2x16Case; 237 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>> 247 248 inputs.push(0x00000000); 249 inputs.push(0x7fff8000); 250 inputs.push(0x80007fff); 251 inputs.push(0xffffffff); 252 inputs.push(0x0001fffe); 253 254 // Random values. 255 for (var ndx = 0; ndx < 95; ndx++) 256 inputs.push(rnd.getInt()); 257 258 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values'); 259 260 this.m_executor.useProgram(); 261 shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0]; // This test case only has one output 262 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); 267 268 // Verify 269 /** @type {number} */ var numValues = inputs.length; 270 /** @type {number} */ var maxPrints = 10; 271 /** @type {number} */ var numFailed = 0; 272 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]; 288 289 /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0); 290 /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1); 291 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('...'); 301 302 numFailed += 1; 303 } 304 } 305 306 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed'); 307 308 /** @type {boolean} */ var isOk = numFailed === 0; 309 if (!isOk) 310 testFailedOptions('Result comparison failed', false); 311 else 312 testPassedOptions('Pass', true); 313 314 return tcuTestCase.IterateResult.STOP; 315 }; 316 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; 329 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 }; 334 335 es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype); 336 es3fShaderPackingFunctionTests.PackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackUnorm2x16Case; 337 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]); 357 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 } 364 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 } 371 372 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values'); 373 374 this.m_executor.useProgram(); 375 shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0]; 376 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); 381 382 // Verify 383 /** @type {number} */ var numValues = inputs.length; 384 /** @type {number} */ var maxPrints = 10; 385 /** @type {number} */ var numFailed = 0; 386 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); 396 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('...'); 405 406 numFailed += 1; 407 } 408 } 409 410 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed'); 411 412 /** @type {boolean} */ var isOk = numFailed === 0; 413 if (!isOk) 414 testFailedOptions('Result comparison failed', false); 415 else 416 testPassedOptions('Pass', true); 417 418 return tcuTestCase.IterateResult.STOP; 419 }; 420 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); 430 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 }; 435 436 es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype); 437 es3fShaderPackingFunctionTests.UnpackUnorm2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackUnorm2x16Case; 438 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> 448 449 inputs.push(0x00000000); 450 inputs.push(0x7fff8000); 451 inputs.push(0x80007fff); 452 inputs.push(0xffffffff); 453 inputs.push(0x0001fffe); 454 455 // Random values. 456 for (var ndx = 0; ndx < 95; ndx++) 457 inputs.push(rnd.getInt()); 458 459 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values'); 460 461 this.m_executor.useProgram(); 462 shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0]; 463 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); 468 469 // Verify 470 /** @type {number} */ var numValues = inputs.length; 471 /** @type {number} */ var maxPrints = 10; 472 /** @type {number} */ var numFailed = 0; 473 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]; 481 482 /** @type {number} */ var diff0 = es3fShaderPackingFunctionTests.getUlpDiff(ref0, res0); 483 /** @type {number} */ var diff1 = es3fShaderPackingFunctionTests.getUlpDiff(ref1, res1); 484 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('...'); 494 495 numFailed += 1; 496 } 497 } 498 499 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed'); 500 501 /** @type {boolean} */ var isOk = numFailed === 0; 502 if (!isOk) 503 testFailedOptions('Result comparison failed', false); 504 else 505 testPassedOptions('Pass', true); 506 507 return tcuTestCase.IterateResult.STOP; 508 }; 509 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); 519 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 }; 524 525 es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype); 526 es3fShaderPackingFunctionTests.PackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.PackHalf2x16Case; 527 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 537 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]); 544 545 // Random values. 546 /** @type {number} */ var minExp = -14; 547 /** @type {number} */ var maxExp = 15; 548 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); 555 556 v[c] = (new tcuFloat.deFloat()).construct(s, exp ? exp : 1 /* avoid denormals */, (1 << 23) | mantissa).getValue(); 557 } 558 inputs.push(v); 559 } 560 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()]; 564 565 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values'); 566 567 this.m_executor.useProgram(); 568 shaderExecutorOutput = this.m_executor.execute(inputs.length, [tcuMatrixUtil.flatten(inputs)])[0]; 569 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); 574 575 // Verify 576 /** @type {number} */ var numValues = inputs.length; 577 /** @type {number} */ var maxPrints = 10; 578 /** @type {number} */ var numFailed = 0; 579 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); 589 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('...'); 598 599 numFailed += 1; 600 } 601 } 602 603 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed'); 604 605 /** @type {boolean} */ var isOk = numFailed === 0; 606 if (!isOk) 607 testFailedOptions('Result comparison failed', false); 608 else 609 testPassedOptions('Pass', true); 610 611 return tcuTestCase.IterateResult.STOP; 612 613 }; 614 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); 624 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 }; 629 630 es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype = Object.create(es3fShaderPackingFunctionTests.ShaderPackingFunctionCase.prototype); 631 es3fShaderPackingFunctionTests.UnpackHalf2x16Case.prototype.constructor = es3fShaderPackingFunctionTests.UnpackHalf2x16Case; 632 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; 642 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()); 648 649 // Construct random values. 650 /** @type {number} */ var minExp = -14; 651 /** @type {number} */ var maxExp = 15; 652 /** @type {number} */ var mantBits = 10; 653 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(); 661 662 inVal |= value << (16 * c); 663 } 664 inputs.push(inVal); 665 } 666 667 bufferedLogToConsole('Executing shader for ' + inputs.length + ' input values'); 668 669 this.m_executor.useProgram(); 670 shaderExecutorOutput = this.m_executor.execute(inputs.length, [inputs])[0]; 671 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); 676 677 // Verify 678 /** @type {number} */ var numValues = inputs.length 679 /** @type {number} */ var maxPrints = 10; 680 /** @type {number} */ var numFailed = 0; 681 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(); 693 694 /** @type {number} */ var diff0 = Math.abs(refBits0 - resBits0); 695 /** @type {number} */ var diff1 = Math.abs(refBits1 - resBits1); 696 697 if (isNaN(ref0) && isNaN(res0)) 698 diff0 = 0; 699 if (isNaN(ref1) && isNaN(res1)) 700 diff1 = 0; 701 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('...'); 711 712 numFailed += 1; 713 } 714 } 715 716 bufferedLogToConsole((numValues - numFailed) + ' / ' + numValues + ' values passed'); 717 718 /** @type {boolean} */ var isOk = numFailed === 0; 719 if (!isOk) 720 testFailedOptions('Result comparison failed', false); 721 else 722 testPassedOptions('Pass', true); 723 724 return tcuTestCase.IterateResult.STOP; 725 }; 726 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 }; 734 735 es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 736 es3fShaderPackingFunctionTests.ShaderPackingFunctionTests.prototype.constructor = es3fShaderPackingFunctionTests.ShaderPackingFunctionTests; 737 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)); 746 747 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.VERTEX)); 748 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackSnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT)); 749 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)); 756 757 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.VERTEX)); 758 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackUnorm2x16Case(gluShaderProgram.shaderType.FRAGMENT)); 759 760 testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.VERTEX)); 761 testGroup.addChild(new es3fShaderPackingFunctionTests.PackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT)); 762 763 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.VERTEX)); 764 testGroup.addChild(new es3fShaderPackingFunctionTests.UnpackHalf2x16Case(gluShaderProgram.shaderType.FRAGMENT)); 765 }; 766 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()); 776 777 //Set up name and description of this test series. 778 setCurrentTestName(state.testCases.fullName()); 779 description(state.testCases.getDescription()); 780 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 }; 790 791 });