es3fShaderPrecisionTests.js (48813B)
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.es3fShaderPrecisionTests'); 23 goog.require('framework.common.tcuTestCase'); 24 goog.require('framework.common.tcuFloat'); 25 goog.require('framework.delibs.debase.deMath'); 26 goog.require('framework.delibs.debase.deRandom'); 27 goog.require('framework.delibs.debase.deString'); 28 goog.require('framework.opengl.gluDrawUtil'); 29 goog.require('framework.opengl.gluShaderProgram'); 30 goog.require('framework.opengl.gluShaderUtil'); 31 32 goog.scope(function() { 33 var es3fShaderPrecisionTests = functional.gles3.es3fShaderPrecisionTests; 34 var deMath = framework.delibs.debase.deMath; 35 var deRandom = framework.delibs.debase.deRandom; 36 var deString = framework.delibs.debase.deString; 37 var tcuFloat = framework.common.tcuFloat; 38 var tcuTestCase = framework.common.tcuTestCase; 39 var gluDrawUtil = framework.opengl.gluDrawUtil; 40 var gluShaderUtil = framework.opengl.gluShaderUtil; 41 var gluShaderProgram = framework.opengl.gluShaderProgram; 42 43 /** @const {number} */ es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH = 32; 44 /** @const {number} */ es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT = 32; 45 46 es3fShaderPrecisionTests.add = function(a, b) { return a + b; }; 47 es3fShaderPrecisionTests.sub = function(a, b) { return a - b; }; 48 es3fShaderPrecisionTests.mul = function(a, b) { return a * b; }; 49 // a * b = (a1 * 2^16 + a0) * (b1 * 2^16 + b0) = a1 * b1 * 2^32 + (a0 * b1 + a1 * b0) * 2^16 + a0 * b0 50 // 32bit integer multiplication may overflow in JavaScript. Only return low 32bit of the result. 51 es3fShaderPrecisionTests.mul32 = function(a, b) { 52 var sign = Math.sign(a) * Math.sign(b); 53 a = Math.abs(a); 54 b = Math.abs(b); 55 var a1 = deMath.split16(a)[1]; 56 var a0 = deMath.split16(a)[0]; 57 var b1 = deMath.split16(b)[1]; 58 var b0 = deMath.split16(b)[0]; 59 return sign * ((a0 * b1 + a1 * b0) * 0x10000 + a0 * b0); 60 } 61 es3fShaderPrecisionTests.div = function(a, b) { if (b !== 0) return a / b; else throw new Error('division by zero.')}; 62 63 /** 64 * @param {gluShaderUtil.precision} precision 65 * @param {string} evalOp 66 * @param {boolean} isVertexCase 67 * @return {gluShaderProgram.ShaderProgram} 68 */ 69 es3fShaderPrecisionTests.createFloatPrecisionEvalProgram = function(precision, evalOp, isVertexCase) { 70 /** @type {gluShaderUtil.DataType} */ var type = gluShaderUtil.DataType.FLOAT; 71 /** @type {gluShaderUtil.DataType} */ var outType = gluShaderUtil.DataType.UINT; 72 /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(type); 73 /** @type {string} */ var outTypeName = gluShaderUtil.getDataTypeName(outType); 74 /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision); 75 /** @type {string} */ var vtx = ''; 76 /** @type {string} */ var frag = ''; 77 /** @type {string} */ var op = ''; 78 79 vtx += '#version 300 es\n' + 80 'in highp vec4 a_position;\n' + 81 'in ' + precName + ' ' + typeName + ' a_in0;\n' + 82 'in ' + precName + ' ' + typeName + ' a_in1;\n'; 83 frag += '#version 300 es\n' + 84 'layout(location = 0) out highp ' + outTypeName + ' o_out;\n'; 85 86 if (isVertexCase) { 87 vtx += 'flat out ' + precName + ' ' + typeName + ' v_out;\n'; 88 frag += 'flat in ' + precName + ' ' + typeName + ' v_out;\n'; 89 } else { 90 vtx += 'flat out ' + precName + ' ' + typeName + ' v_in0;\n' + 91 'flat out ' + precName + ' ' + typeName + ' v_in1;\n'; 92 frag += 'flat in ' + precName + ' ' + typeName + ' v_in0;\n' + 93 'flat in ' + precName + ' ' + typeName + ' v_in1;\n'; 94 } 95 96 vtx += '\nvoid main (void)\n{\n' + 97 ' gl_Position = a_position;\n'; 98 frag += '\nvoid main (void)\n{\n'; 99 100 op += '\t' + precName + ' ' + typeName + ' in0 = ' + (isVertexCase ? 'a_' : 'v_') + 'in0;\n' + 101 '\t' + precName + ' ' + typeName + ' in1 = ' + (isVertexCase ? 'a_' : 'v_') + 'in1;\n'; 102 103 if (!isVertexCase) 104 op += '\t' + precName + ' ' + typeName + ' res;\n'; 105 106 op += '\t' + (isVertexCase ? 'v_out' : 'res') + ' = ' + evalOp + ';\n'; 107 108 vtx += isVertexCase ? op : ''; 109 frag += isVertexCase ? '' : op; 110 op = ''; 111 112 if (isVertexCase) { 113 frag += ' o_out = floatBitsToUint(v_out);\n'; 114 } else { 115 vtx += ' v_in0 = a_in0;\n' + 116 ' v_in1 = a_in1;\n'; 117 frag += ' o_out = floatBitsToUint(res);\n'; 118 } 119 120 vtx += '}\n'; 121 frag += '}\n'; 122 123 return new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag)); 124 }; 125 126 /** 127 * @param {gluShaderUtil.DataType} type 128 * @param {gluShaderUtil.precision} precision 129 * @param {string} evalOp 130 * @param {boolean} isVertexCase 131 * @return {gluShaderProgram.ShaderProgram} 132 */ 133 es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram = function(type, precision, evalOp, isVertexCase) { 134 /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(type); 135 /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision); 136 /** @type {string} */ var vtx = ''; 137 /** @type {string} */ var frag = ''; 138 /** @type {string} */ var op = ''; 139 140 vtx += '#version 300 es\n' + 141 'in highp vec4 a_position;\n' + 142 'in ' + precName + ' ' + typeName + ' a_in0;\n' + 143 'in ' + precName + ' ' + typeName + ' a_in1;\n'; 144 frag += '#version 300 es\n' + 145 'layout(location = 0) out ' + precName + ' ' + typeName + ' o_out;\n'; 146 147 if (isVertexCase) { 148 vtx += 'flat out ' + precName + ' ' + typeName + ' v_out;\n'; 149 frag += 'flat in ' + precName + ' ' + typeName + ' v_out;\n'; 150 } else { 151 vtx += 'flat out ' + precName + ' ' + typeName + ' v_in0;\n' + 152 'flat out ' + precName + ' ' + typeName + ' v_in1;\n'; 153 frag += 'flat in ' + precName + ' ' + typeName + ' v_in0;\n' + 154 'flat in ' + precName + ' ' + typeName + ' v_in1;\n'; 155 } 156 157 vtx += '\nvoid main (void)\n{\n'+ 158 ' gl_Position = a_position;\n'; 159 frag += '\nvoid main (void)\n{\n'; 160 161 op += '\t' + precName + ' ' + typeName + ' in0 = ' + (isVertexCase ? 'a_' : 'v_') + 'in0;\n' + 162 '\t' + precName + ' ' + typeName + ' in1 = ' + (isVertexCase ? 'a_' : 'v_') + 'in1;\n'; 163 164 op += '\t' + (isVertexCase ? 'v_' : 'o_') + 'out = ' + evalOp + ';\n'; 165 166 vtx += isVertexCase ? op : ''; 167 frag += isVertexCase ? '' : op; 168 op = ''; 169 170 if (isVertexCase) { 171 frag += ' o_out = v_out;\n'; 172 } else { 173 vtx += ' v_in0 = a_in0;\n' + 174 ' v_in1 = a_in1;\n'; 175 } 176 177 vtx += '}\n'; 178 frag += '}\n'; 179 180 return new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag)); 181 }; 182 183 /** @typedef {function(number, number)} */ es3fShaderPrecisionTests.EvalFunc; 184 185 186 /** 187 * @constructor 188 * @extends {tcuTestCase.DeqpTest} 189 * @param {string} name 190 * @param {string} desc 191 * @param {string} op 192 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc 193 * @param {gluShaderUtil.precision} precision 194 * @param {Array<number>} rangeA 195 * @param {Array<number>} rangeB 196 * @param {boolean} isVertexCase 197 */ 198 es3fShaderPrecisionTests.ShaderFloatPrecisionCase = function(name, desc, op, evalFunc, precision, rangeA, rangeB, isVertexCase) { 199 tcuTestCase.DeqpTest.call(this, name, desc); 200 // Case parameters. 201 /** @type {string} */ this.m_op = op; 202 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc; 203 /** @type {gluShaderUtil.precision} */ this.m_precision = precision; 204 /** @type {Array<number>} */ this.m_rangeA = rangeA; 205 /** @type {Array<number>} */ this.m_rangeB = rangeB; 206 /** @type {boolean} */ this.m_isVertexCase = isVertexCase; 207 208 /** @type {number} */ this.m_numTestsPerIter = 32; 209 /** @type {number} */ this.m_numIters = 4; 210 /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name)); 211 212 // Iteration state. 213 /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null; 214 /** @type {?WebGLFramebuffer} */ this.m_framebuffer = null; 215 /** @type {?WebGLRenderbuffer} */ this.m_renderbuffer = null; 216 /** @type {number} */ this.m_iterNdx = 0; 217 /** @type {Array<boolean>} */ this.m_iterPass = []; 218 }; 219 220 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 221 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderFloatPrecisionCase; 222 223 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.init = function() { 224 assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true); 225 226 // Create program. 227 this.m_program = es3fShaderPrecisionTests.createFloatPrecisionEvalProgram(this.m_precision, this.m_op, this.m_isVertexCase); 228 229 if (!this.m_program.isOk()) 230 assertMsgOptions(false, 'Compile failed', false, true); 231 232 // Create framebuffer. 233 this.m_framebuffer = gl.createFramebuffer(); 234 this.m_renderbuffer = gl.createRenderbuffer(); 235 236 gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer); 237 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32UI, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT); 238 239 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 240 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer); 241 242 assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true); 243 244 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 245 246 this.m_iterNdx = 0; 247 }; 248 249 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.deinit = function() { 250 if(this.m_framebuffer) 251 gl.deleteFramebuffer(this.m_framebuffer); 252 if(this.m_renderbuffer) 253 gl.deleteRenderbuffer(this.m_renderbuffer); 254 this.m_program = null; 255 this.m_framebuffer = null; 256 this.m_renderbuffer = null; 257 }; 258 259 /** 260 * @param {number} in0 261 * @param {number} in1 262 * @param {number} reference 263 * @param {number} result 264 */ 265 266 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.compare = function(in0, in1, reference, result) { 267 // Comparison is done using 64-bit reference value to accurately evaluate rounding mode error. 268 // If 32-bit reference value is used, 2 bits of rounding error must be allowed. 269 270 // For mediump and lowp types the comparison currently allows 3 bits of rounding error: 271 // two bits from conversions and one from actual operation. 272 273 // \todo [2013-09-30 pyry] Make this more strict: determine if rounding can actually happen. 274 275 /** @type {number} */ var mantissaBits = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 23 : 10; 276 /** @type {number} */ var numPrecBits = 52 - mantissaBits; 277 278 /** @type {number} */ var in0Exp = tcuFloat.newFloat32(in0).exponent(); 279 /** @type {number} */ var in1Exp = tcuFloat.newFloat32(in1).exponent(); 280 /** @type {number} */ var resExp = tcuFloat.newFloat32(result).exponent(); 281 /** @type {number} */ var numLostBits = Math.max(in0Exp - resExp, in1Exp - resExp, 0); // Lost due to mantissa shift. 282 283 /** @type {number} */ var roundingUlpError = this.m_precision == gluShaderUtil.precision.PRECISION_HIGHP ? 1 : 3; 284 /** @type {number} */ var maskBits = numLostBits + numPrecBits; 285 286 bufferedLogToConsole("Assuming " + mantissaBits + " mantissa bits, " + numLostBits + " bits lost in operation, and " + roundingUlpError + " ULP rounding error.") 287 288 // These numbers should never be larger than 52 bits. An assertion in getBitRange verifies this. 289 /** @type {number} */ var accurateRefBits = tcuFloat.newFloat64(reference).getBitRange(maskBits, 64); 290 /** @type {number} */ var accurateResBits = tcuFloat.newFloat64(result).getBitRange(maskBits, 64); 291 /** @type {number} */ var ulpDiff = Math.abs(accurateRefBits - accurateResBits); 292 293 if (ulpDiff > roundingUlpError) { 294 bufferedLogToConsole("ERROR: comparison failed! ULP diff (ignoring lost/undefined bits) = " + ulpDiff ); 295 return false; 296 } 297 else 298 return true; 299 }; 300 301 /** 302 * @return {tcuTestCase.IterateResult} 303 */ 304 es3fShaderPrecisionTests.ShaderFloatPrecisionCase.prototype.iterate = function() { 305 var testPassed = true; 306 var testPassedMsg = 'Pass'; 307 308 // Constant data. 309 /** @type {Array<number>} */ var position =[ 310 -1.0, -1.0, 0.0, 1.0, 311 -1.0, 1.0, 0.0, 1.0, 312 1.0, -1.0, 0.0, 1.0, 313 1.0, 1.0, 0.0, 1.0 314 ]; 315 316 /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3]; 317 /** @type {number} */ var numVertices = 4; 318 /** @type {Array<number>} */ var in0Arr = [0.0, 0.0, 0.0, 0.0]; 319 /** @type {Array<number>} */ var in1Arr = [0.0, 0.0, 0.0, 0.0]; 320 321 /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = []; 322 323 // Image read from GL. 324 /** @type {goog.TypedArray} */ var pixels_uint = new Uint32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4); 325 326 // \todo [2012-05-03 pyry] Could be cached. 327 /** @type {WebGLProgram} */ var prog = this.m_program.getProgram(); 328 329 gl.useProgram(prog); 330 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 331 332 vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position); 333 334 335 // Compute values and reference. 336 for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) { 337 /** @type {number} */ var in0 = this.m_rnd.getFloat(this.m_rangeA[0], this.m_rangeA[1]); 338 /** @type {number} */ var in1 = this.m_rnd.getFloat(this.m_rangeB[0], this.m_rangeB[1]); 339 340 // These random numbers are used in the reference computation. But 341 // highp is only 32 bits, so these float64s must be rounded to 342 // float32 first for correctness. This is needed for highp_mul_* on 343 // one Linux/NVIDIA machine. 344 in0 = tcuFloat.newFloat32(in0).getValue(); 345 in1 = tcuFloat.newFloat32(in1).getValue(); 346 347 /** @type {number} */ var refD = this.m_evalFunc(in0, in1); 348 349 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": "+ 350 "in0 = " + in0 + " / " + tcuFloat.newFloat32(in0).bits() + 351 ", in1 = " + in1 + " / " + tcuFloat.newFloat32(in1).bits() + 352 " reference = " + refD + " / " + tcuFloat.newFloat32(refD).bits()); 353 354 in0Arr = [in0, in0, in0, in0]; 355 in1Arr = [in1, in1, in1, in1]; 356 vertexArrays[1] = gluDrawUtil.newFloatVertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr); 357 vertexArrays[2] = gluDrawUtil.newFloatVertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr); 358 359 gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices)); 360 361 gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, 362 es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT, gl.RGBA_INTEGER, gl.UNSIGNED_INT, pixels_uint); 363 364 var pixels = new Float32Array(pixels_uint.buffer); 365 bufferedLogToConsole(" result = " + pixels[0] + " / " + tcuFloat.newFloat32(pixels[0]).bits()); 366 367 // Verify results 368 /** @type {boolean} */ var firstPixelOk = this.compare(in0, in1, refD, pixels[0]); 369 370 if (firstPixelOk) { 371 // Check that rest of pixels match to first one. 372 /** @type {number} */ var firstPixelBits = tcuFloat.newFloat32(pixels[0]).bits(); 373 /** @type {boolean} */ var allPixelsOk = true; 374 375 for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) { 376 for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) { 377 /** @type {number} */ var pixelBits = tcuFloat.newFloat32(pixels[(y * es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4]).bits(); 378 379 if (pixelBits != firstPixelBits) { 380 bufferedLogToConsole("ERROR: Inconsistent results, got " + pixelBits + " at (" + x + ", " + y + ")") 381 allPixelsOk = false; 382 } 383 } 384 385 if (!allPixelsOk) 386 break; 387 } 388 389 if (!allPixelsOk){ 390 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + "Inconsistent values in framebuffer"); 391 testPassed = false; 392 testPassedMsg = 'Inconsistent values in framebuffer'; 393 } 394 } 395 else{ 396 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + "Result comparison failed"); 397 testPassed = false; 398 testPassedMsg = 'Result comparison failed' 399 } 400 } 401 402 // [dag] Aggregating test results to make the test less verbose. 403 this.m_iterPass[this.m_iterNdx] = testPassed; 404 405 // [dag] Show test results after the last iteration is done. 406 if (this.m_iterPass.length === this.m_numIters) { 407 if (!deMath.boolAll(this.m_iterPass)) 408 testFailedOptions(testPassedMsg, false); 409 else 410 testPassedOptions(testPassedMsg, true); 411 } 412 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 413 414 this.m_iterNdx += 1; 415 return (this.m_iterNdx < this.m_numIters) ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP; 416 }; 417 418 /** 419 * @constructor 420 * @extends {tcuTestCase.DeqpTest} 421 * @param {string} name 422 * @param {string} desc 423 * @param {string} op 424 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc 425 * @param {gluShaderUtil.precision} precision 426 * @param {number} bits 427 * @param {Array<number>} rangeA 428 * @param {Array<number>} rangeB 429 * @param {boolean} isVertexCase 430 */ 431 es3fShaderPrecisionTests.ShaderIntPrecisionCase = function(name, desc, op, evalFunc, precision, bits, rangeA, rangeB, isVertexCase) { 432 tcuTestCase.DeqpTest.call(this, name, desc); 433 // Case parameters. 434 /** @type {string} */ this.m_op = op; 435 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc; 436 /** @type {gluShaderUtil.precision} */ this.m_precision = precision; 437 /** @type {number} */ this.m_bits = bits; 438 /** @type {Array<number>} */ this.m_rangeA = rangeA; 439 /** @type {Array<number>} */ this.m_rangeB = rangeB; 440 /** @type {boolean} */ this.m_isVertexCase = isVertexCase; 441 442 /** @type {number} */ this.m_numTestsPerIter = 32; 443 /** @type {number} */ this.m_numIters = 4; 444 /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name)); 445 446 // Iteration state. 447 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null; 448 /** @type {WebGLFramebuffer} */ this.m_framebuffer = null; 449 /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null; 450 /** @type {number} */ this.m_iterNdx = 0; 451 }; 452 453 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 454 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderIntPrecisionCase; 455 456 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.init = function() { 457 assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true); 458 // Create program. 459 this.m_program = es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram(gluShaderUtil.DataType.INT, this.m_precision, this.m_op, this.m_isVertexCase); 460 461 if (!this.m_program.isOk()) 462 assertMsgOptions(false, 'Compile failed', false, true); 463 464 // Create framebuffer. 465 this.m_framebuffer = gl.createFramebuffer(); 466 this.m_renderbuffer = gl.createRenderbuffer(); 467 468 gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer); 469 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32I, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT); 470 471 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 472 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer); 473 474 assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true); 475 476 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 477 478 this.m_iterNdx = 0; 479 480 bufferedLogToConsole("Number of accurate bits assumed = " + this.m_bits); 481 }; 482 483 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.deinit = function() { 484 if(this.m_framebuffer) 485 gl.deleteFramebuffer(this.m_framebuffer); 486 if(this.m_renderbuffer) 487 gl.deleteRenderbuffer(this.m_renderbuffer); 488 this.m_program = null; 489 this.m_framebuffer = null; 490 this.m_renderbuffer = null; 491 }; 492 493 /** 494 * @param {number} value 495 * @param {number} bits 496 * @return {number} 497 */ 498 499 es3fShaderPrecisionTests.extendTo32Bit = function(value, bits) { 500 return (value & ((1 << (bits - 1)) - 1)) | ((value & (1 << (bits - 1))) << (32 - bits)) >> (32 - bits); 501 }; 502 503 /** 504 * @return {tcuTestCase.IterateResult} 505 */ 506 es3fShaderPrecisionTests.ShaderIntPrecisionCase.prototype.iterate = function() { 507 var testPassed = true; 508 var testPassedMsg = 'Pass'; 509 // Constant data. 510 /** @type {Array<number>} */ var position = [ 511 -1.0, -1.0, 0.0, 1.0, 512 -1.0, 1.0, 0.0, 1.0, 513 1.0, -1.0, 0.0, 1.0, 514 1.0, 1.0, 0.0, 1.0 515 ] 516 /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3]; 517 518 /** @type {number} */ var numVertices = 4; 519 /** @type {Array<number>} */ var in0Arr = [0, 0, 0, 0]; 520 /** @type {Array<number>} */ var in1Arr = [0, 0, 0, 0]; 521 522 /** @type {number} */ var mask = this.m_bits === 32 ? 0xffffffff : ((1 << this.m_bits) - 1); 523 /** @type {goog.TypedArray} */ var pixels = new Int32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4); 524 /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = []; 525 526 /** @type {WebGLProgram} */ var prog = this.m_program.getProgram(); 527 528 // \todo [2012-05-03 pyry] A bit hacky. getInt() should work fine with ranges like this. 529 /** @type {boolean} */ var isMaxRangeA = this.m_rangeA[0] === 0x80000000 && this.m_rangeA[1] === 0x7fffffff; 530 /** @type {boolean} */ var isMaxRangeB = this.m_rangeB[0] === 0x80000000 && this.m_rangeB[1] === 0x7fffffff; 531 532 gl.useProgram(prog); 533 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 534 535 vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position); 536 537 // Compute values and reference. 538 for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) { 539 /** @type {number} */ var in0 = this.m_rnd.getInt(this.m_rangeA[0], this.m_rangeA[1]); //es3fShaderPrecisionTests.extendTo32Bit(((isMaxRangeA ? Math.abs(this.m_rnd.getInt()) : this.m_rnd.getInt(this.m_rangeA[0], this.m_rangeA[1])) & mask), this.m_bits); 540 /** @type {number} */ var in1 = this.m_rnd.getInt(this.m_rangeB[0], this.m_rangeB[1]); //es3fShaderPrecisionTests.extendTo32Bit(((isMaxRangeB ? Math.abs(this.m_rnd.getInt()) : this.m_rnd.getInt(this.m_rangeB[0], this.m_rangeB[1])) & mask), this.m_bits); 541 /** @type {number} */ var refMasked = this.m_evalFunc(in0, in1) & mask; 542 /** @type {number} */ var refOut = es3fShaderPrecisionTests.extendTo32Bit(refMasked, this.m_bits); 543 544 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": " + 545 "in0 = " + in0 + ", in1 = " + in1 + ", ref out = " + refOut + " / " + refMasked); 546 547 in0Arr = [in0, in0, in0, in0]; 548 in1Arr = [in1, in1, in1, in1]; 549 550 vertexArrays[1] = gluDrawUtil.newInt32VertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr); 551 vertexArrays[2] = gluDrawUtil.newInt32VertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr); 552 553 gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices)); 554 555 gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, 556 es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT, 557 gl.RGBA_INTEGER, gl.INT, pixels); 558 559 // Compare pixels. 560 for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) { 561 for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) { 562 /** @type {number} */ var cmpOut = pixels[(y * es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4]; 563 /** @type {number} */ var cmpMasked = cmpOut & mask; 564 565 if (cmpMasked != refMasked) { 566 bufferedLogToConsole("Comparison failed (at " + x + ", " + y + "): " + 567 + "got " + cmpOut + " / " + cmpOut); 568 testPassed = false; 569 testPassedMsg = 'Comparison failed'; 570 } 571 } 572 } 573 } 574 575 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 576 577 this.m_iterNdx += 1; 578 if (!testPassed) { 579 testFailedOptions(testPassedMsg, false); 580 return tcuTestCase.IterateResult.STOP; 581 } else if (testPassed && this.m_iterNdx < this.m_numIters) { 582 return tcuTestCase.IterateResult.CONTINUE; 583 } else { 584 testPassedOptions(testPassedMsg, true); 585 return tcuTestCase.IterateResult.STOP; 586 } 587 }; 588 589 /** 590 * @constructor 591 * @extends {tcuTestCase.DeqpTest} 592 * @param {string} name 593 * @param {string} desc 594 * @param {string} op 595 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc 596 * @param {gluShaderUtil.precision} precision 597 * @param {number} bits 598 * @param {Array<number>} rangeA 599 * @param {Array<number>} rangeB 600 * @param {boolean} isVertexCase 601 */ 602 es3fShaderPrecisionTests.ShaderUintPrecisionCase = function(name, desc, op, evalFunc, precision, bits, rangeA, rangeB, isVertexCase) { 603 tcuTestCase.DeqpTest.call(this, name, desc); 604 // Case parameters. 605 /** @type {string} */ this.m_op = op; 606 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.m_evalFunc = evalFunc; 607 /** @type {gluShaderUtil.precision} */ this.m_precision = precision; 608 /** @type {number} */ this.m_bits = bits; 609 /** @type {Array<number>} */ this.m_rangeA = rangeA; 610 /** @type {Array<number>} */ this.m_rangeB = rangeB; 611 /** @type {boolean} */ this.m_isVertexCase = isVertexCase; 612 613 /** @type {number} */ this.m_numTestsPerIter = 32; 614 /** @type {number} */ this.m_numIters = 4; 615 /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name)); 616 617 // Iteration state. 618 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null; 619 /** @type {WebGLFramebuffer} */ this.m_framebuffer = null; 620 /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null; 621 /** @type {number} */ this.m_iterNdx = 0; 622 }; 623 624 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 625 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.constructor = es3fShaderPrecisionTests.ShaderUintPrecisionCase; 626 627 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.init = function() { 628 assertMsgOptions(!this.m_program && !this.m_framebuffer && !this.m_renderbuffer, 'Program/Framebuffer/Renderbuffer should be null at this point.', false, true); 629 // Create program. 630 this.m_program = es3fShaderPrecisionTests.createIntUintPrecisionEvalProgram(gluShaderUtil.DataType.UINT, this.m_precision, this.m_op, this.m_isVertexCase); 631 632 if (!this.m_program.isOk()) 633 assertMsgOptions(false, 'Compile failed', false, true); 634 635 // Create framebuffer. 636 this.m_framebuffer = gl.createFramebuffer(); 637 this.m_renderbuffer = gl.createRenderbuffer(); 638 639 gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer); 640 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32UI, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT); 641 642 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 643 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_renderbuffer); 644 645 assertMsgOptions(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, 'Framebuffer is incomplete', false, true); 646 647 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 648 649 this.m_iterNdx = 0; 650 651 bufferedLogToConsole("Number of accurate bits assumed = " + this.m_bits); 652 }; 653 654 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.deinit = function() { 655 if(this.m_framebuffer) 656 gl.deleteFramebuffer(this.m_framebuffer); 657 if(this.m_renderbuffer) 658 gl.deleteRenderbuffer(this.m_renderbuffer); 659 this.m_program = null; 660 this.m_framebuffer = null; 661 this.m_renderbuffer = null; 662 }; 663 664 /** 665 * @return {tcuTestCase.IterateResult} 666 */ 667 es3fShaderPrecisionTests.ShaderUintPrecisionCase.prototype.iterate = function() { 668 var testPassed = true; 669 var testPassedMsg = 'Pass'; 670 671 // Constant data. 672 /** @type {Array<number>} */ var position = [ 673 -1.0, -1.0, 0.0, 1.0, 674 -1.0, 1.0, 0.0, 1.0, 675 1.0, -1.0, 0.0, 1.0, 676 1.0, 1.0, 0.0, 1.0 677 ]; 678 /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3]; 679 680 /** @type {number} */ var numVertices = 4; 681 /** @type {Array<number>} */ var in0Arr = [0, 0, 0, 0]; 682 /** @type {Array<number>} */ var in1Arr = [0, 0, 0, 0]; 683 684 /** @type {number} */ var mask = this.m_bits === 32 ? 0xffffffff : ((1 << this.m_bits) - 1); 685 /** @type {goog.TypedArray} */ var pixels = new Uint32Array(es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH * es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT * 4); 686 /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = []; 687 688 /** @type {WebGLProgram} */ var prog = this.m_program.getProgram(); 689 690 // \todo [2012-05-03 pyry] A bit hacky. 691 /** @type {boolean} */ var isMaxRangeA = this.m_rangeA[0] === 0 && this.m_rangeA[1] === 0xffffffff; 692 /** @type {boolean} */ var isMaxRangeB = this.m_rangeB[0] === 0 && this.m_rangeB[1] === 0xffffffff; 693 694 gl.useProgram(prog); 695 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 696 697 vertexArrays[0] = gluDrawUtil.newFloatVertexArrayBinding("a_position", 4, numVertices, 0, position); 698 699 // Compute values and reference. 700 for (var testNdx = 0; testNdx < this.m_numTestsPerIter; testNdx++) { 701 /** @type {number} */ var in0 = (isMaxRangeA ? Math.abs(this.m_rnd.getInt()) : (this.m_rangeA[0] + Math.abs(this.m_rnd.getInt()) % (this.m_rangeA[1] - this.m_rangeA[0] + 1))) & mask; 702 /** @type {number} */ var in1 = (isMaxRangeB ? Math.abs(this.m_rnd.getInt()) : (this.m_rangeB[0] + Math.abs(this.m_rnd.getInt()) % (this.m_rangeB[1] - this.m_rangeB[0] + 1))) & mask; 703 /** @type {number} */ var refOut = this.m_evalFunc(in0, in1) & mask; 704 705 bufferedLogToConsole("iter " + this.m_iterNdx + ", test " + testNdx + ": " + 706 + "in0 = " + in0 + ", in1 = " + in1 + ", ref out = " + refOut) 707 708 in0Arr = [in0, in0, in0, in0]; 709 in1Arr = [in1, in1, in1, in1]; 710 vertexArrays[1] = gluDrawUtil.newUint32VertexArrayBinding("a_in0", 1, numVertices, 0, in0Arr); 711 vertexArrays[2] = gluDrawUtil.newUint32VertexArrayBinding("a_in1", 1, numVertices, 0, in1Arr); 712 713 gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices)); 714 715 gl.readPixels(0, 0, es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH, 716 es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT, gl.RGBA_INTEGER, gl.UNSIGNED_INT, pixels); 717 718 // Compare pixels. 719 for (var y = 0; y < es3fShaderPrecisionTests.FRAMEBUFFER_HEIGHT; y++) { 720 for (var x = 0; x < es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH; x++) { 721 /** @type {number} */ var cmpOut = pixels[(y*es3fShaderPrecisionTests.FRAMEBUFFER_WIDTH + x) * 4]; 722 /** @type {number} */ var cmpMasked = cmpOut & mask; 723 724 if (cmpMasked != refOut) { 725 bufferedLogToConsole("Comparison failed (at " + x + ", " + y + "): " + "got " + cmpOut) 726 testPassed = false; 727 testPassedMsg = 'Comparison failed'; 728 } 729 } 730 } 731 } 732 733 734 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 735 736 this.m_iterNdx += 1; 737 if (!testPassed) { 738 testFailedOptions(testPassedMsg, false); 739 return tcuTestCase.IterateResult.STOP; 740 } else if (testPassed && this.m_iterNdx < this.m_numIters) { 741 return tcuTestCase.IterateResult.CONTINUE; 742 } else { 743 testPassedOptions(testPassedMsg, true); 744 return tcuTestCase.IterateResult.STOP; 745 } 746 }; 747 748 /** 749 * @constructor 750 * @extends {tcuTestCase.DeqpTest} 751 */ 752 es3fShaderPrecisionTests.ShaderPrecisionTests = function() { 753 tcuTestCase.DeqpTest.call(this, 'precision', 'Shader precision requirements validation tests'); 754 }; 755 756 es3fShaderPrecisionTests.ShaderPrecisionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 757 es3fShaderPrecisionTests.ShaderPrecisionTests.prototype.constructor = es3fShaderPrecisionTests.ShaderPrecisionTests; 758 759 es3fShaderPrecisionTests.ShaderPrecisionTests.prototype.init = function() { 760 var testGroup = tcuTestCase.runner.testCases; 761 // Exp = Emax-2, Mantissa = 0 762 // /** @type {number} */ var minF32 = tcuFloat.newFloat32((1 << 31) | (0xfd << 23) | 0x0).getValue(); 763 // /** @type {number} */ var maxF32 = tcuFloat.newFloat32((0 << 31) | (0xfd << 23) | 0x0).getValue(); 764 // [dag] Workaround for float32 numbers 765 /** @type {number} */ var minF32 = new Float32Array(new Uint32Array([1<<31|0xfd<<23|0x0]).buffer)[0]; 766 /** @type {number} */ var maxF32 = new Float32Array(new Uint32Array([0<<31|0xfd<<23|0x0]).buffer)[0]; 767 768 // /** @type {number} */ var minF16 = tcuFloat.newFloat16(((1 << 15) | (0x1d << 10) | 0x0)).getValue(); 769 // /** @type {number} */ var maxF16 = tcuFloat.newFloat16(((0 << 15) | (0x1d << 10) | 0x0)).getValue(); 770 /** @type {number} */ var minF16 = -16384; //-1 << 14; // 1 << 15 | 0x1d | 0x0 == 0b1111010000000000; -1 * (2**(29-15)) * 1 771 /** @type {number} */ var maxF16 = 16384; //1 << 14; // 0 << 15 | 0x1d | 0x0 == 0b0111010000000000; +1 * (2**(29-15)) * 1 772 773 /** @type {Array<number>} */ var fullRange32F = [minF32, maxF32]; 774 /** @type {Array<number>} */ var fullRange16F = [minF16, maxF16]; 775 /** @type {Array<number>} */ var fullRange32I = [-2147483648, 2147483647]; // [0x80000000|0, 0x7fffffff|0]; // |0 to force the number as a 32-bit integer 776 /** @type {Array<number>} */ var fullRange16I = [minF16, maxF16 - 1]; //[-(1 << 15), (1 << 15) - 1]; // Added the negative sign to index 0 777 /** @type {Array<number>} */ var fullRange8I = [-128, 127]; //[-(1 << 7), (1 << 7) - 1]; // Added the negative sign to index 0 778 /** @type {Array<number>} */ var fullRange32U = [0, 0xffffffff]; 779 /** @type {Array<number>} */ var fullRange16U = [0, 0xffff]; 780 /** @type {Array<number>} */ var fullRange8U = [0, 0xff]; 781 782 // \note Right now it is not programmatically verified that the results shouldn't end up being inf/nan but 783 // actual values used are ok. 784 785 /** 786 * @constructor 787 * @struct 788 * @param {string} name 789 * @param {string} op 790 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc 791 * @param {gluShaderUtil.precision} precision 792 * @param {Array<number>} rangeA 793 * @param {Array<number>} rangeB 794 */ 795 var FloatCase = function(name, op, evalFunc, precision, rangeA, rangeB) { 796 /** @type {string} */ this.name = name; 797 /** @type {string} */ this.op = op; 798 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc; 799 /** @type {gluShaderUtil.precision} */ this.precision = precision; 800 /** @type {Array<number>} */ this.rangeA = rangeA; 801 /** @type {Array<number>} */ this.rangeB = rangeB; 802 }; 803 804 /** @type {Array<FloatCase>} */ var floatCases = [ 805 new FloatCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, fullRange32F, fullRange32F), 806 new FloatCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, fullRange32F, fullRange32F), 807 new FloatCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_HIGHP, [-1e5, 1e5], [-1e5, 1e5]), 808 new FloatCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, [-1e5, 1e5], [-1e5, 1e5]), 809 new FloatCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, fullRange16F, fullRange16F), 810 new FloatCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, fullRange16F, fullRange16F), 811 new FloatCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, [-1e2, 1e2], [-1e2, 1e2]), 812 new FloatCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, [-1e2, 1e2], [-1e2, 1e2]) 813 ]; 814 815 /** 816 * @constructor 817 * @struct 818 * @param {string} name 819 * @param {string} op 820 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc 821 * @param {gluShaderUtil.precision} precision 822 * @param {number} bits 823 * @param {Array<number>} rangeA 824 * @param {Array<number>} rangeB 825 */ 826 var IntCase = function(name, op, evalFunc, precision, bits, rangeA, rangeB) { 827 /** @type {string} */ this.name = name; 828 /** @type {string} */ this.op = op; 829 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc; 830 /** @type {gluShaderUtil.precision} */ this.precision = precision; 831 /** @type {number} */ this.bits = bits; 832 /** @type {Array<number>} */ this.rangeA = rangeA; 833 /** @type {Array<number>} */ this.rangeB = rangeB; 834 }; 835 836 /** @type {Array<IntCase>} */ var intCases = [ 837 new IntCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I), 838 new IntCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I), 839 new IntCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul32, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, fullRange32I), 840 new IntCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32I, [-10000, -1]), 841 new IntCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I), 842 new IntCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I), 843 new IntCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, fullRange16I), 844 new IntCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16I, [1, 1000]), 845 new IntCase('lowp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I), 846 new IntCase('lowp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I), 847 new IntCase('lowp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, fullRange8I), 848 new IntCase('lowp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8I, [-50, -1]) 849 ]; 850 851 /** 852 * @constructor 853 * @struct 854 * @param {string} name 855 * @param {string} op 856 * @param {es3fShaderPrecisionTests.EvalFunc} evalFunc 857 * @param {gluShaderUtil.precision} precision 858 * @param {number} bits 859 * @param {Array<number>} rangeA 860 * @param {Array<number>} rangeB 861 */ 862 var UintCase = function(name, op, evalFunc, precision, bits, rangeA, rangeB) { 863 /** @type {string} */ this.name = name; 864 /** @type {string} */ this.op = op; 865 /** @type {es3fShaderPrecisionTests.EvalFunc} */ this.evalFunc = evalFunc; 866 /** @type {gluShaderUtil.precision} */ this.precision = precision; 867 /** @type {number} */ this.bits = bits; 868 /** @type {Array<number>} */ this.rangeA = rangeA; 869 /** @type {Array<number>} */ this.rangeB = rangeB; 870 }; 871 872 /** @type {Array<UintCase>} */ var uintCases = [ 873 new UintCase('highp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U), 874 new UintCase('highp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U), 875 new UintCase('highp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul32, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, fullRange32U), 876 new UintCase('highp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_HIGHP, 32, fullRange32U, [1, 10000]), 877 new UintCase('mediump_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U), 878 new UintCase('mediump_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U), 879 new UintCase('mediump_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, fullRange16U), 880 new UintCase('mediump_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_MEDIUMP, 16, fullRange16U, [1, 1000]), 881 new UintCase('lowp_add', 'in0 + in1', es3fShaderPrecisionTests.add, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U), 882 new UintCase('lowp_sub', 'in0 - in1', es3fShaderPrecisionTests.sub, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U), 883 new UintCase('lowp_mul', 'in0 * in1', es3fShaderPrecisionTests.mul, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, fullRange8U), 884 new UintCase('lowp_div', 'in0 / in1', es3fShaderPrecisionTests.div, gluShaderUtil.precision.PRECISION_LOWP, 8, fullRange8U, [1, 50]) 885 ]; 886 887 /** @type {tcuTestCase.DeqpTest} */ var floatGroup = tcuTestCase.newTest('float', 'Floating-point precision tests'); 888 testGroup.addChild(floatGroup); 889 for (var ndx = 0; ndx < floatCases.length; ndx++) { 890 floatGroup.addChild(new es3fShaderPrecisionTests.ShaderFloatPrecisionCase( 891 floatCases[ndx].name + '_vertex', '', floatCases[ndx].op, floatCases[ndx].evalFunc, 892 floatCases[ndx].precision, floatCases[ndx].rangeA, floatCases[ndx].rangeB, true)); 893 floatGroup.addChild(new es3fShaderPrecisionTests.ShaderFloatPrecisionCase( 894 floatCases[ndx].name + '_fragment', '', floatCases[ndx].op, floatCases[ndx].evalFunc, 895 floatCases[ndx].precision, floatCases[ndx].rangeA, floatCases[ndx].rangeB, false)); 896 } 897 898 /** @type {tcuTestCase.DeqpTest} */ var intGroup = tcuTestCase.newTest('int', 'Integer precision tests'); 899 testGroup.addChild(intGroup); 900 for (var ndx = 0; ndx < intCases.length; ndx++) { 901 intGroup.addChild(new es3fShaderPrecisionTests.ShaderIntPrecisionCase( 902 intCases[ndx].name + '_vertex', '', intCases[ndx].op, intCases[ndx].evalFunc, 903 intCases[ndx].precision, intCases[ndx].bits, intCases[ndx].rangeA, intCases[ndx].rangeB, true)); 904 intGroup.addChild(new es3fShaderPrecisionTests.ShaderIntPrecisionCase( 905 intCases[ndx].name + '_fragment', '', intCases[ndx].op, intCases[ndx].evalFunc, 906 intCases[ndx].precision, intCases[ndx].bits, intCases[ndx].rangeA, intCases[ndx].rangeB, false)); 907 } 908 909 /** @type {tcuTestCase.DeqpTest} */ var uintGroup = tcuTestCase.newTest('uint', 'Unsigned integer precision tests'); 910 testGroup.addChild(uintGroup); 911 for (var ndx = 0; ndx < uintCases.length; ndx++) { 912 uintGroup.addChild(new es3fShaderPrecisionTests.ShaderUintPrecisionCase( 913 uintCases[ndx].name + '_vertex', '', uintCases[ndx].op, uintCases[ndx].evalFunc, 914 uintCases[ndx].precision, uintCases[ndx].bits, uintCases[ndx].rangeA, uintCases[ndx].rangeB, true)); 915 uintGroup.addChild(new es3fShaderPrecisionTests.ShaderUintPrecisionCase( 916 uintCases[ndx].name + '_fragment', '', uintCases[ndx].op, uintCases[ndx].evalFunc, 917 uintCases[ndx].precision, uintCases[ndx].bits, uintCases[ndx].rangeA, uintCases[ndx].rangeB, false)); 918 } 919 }; 920 921 /** 922 * Run test 923 * @param {WebGL2RenderingContext} context 924 */ 925 es3fShaderPrecisionTests.run = function(context, range) { 926 gl = context; 927 //Set up Test Root parameters 928 var state = tcuTestCase.runner; 929 state.setRoot(new es3fShaderPrecisionTests.ShaderPrecisionTests()); 930 931 //Set up name and description of this test series. 932 setCurrentTestName(state.testCases.fullName()); 933 description(state.testCases.getDescription()); 934 935 try { 936 if (range) 937 state.setRange(range); 938 //Run test cases 939 tcuTestCase.runTestCases(); 940 } 941 catch (err) { 942 testFailedOptions('Failed to es3fShaderPrecisionTests.run tests', false); 943 tcuTestCase.runner.terminate(); 944 } 945 }; 946 947 });