es3fShaderDerivateTests.js (89234B)
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.es3fShaderDerivateTests'); 23 goog.require('framework.delibs.debase.deMath'); 24 goog.require('framework.delibs.debase.deRandom'); 25 goog.require('framework.delibs.debase.deString'); 26 goog.require('framework.opengl.gluDrawUtil'); 27 goog.require('framework.opengl.gluPixelTransfer'); 28 goog.require('framework.opengl.gluShaderProgram'); 29 goog.require('framework.opengl.gluShaderUtil'); 30 goog.require('framework.opengl.gluTexture'); 31 goog.require('framework.opengl.gluTextureUtil'); 32 goog.require('framework.common.tcuInterval'); 33 goog.require('framework.common.tcuFloat'); 34 goog.require('framework.common.tcuLogImage'); 35 goog.require('framework.common.tcuMatrix'); 36 goog.require('framework.common.tcuPixelFormat'); 37 goog.require('framework.common.tcuRGBA'); 38 goog.require('framework.common.tcuStringTemplate'); 39 goog.require('framework.common.tcuSurface'); 40 goog.require('framework.common.tcuTexture'); 41 goog.require('framework.common.tcuTextureUtil'); 42 goog.require('framework.common.tcuTestCase'); 43 goog.require('modules.shared.glsShaderRenderCase'); 44 45 goog.scope(function() { 46 var es3fShaderDerivateTests = functional.gles3.es3fShaderDerivateTests; 47 var deMath = framework.delibs.debase.deMath; 48 var deRandom = framework.delibs.debase.deRandom; 49 var deString = framework.delibs.debase.deString; 50 var gluDrawUtil = framework.opengl.gluDrawUtil; 51 var gluPixelTransfer = framework.opengl.gluPixelTransfer; 52 var gluShaderProgram = framework.opengl.gluShaderProgram; 53 var gluShaderUtil = framework.opengl.gluShaderUtil; 54 var gluTexture = framework.opengl.gluTexture; 55 var gluTextureUtil = framework.opengl.gluTextureUtil; 56 var tcuInterval = framework.common.tcuInterval; 57 var tcuFloat = framework.common.tcuFloat; 58 var tcuLogImage = framework.common.tcuLogImage; 59 var tcuMatrix = framework.common.tcuMatrix; 60 var tcuPixelFormat = framework.common.tcuPixelFormat; 61 var tcuRGBA = framework.common.tcuRGBA; 62 var tcuStringTemplate = framework.common.tcuStringTemplate; 63 var tcuSurface = framework.common.tcuSurface; 64 var tcuTexture = framework.common.tcuTexture; 65 var tcuTextureUtil = framework.common.tcuTextureUtil; 66 var tcuTestCase = framework.common.tcuTestCase; 67 var glsShaderRenderCase = modules.shared.glsShaderRenderCase; 68 69 /** @const {number} */ es3fShaderDerivateTests.VIEWPORT_WIDTH = 167; 70 /** @const {number} */ es3fShaderDerivateTests.VIEWPORT_HEIGHT = 103; 71 /** @const {number} */ es3fShaderDerivateTests.FBO_WIDTH = 99; 72 /** @const {number} */ es3fShaderDerivateTests.FBO_HEIGHT = 133; 73 /** @const {number} */ es3fShaderDerivateTests.MAX_FAILED_MESSAGES = 10; 74 /** @const {number} */ es3fShaderDerivateTests.INTERPOLATION_LOST_BITS = 3; // number mantissa of bits allowed to be lost in varying interpolation 75 /** 76 * @enum {number} 77 */ 78 es3fShaderDerivateTests.DerivateFunc = { 79 DFDX: 0, 80 DFDY: 1, 81 FWIDTH: 2 82 }; 83 84 /** 85 * @enum {number} 86 */ 87 es3fShaderDerivateTests.SurfaceType = { 88 DEFAULT_FRAMEBUFFER: 0, 89 UNORM_FBO: 1, 90 FLOAT_FBO: 2 // \note Uses RGBA32UI fbo actually, since FP rendertargets are not in core spec. 91 }; 92 93 /** 94 * @enum {number} 95 */ 96 es3fShaderDerivateTests.VerificationLogging = { 97 LOG_ALL: 0, 98 LOG_NOTHING: 1 99 }; 100 101 /** 102 * @param {es3fShaderDerivateTests.DerivateFunc} func 103 * @return {string} 104 */ 105 es3fShaderDerivateTests.getDerivateFuncName = function(func) { 106 switch (func) { 107 case es3fShaderDerivateTests.DerivateFunc.DFDX: return 'dFdx'; 108 case es3fShaderDerivateTests.DerivateFunc.DFDY: return 'dFdy'; 109 case es3fShaderDerivateTests.DerivateFunc.FWIDTH: return 'fwidth'; 110 default: throw new Error('Derivate Func not supported.'); 111 } 112 }; 113 114 /** 115 * @param {es3fShaderDerivateTests.DerivateFunc} func 116 * @return {string} 117 */ 118 es3fShaderDerivateTests.getDerivateFuncCaseName = function(func) { 119 switch (func) { 120 case es3fShaderDerivateTests.DerivateFunc.DFDX: return 'dfdx'; 121 case es3fShaderDerivateTests.DerivateFunc.DFDY: return 'dfdy'; 122 case es3fShaderDerivateTests.DerivateFunc.FWIDTH: return 'fwidth'; 123 default: throw new Error('Derivate Func not supported.'); 124 } 125 }; 126 127 /** 128 * @param {?gluShaderUtil.DataType} type 129 * @return {Array<boolean>} 130 */ 131 es3fShaderDerivateTests.getDerivateMask = function(type) { 132 switch (type) { 133 case gluShaderUtil.DataType.FLOAT: return [true, false, false, false]; 134 case gluShaderUtil.DataType.FLOAT_VEC2: return [true, true, false, false]; 135 case gluShaderUtil.DataType.FLOAT_VEC3: return [true, true, true, false]; 136 case gluShaderUtil.DataType.FLOAT_VEC4: return [true, true, true, true]; 137 default: throw new Error('Data Type not supported.'); 138 } 139 }; 140 141 /** 142 * @param {tcuTexture.ConstPixelBufferAccess} surface 143 * @param {Array<number>} derivScale 144 * @param {Array<number>} derivBias 145 * @param {number} x 146 * @param {number} y 147 * @return {Array<number>} 148 */ 149 es3fShaderDerivateTests.readDerivate = function(surface, derivScale, derivBias, x, y) { 150 return deMath.divide(deMath.subtract(surface.getPixel(x, y), derivBias), derivScale); 151 }; 152 153 /** 154 * @param {Array<number>} v 155 * @return {Array<number>} 156 */ 157 es3fShaderDerivateTests.getCompExpBits = function(v) { 158 return [tcuFloat.newFloat32(v[0]).exponentBits(), 159 tcuFloat.newFloat32(v[1]).exponentBits(), 160 tcuFloat.newFloat32(v[2]).exponentBits(), 161 tcuFloat.newFloat32(v[3]).exponentBits()]; 162 }; 163 164 /** 165 * @param {number} value 166 * @param {number} numAccurateBits 167 * @return {number} 168 */ 169 es3fShaderDerivateTests.computeFloatingPointError = function(value, numAccurateBits) { 170 /** @type {number} */ var numGarbageBits = 23 - numAccurateBits; 171 /** @type {number} */ var mask = (1 << numGarbageBits) - 1 ; 172 /** @type {number} */ var exp = tcuFloat.newFloat32(value).exponent(); 173 174 return (new tcuFloat.deFloat()).construct(1, exp, (1 << 23) | mask).getValue() - (new tcuFloat.deFloat()).construct(1, exp, 1 << 23).getValue(); 175 }; 176 177 /** 178 * @param {?gluShaderUtil.precision} precision 179 * @return {number} 180 */ 181 es3fShaderDerivateTests.getNumMantissaBits = function(precision) { 182 switch (precision) { 183 case gluShaderUtil.precision.PRECISION_HIGHP: return 23; 184 case gluShaderUtil.precision.PRECISION_MEDIUMP: return 10; 185 case gluShaderUtil.precision.PRECISION_LOWP: return 6; 186 default: 187 throw new Error('Precision not supported: ' + precision); 188 } 189 }; 190 191 /** 192 * @param {?gluShaderUtil.precision} precision 193 * @return {number} 194 */ 195 es3fShaderDerivateTests.getMinExponent = function(precision) { 196 switch (precision) { 197 case gluShaderUtil.precision.PRECISION_HIGHP: return -126; 198 case gluShaderUtil.precision.PRECISION_MEDIUMP: return -14; 199 case gluShaderUtil.precision.PRECISION_LOWP: return -8; 200 default: 201 throw new Error('Precision not supported: ' + precision); 202 } 203 }; 204 205 /** 206 * @param {number} exp 207 * @param {number} numMantissaBits 208 * @return {number} 209 */ 210 es3fShaderDerivateTests.getSingleULPForExponent = function(exp, numMantissaBits) { 211 if (numMantissaBits > 0) { 212 assertMsgOptions(numMantissaBits <= 23, 'numMantissaBits must be less or equal than 23.', false, true); 213 214 /** @type {number} */ var ulpBitNdx = 23 - numMantissaBits; 215 216 return (new tcuFloat.deFloat()).construct(1, exp, (1 << 23) | (1 << ulpBitNdx)).getValue() - (new tcuFloat.deFloat()).construct(1, exp, 1 << 23).getValue(); 217 } else { 218 assertMsgOptions(numMantissaBits === 0, 'numMantissaBits must equal to 0.', false, true); 219 return (new tcuFloat.deFloat()).construct(1, exp, (1 << 23)).getValue() 220 } 221 }; 222 223 /** 224 * @param {number} value 225 * @param {number} numMantissaBits 226 * @return {number} 227 */ 228 es3fShaderDerivateTests.getSingleULPForValue = function(value, numMantissaBits) { 229 /** @type {number} */ var exp = (new tcuFloat.deFloat().deFloatNumber(value)).exponent(); 230 return es3fShaderDerivateTests.getSingleULPForExponent(exp, numMantissaBits); 231 }; 232 233 /** 234 * @param {number} value 235 * @param {number} minExponent 236 * @param {number} numAccurateBits 237 * @return {number} 238 */ 239 es3fShaderDerivateTests.convertFloorFlushToZero = function(value, minExponent, numAccurateBits) { 240 if (value === 0.0) { 241 return 0.0; 242 } else { 243 /** @type {tcuFloat.deFloat} */ var inputFloat = new tcuFloat.deFloat().deFloatNumber(value); 244 /** @type {number} */ var numTruncatedBits = 23 - numAccurateBits; 245 /** @type {number} */ var truncMask = (1 << numTruncatedBits) - 1; 246 247 if (value > 0.0) { 248 if (value > 0.0 && (new tcuFloat.deFloat().deFloatNumber(value)).exponent() < minExponent) { 249 // flush to zero if possible 250 return 0.0; 251 } else { 252 // just mask away non-representable bits 253 return (new tcuFloat.deFloat()).construct(1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).getValue(); 254 } 255 } else { 256 if (inputFloat.mantissa() & truncMask) { 257 // decrement one ulp if truncated bits are non-zero (i.e. if value is not representable) 258 return (new tcuFloat.deFloat()).construct(-1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).getValue() - es3fShaderDerivateTests.getSingleULPForExponent(inputFloat.exponent(), numAccurateBits); 259 } else { 260 // value is representable, no need to do anything 261 return value; 262 } 263 } 264 } 265 }; 266 267 /** 268 * @param {number} value 269 * @param {number} minExponent 270 * @param {number} numAccurateBits 271 * @return {number} 272 */ 273 es3fShaderDerivateTests.convertCeilFlushToZero = function(value, minExponent, numAccurateBits) { 274 return -es3fShaderDerivateTests.convertFloorFlushToZero(-value, minExponent, numAccurateBits); 275 }; 276 277 /** 278 * @param {number} value 279 * @param {number} numUlps 280 * @param {number} numMantissaBits 281 * @return {number} 282 */ 283 es3fShaderDerivateTests.addErrorUlp = function(value, numUlps, numMantissaBits) { 284 return value + numUlps * es3fShaderDerivateTests.getSingleULPForValue(value, numMantissaBits); 285 }; 286 287 /** 288 * @param {?gluShaderUtil.precision} precision 289 * @param {Array<number>} valueMin 290 * @param {Array<number>} valueMax 291 * @param {Array<number>} expectedDerivate 292 * @return {Array<number>} 293 */ 294 es3fShaderDerivateTests.getDerivateThreshold = function(precision, valueMin, valueMax, expectedDerivate) { 295 /** @type {number} */ var baseBits = es3fShaderDerivateTests.getNumMantissaBits(precision); 296 /** @type {Array<number>} */ var derivExp = es3fShaderDerivateTests.getCompExpBits(expectedDerivate); 297 /** @type {Array<number>} */ var maxValueExp = deMath.max(es3fShaderDerivateTests.getCompExpBits(valueMin), es3fShaderDerivateTests.getCompExpBits(valueMax)); 298 /** @type {Array<number>} */ var numBitsLost = deMath.subtract(maxValueExp, deMath.min(maxValueExp, derivExp)); 299 /** @type {Array<number>} */ 300 var numAccurateBits = deMath.max( 301 deMath.addScalar( 302 deMath.subtract( 303 [baseBits, baseBits, baseBits, baseBits], 304 numBitsLost), 305 -es3fShaderDerivateTests.INTERPOLATION_LOST_BITS), 306 [0, 0, 0, 0]); 307 308 return [es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]), 309 es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]), 310 es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]), 311 es3fShaderDerivateTests.computeFloatingPointError(expectedDerivate[3], numAccurateBits[3])]; 312 }; 313 314 /** 315 * @param {tcuTexture.ConstPixelBufferAccess} result 316 * @param {tcuTexture.PixelBufferAccess} errorMask 317 * @param {?gluShaderUtil.DataType} dataType 318 * @param {Array<number>} reference 319 * @param {Array<number>} threshold 320 * @param {Array<number>} scale 321 * @param {Array<number>} bias 322 * @param {es3fShaderDerivateTests.VerificationLogging=} logPolicy 323 * @return {boolean} 324 */ 325 es3fShaderDerivateTests.verifyConstantDerivate = function(result, errorMask, dataType, reference, threshold, scale, bias, logPolicy) { 326 logPolicy = logPolicy === undefined ? es3fShaderDerivateTests.VerificationLogging.LOG_ALL : logPolicy; 327 /** @type {Array<boolean>} */ var mask = deMath.logicalNotBool(es3fShaderDerivateTests.getDerivateMask(dataType)); 328 /** @type {number} */ var numFailedPixels = 0; 329 330 if (logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL) 331 bufferedLogToConsole('Expecting ' + reference + ' with threshold ' + threshold); 332 333 for (var y = 0; y < result.getHeight(); y++) { 334 for (var x = 0; x < result.getWidth(); x++) { 335 /** @type {Array<number>} */ var resDerivate = es3fShaderDerivateTests.readDerivate(result, scale, bias, x, y); 336 /** @type {boolean} */ 337 var isOk = deMath.boolAll( 338 deMath.logicalOrBool( 339 deMath.lessThanEqual( 340 deMath.abs(deMath.subtract(reference, resDerivate)), 341 threshold), 342 mask)); 343 344 if (!isOk) { 345 if (numFailedPixels < es3fShaderDerivateTests.MAX_FAILED_MESSAGES && logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL) 346 bufferedLogToConsole('FAIL: got ' + resDerivate + ', diff = ' + deMath.abs(deMath.subtract(reference, resDerivate)) + ', at x = ' + x + ', y = ' + y); 347 numFailedPixels += 1; 348 errorMask.setPixel(tcuRGBA.RGBA.red.toVec(), x, y); 349 } 350 } 351 } 352 353 if (numFailedPixels >= es3fShaderDerivateTests.MAX_FAILED_MESSAGES && logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL) 354 bufferedLogToConsole('...'); 355 356 if (numFailedPixels > 0 && logPolicy === es3fShaderDerivateTests.VerificationLogging.LOG_ALL) 357 bufferedLogToConsole('FAIL: found ' + numFailedPixels + ' failed pixels'); 358 359 return numFailedPixels === 0; 360 }; 361 362 /** 363 * .-----. 364 * | s_x | 365 * M x | s_y | 366 * | 1.0 | 367 * '-----' 368 * @struct 369 * @constructor 370 */ 371 es3fShaderDerivateTests.Linear2DFunctionEvaluator = function() { 372 /** @type {tcuMatrix.Matrix} */ this.matrix = new tcuMatrix.Matrix(4, 3); 373 }; 374 375 es3fShaderDerivateTests.Linear2DFunctionEvaluator.prototype.evaluateAt = function(screenX, screenY) { 376 /** @type {Array<number>} */ var position = [screenX, screenY, 1.0]; 377 return tcuMatrix.multiplyMatVec(this.matrix, position); 378 }; 379 380 /** 381 * @param {tcuTexture.ConstPixelBufferAccess} result 382 * @param {tcuTexture.PixelBufferAccess} errorMask 383 * @param {?gluShaderUtil.DataType} dataType 384 * @param {?gluShaderUtil.precision} precision 385 * @param {Array<number>} derivScale 386 * @param {Array<number>} derivBias 387 * @param {Array<number>} surfaceThreshold 388 * @param {es3fShaderDerivateTests.DerivateFunc} derivateFunc 389 * @param {es3fShaderDerivateTests.Linear2DFunctionEvaluator} func 390 * @return {boolean} 391 */ 392 es3fShaderDerivateTests.reverifyConstantDerivateWithFlushRelaxations = function(result, errorMask, dataType, precision, derivScale, derivBias, surfaceThreshold, derivateFunc, func) { 393 assertMsgOptions(result.getWidth() === errorMask.getWidth(), 'Dimensions of result and errorMask inconsistent.', false, true); 394 assertMsgOptions(result.getHeight() === errorMask.getHeight(), 'Dimensions of result and errorMask inconsistent.', false, true); 395 assertMsgOptions(derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX || derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDY, 'Derivate Function should be DFDX or DFDY.', false, true); 396 397 /** @type {Array<number>} */ var red = [255, 0, 0, 255]; 398 /** @type {Array<number>} */ var green = [0, 255, 0, 255]; 399 /** @type {number} */ var divisionErrorUlps = 2.5; 400 401 /** @type {number} */ var numComponents = gluShaderUtil.getDataTypeScalarTypeAsDataType(dataType); 402 /** @type {number} */ var numBits = es3fShaderDerivateTests.getNumMantissaBits(precision); 403 /** @type {number} */ var minExponent = es3fShaderDerivateTests.getMinExponent(precision); 404 405 /** @type {number} */ var numVaryingSampleBits = numBits - es3fShaderDerivateTests.INTERPOLATION_LOST_BITS; 406 /** @type {number} */ var numFailedPixels = 0; 407 408 errorMask.clear(green); 409 410 // search for failed pixels 411 for (var y = 0; y < result.getHeight(); ++y) 412 for (var x = 0; x < result.getWidth(); ++x) { 413 // flushToZero?(f2z?(functionValueCurrent) - f2z?(functionValueBefore)) 414 // flushToZero? ( ------------------------------------------------------------------------ +- 2.5 ULP ) 415 // dx 416 417 /** @type {Array<number>} */ var resultDerivative = es3fShaderDerivateTests.readDerivate(result, derivScale, derivBias, x, y); 418 419 // sample at the front of the back pixel and the back of the front pixel to cover the whole area of 420 // legal sample positions. In general case this is NOT OK, but we know that the target funtion is 421 // (mostly*) linear which allows us to take the sample points at arbitrary points. This gets us the 422 // maximum difference possible in exponents which are used in error bound calculations. 423 // * non-linearity may happen around zero or with very high function values due to subnorms not 424 // behaving well. 425 /** @type {Array<number>} */ var functionValueForward = (derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX) ? 426 (func.evaluateAt(x + 2.0, y + 0.5)) : 427 (func.evaluateAt(x + 0.5, y + 2.0)); 428 /** @type {Array<number>} */ var functionValueBackward = (derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX) ? 429 (func.evaluateAt(x - 1.0, y + 0.5)) : 430 (func.evaluateAt(x + 0.5, y - 1.0)); 431 432 /** @type {boolean} */ var anyComponentFailed = false; 433 434 // check components separately 435 for (var c = 0; c < numComponents; ++c) { 436 // interpolation value range 437 /** @type {tcuInterval.Interval} */ var forwardComponent = tcuInterval.withIntervals( 438 new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero( 439 es3fShaderDerivateTests.addErrorUlp(functionValueForward[c], -0.5, numVaryingSampleBits), minExponent, numBits)), 440 new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero( 441 es3fShaderDerivateTests.addErrorUlp(functionValueForward[c], +0.5, numVaryingSampleBits), minExponent, numBits)) 442 ); 443 444 /** @type {tcuInterval.Interval} */ var backwardComponent = tcuInterval.withIntervals( 445 new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero( 446 es3fShaderDerivateTests.addErrorUlp(functionValueBackward[c], -0.5, numVaryingSampleBits), minExponent, numBits)), 447 new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero( 448 es3fShaderDerivateTests.addErrorUlp(functionValueBackward[c], +0.5, numVaryingSampleBits), minExponent, numBits)) 449 ); 450 451 /** @type {number} */ 452 var maxValueExp = Math.max( 453 (new tcuFloat.deFloat().deFloatNumber(forwardComponent.lo())).exponent(), 454 (new tcuFloat.deFloat().deFloatNumber(forwardComponent.hi())).exponent(), 455 (new tcuFloat.deFloat().deFloatNumber(backwardComponent.lo())).exponent(), 456 (new tcuFloat.deFloat().deFloatNumber(backwardComponent.hi())).exponent()); 457 458 // subtraction in nominator will likely cause a cancellation of the most 459 // significant bits. Apply error bounds. 460 /** @type {tcuInterval.Interval} */ var nominator = tcuInterval.Interval.operatorSub(forwardComponent, backwardComponent); 461 /** @type {number} */ var nominatorLoExp = (new tcuFloat.deFloat().deFloatNumber(nominator.lo())).exponent(); 462 /** @type {number} */ var nominatorHiExp = (new tcuFloat.deFloat().deFloatNumber(nominator.hi())).exponent(); 463 /** @type {number} */ var nominatorLoBitsLost = maxValueExp - nominatorLoExp; 464 /** @type {number} */ var nominatorHiBitsLost = maxValueExp - nominatorHiExp; 465 /** @type {number} */ var nominatorLoBits = Math.max(0, numBits - nominatorLoBitsLost); 466 /** @type {number} */ var nominatorHiBits = Math.max(0, numBits - nominatorHiBitsLost); 467 468 /** @type {tcuInterval.Interval} */ var nominatorRange = tcuInterval.withIntervals( 469 new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero(nominator.lo(), minExponent, nominatorLoBits)), 470 new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero(nominator.hi(), minExponent, nominatorHiBits))); 471 // 472 /** @type {tcuInterval.Interval} */ var divisionRange = tcuInterval.Interval.operatorDiv(nominatorRange, new tcuInterval.Interval(3.0)); // legal sample area is anywhere within this and neighboring pixels (i.e. size = 3) 473 /** @type {tcuInterval.Interval} */ var divisionResultRange = tcuInterval.withIntervals( 474 new tcuInterval.Interval(es3fShaderDerivateTests.convertFloorFlushToZero(es3fShaderDerivateTests.addErrorUlp(divisionRange.lo(), -divisionErrorUlps, numBits), minExponent, numBits)), 475 new tcuInterval.Interval(es3fShaderDerivateTests.convertCeilFlushToZero(es3fShaderDerivateTests.addErrorUlp(divisionRange.hi(), divisionErrorUlps, numBits), minExponent, numBits))); 476 /** @type {tcuInterval.Interval} */ var finalResultRange = tcuInterval.withIntervals( 477 new tcuInterval.Interval(divisionResultRange.lo() - surfaceThreshold[c]), 478 new tcuInterval.Interval(divisionResultRange.hi() + surfaceThreshold[c])); 479 480 if (resultDerivative[c] >= finalResultRange.lo() && resultDerivative[c] <= finalResultRange.hi()) { 481 // value ok 482 } else { 483 if (numFailedPixels < es3fShaderDerivateTests.MAX_FAILED_MESSAGES) 484 bufferedLogToConsole('Error in pixel at ' + x + ', ' + y + ' with component ' + c + ' (channel ' + ('rgba'[c]) + ')\n' + 485 '\tGot pixel value ' + result.getPixelInt(x, y) + '\n' + 486 '\t\tdFd' + ((derivateFunc === es3fShaderDerivateTests.DerivateFunc.DFDX) ? 'x' : 'y') + ' ~= ' + resultDerivative[c] + '\n' + 487 '\t\tdifference to a valid range: ' + 488 ((resultDerivative[c] < finalResultRange.lo()) ? '-' : '+') + 489 ((resultDerivative[c] < finalResultRange.lo()) ? (finalResultRange.lo() - resultDerivative[c]) : (resultDerivative[c] - finalResultRange.hi())) + 490 '\n' + 491 '\tDerivative value range:\n' + 492 '\t\tMin: ' + finalResultRange.lo() + '\n' + 493 '\t\tMax: ' + finalResultRange.hi() + '\n'); 494 495 ++numFailedPixels; 496 anyComponentFailed = true; 497 } 498 } 499 500 if (anyComponentFailed) 501 errorMask.setPixel(red, x, y); 502 } 503 504 if (numFailedPixels >= es3fShaderDerivateTests.MAX_FAILED_MESSAGES) 505 bufferedLogToConsole('...'); 506 507 if (numFailedPixels > 0) 508 bufferedLogToConsole('FAIL: found ' + numFailedPixels + ' failed pixels'); 509 510 return numFailedPixels === 0; 511 }; 512 513 /** 514 * @constructor 515 * @extends {tcuTestCase.DeqpTest} 516 * @param {string} name 517 * @param {string} description 518 */ 519 es3fShaderDerivateTests.TriangleDerivateCase = function(name, description) { 520 tcuTestCase.DeqpTest.call(this, name, description); 521 /** @type {?gluShaderUtil.DataType} */ this.m_dataType = null; 522 /** @type {?gluShaderUtil.precision} */ this.m_precision = null; 523 524 /** @type {?gluShaderUtil.DataType} */ this.m_coordDataType = null; 525 /** @type {?gluShaderUtil.precision} */ this.m_coordPrecision = null; 526 527 /** @type {string} */ this.m_fragmentSrc; 528 529 /** @type {Array<number>} */ this.m_coordMin = []; 530 /** @type {Array<number>} */ this.m_coordMax = []; 531 /** @type {Array<number>} */ this.m_derivScale = []; 532 /** @type {Array<number>} */ this.m_derivBias = []; 533 534 /** @type {es3fShaderDerivateTests.SurfaceType} */ this.m_surfaceType = es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER; 535 /** @type {number} */ this.m_numSamples = 0; 536 /** @type {number} */ this.m_hint = gl.DONT_CARE; 537 538 assertMsgOptions(this.m_surfaceType !== es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER || this.m_numSamples === 0, 'Did not expect surfaceType = DEFAULT_FRAMEBUFFER or numSamples = 0', false, true); 539 }; 540 541 es3fShaderDerivateTests.TriangleDerivateCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 542 es3fShaderDerivateTests.TriangleDerivateCase.prototype.constructor = es3fShaderDerivateTests.TriangleDerivateCase; 543 544 es3fShaderDerivateTests.TriangleDerivateCase.prototype.deinit = function() {}; 545 546 /** @param {WebGLProgram} program */ 547 es3fShaderDerivateTests.TriangleDerivateCase.prototype.setupRenderState = function(program) {}; 548 549 /** 550 * @param {?gluShaderUtil.DataType} coordType 551 * @param {?gluShaderUtil.precision} precision 552 * @return {string} 553 */ 554 es3fShaderDerivateTests.genVertexSource = function(coordType, precision) { 555 assertMsgOptions(gluShaderUtil.isDataTypeFloatOrVec(coordType), 'Coord Type not supported', false, true); 556 557 /** @type {string} */ var vertexTmpl = '' + 558 '#version 300 es\n' + 559 'in highp vec4 a_position;\n' + 560 'in ${PRECISION} ${DATATYPE} a_coord;\n' + 561 'out ${PRECISION} ${DATATYPE} v_coord;\n' + 562 'void main (void)\n' + 563 '{\n' + 564 ' gl_Position = a_position;\n' + 565 ' v_coord = a_coord;\n' + 566 '}\n'; 567 568 /** @type {Object} */ var vertexParams = {}; 569 570 vertexParams['PRECISION'] = gluShaderUtil.getPrecisionName(precision); 571 vertexParams['DATATYPE'] = gluShaderUtil.getDataTypeName(coordType); 572 573 return tcuStringTemplate.specialize(vertexTmpl, vertexParams); 574 }; 575 576 /** 577 * @return {Array<number>} 578 */ 579 es3fShaderDerivateTests.TriangleDerivateCase.prototype.getViewportSize = function() { 580 if (this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER) { 581 /** @type {number} */ var width = Math.min(gl.drawingBufferWidth, es3fShaderDerivateTests.VIEWPORT_WIDTH); 582 /** @type {number} */ var height = Math.min(gl.drawingBufferHeight, es3fShaderDerivateTests.VIEWPORT_HEIGHT); 583 return [width, height]; 584 } else 585 return [es3fShaderDerivateTests.FBO_WIDTH, es3fShaderDerivateTests.FBO_HEIGHT]; 586 }; 587 588 /** 589 * @return {tcuTestCase.IterateResult} 590 */ 591 es3fShaderDerivateTests.TriangleDerivateCase.prototype.iterate = function() { 592 /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(es3fShaderDerivateTests.genVertexSource(this.m_coordDataType, this.m_coordPrecision), this.m_fragmentSrc)); 593 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xbbc24); 594 /** @type {boolean} */ var useFbo = this.m_surfaceType != es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER; 595 /** @type {number} */ var fboFormat = this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO ? gl.RGBA32UI : gl.RGBA8; 596 /** @type {Array<number>} */ var viewportSize = this.getViewportSize(); 597 /** @type {number} */ var viewportX = useFbo ? 0 : rnd.getInt(0, gl.drawingBufferWidth - viewportSize[0]); 598 /** @type {number} */ var viewportY = useFbo ? 0 : rnd.getInt(0, gl.drawingBufferHeight - viewportSize[1]); 599 /** @type {?WebGLFramebuffer} */ var fbo = null; 600 /** @type {?WebGLRenderbuffer} */ var rbo = null; 601 /** @type {tcuTexture.TextureLevel} */ var result = null; 602 603 bufferedLogToConsole(program.getProgramInfo().infoLog); 604 605 if (!program.isOk()) 606 assertMsgOptions(false, 'Compile failed', false, true); 607 608 if (useFbo) { 609 bufferedLogToConsole('Rendering to FBO, format = ' + wtu.glEnumToString(gl, fboFormat) + ', samples = ' + this.m_numSamples); 610 611 fbo = gl.createFramebuffer(); 612 rbo = gl.createRenderbuffer(); 613 614 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 615 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, this.m_numSamples, fboFormat, viewportSize[0], viewportSize[1]); 616 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 617 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); 618 } else { 619 /** @type {tcuPixelFormat.PixelFormat} */ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl); 620 621 bufferedLogToConsole('Rendering to default framebuffer\n' + 622 '\tColor depth: R=' + pixelFormat.redBits + ', G=' + pixelFormat.greenBits + ', B=' + pixelFormat.blueBits + ', A=' + pixelFormat.alphaBits); 623 } 624 625 bufferedLogToConsole('in: ' + this.m_coordMin + ' ' + this.m_coordMax + '\n' + 626 'v_coord.x = in.x * x\n' + 627 'v_coord.y = in.y * y\n' + 628 'v_coord.z = in.z * (x+y)/2\n' + 629 'v_coord.w = in.w * (1 - (x+y)/2)\n' + 630 '\n' + 631 'u_scale: ' + this.m_derivScale + ', u_bias: ' + this.m_derivBias + ' (displayed values have scale/bias removed)' + 632 'Viewport: ' + viewportSize[0] + 'x' + viewportSize[1] + 633 'gl.FRAGMENT_SHADER_DERIVATE_HINT: ' + wtu.glEnumToString(gl, this.m_hint)); 634 // Draw 635 /** @type {Array<number>} */ var positions = [ 636 -1.0, -1.0, 0.0, 1.0, 637 -1.0, 1.0, 0.0, 1.0, 638 1.0, -1.0, 0.0, 1.0, 639 1.0, 1.0, 0.0, 1.0 640 ]; 641 642 /** @type {Array<number>} */ var coords =[ 643 this.m_coordMin[0], this.m_coordMin[1], this.m_coordMin[2], this.m_coordMax[3], 644 this.m_coordMin[0], this.m_coordMax[1], (this.m_coordMin[2] + this.m_coordMax[2]) * 0.5, (this.m_coordMin[3]+this.m_coordMax[3]) * 0.5, 645 this.m_coordMax[0], this.m_coordMin[1], (this.m_coordMin[2] + this.m_coordMax[2]) * 0.5, (this.m_coordMin[3]+this.m_coordMax[3]) * 0.5, 646 this.m_coordMax[0], this.m_coordMax[1], this.m_coordMax[2], this.m_coordMin[3] 647 ]; 648 649 /** @type {Array<gluDrawUtil.VertexArrayBinding>} */ var vertexArrays = [ 650 gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions), 651 gluDrawUtil.newFloatVertexArrayBinding('a_coord', 4, 4, 0, coords) 652 ]; 653 654 /** @type {Array<number>} */ var indices = [0, 2, 1, 2, 3, 1]; 655 656 gl.clearColor(0.125, 0.25, 0.5, 1.0); 657 // We can't really call clear() on gl.COLOR_BUFFER_BIT here as in c++ deqp. 658 // The fbo format might be of integer type and WebGL2 requires an INVALID_OPERATION to be generated. 659 var formatObj = gluTextureUtil.mapGLInternalFormat(fboFormat); 660 var fmtClass = tcuTexture.getTextureChannelClass(formatObj.type); 661 switch (fmtClass) { 662 case tcuTexture.TextureChannelClass.FLOATING_POINT: 663 case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT: 664 case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT: 665 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 666 break; 667 case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER: 668 gl.clearBufferuiv(gl.COLOR, 0, new Uint32Array([31, 63, 127, 255])); 669 gl.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 670 break; 671 case tcuTexture.TextureChannelClass.SIGNED_INTEGER: 672 gl.clearBufferiv(gl.COLOR, 0, new Int32Array([31, 63, 127, 255])); 673 gl.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 674 break; 675 default: 676 throw new Error('Invalid channelclass ' + fmtClass); 677 } 678 gl.disable(gl.DITHER); 679 680 gl.useProgram(program.getProgram()); 681 682 /** @type {WebGLUniformLocation} */ var scaleLoc = gl.getUniformLocation(program.getProgram(), 'u_scale'); 683 /** @type {WebGLUniformLocation} */ var biasLoc = gl.getUniformLocation(program.getProgram(), 'u_bias'); 684 685 switch (this.m_dataType) { 686 case gluShaderUtil.DataType.FLOAT: 687 gl.uniform1f(scaleLoc, this.m_derivScale[0]); 688 gl.uniform1f(biasLoc, this.m_derivBias[0]); 689 break; 690 691 case gluShaderUtil.DataType.FLOAT_VEC2: 692 gl.uniform2fv(scaleLoc, this.m_derivScale.slice(0,2)); 693 gl.uniform2fv(biasLoc, this.m_derivBias.slice(0,2)); 694 break; 695 696 case gluShaderUtil.DataType.FLOAT_VEC3: 697 gl.uniform3fv(scaleLoc, this.m_derivScale.slice(0,3)); 698 gl.uniform3fv(biasLoc, this.m_derivBias.slice(0,3)); 699 break; 700 701 case gluShaderUtil.DataType.FLOAT_VEC4: 702 gl.uniform4fv(scaleLoc, this.m_derivScale); 703 gl.uniform4fv(biasLoc, this.m_derivBias); 704 break; 705 706 default: 707 throw new Error('Data Type not supported: ' + this.m_dataType); 708 } 709 710 glsShaderRenderCase.setupDefaultUniforms(program.getProgram()); 711 this.setupRenderState(program.getProgram()); 712 713 gl.hint(gl.FRAGMENT_SHADER_DERIVATIVE_HINT, this.m_hint); 714 715 gl.viewport(viewportX, viewportY, viewportSize[0], viewportSize[1]); 716 gluDrawUtil.draw(gl, program.getProgram(), vertexArrays, gluDrawUtil.triangles(indices)); 717 718 // Read back results 719 720 /** @type {boolean} */ var isMSAA = useFbo && this.m_numSamples > 0; 721 /** @type {?WebGLFramebuffer} */ var resFbo = null; 722 /** @type {?WebGLRenderbuffer} */ var resRbo = null; 723 724 // Resolve if necessary 725 if (isMSAA) { 726 resFbo = gl.createFramebuffer(); 727 resRbo = gl.createRenderbuffer(); 728 729 gl.bindRenderbuffer(gl.RENDERBUFFER, resRbo); 730 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 0, fboFormat, viewportSize[0], viewportSize[1]); 731 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resFbo); 732 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resRbo); 733 734 gl.blitFramebuffer(0, 0, viewportSize[0], viewportSize[1], 0, 0, viewportSize[0], viewportSize[1], gl.COLOR_BUFFER_BIT, gl.NEAREST); 735 736 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, resFbo); 737 } 738 switch (this.m_surfaceType) { 739 case es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER: 740 case es3fShaderDerivateTests.SurfaceType.UNORM_FBO: 741 var dataFormat = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8); 742 result = new tcuTexture.TextureLevel(dataFormat, viewportSize[0], viewportSize[1]); 743 gluPixelTransfer.readPixels(gl, viewportX, viewportY, dataFormat, result); 744 break; 745 746 case es3fShaderDerivateTests.SurfaceType.FLOAT_FBO: 747 var dataFormat = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.FLOAT); 748 var transferFormat = new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT32); 749 result = new tcuTexture.TextureLevel(dataFormat, viewportSize[0], viewportSize[1]); 750 gluPixelTransfer.readPixels(gl, viewportX, viewportY, transferFormat, result); 751 break; 752 753 default: 754 throw new Error('Surface Type not supported: ' + this.m_surfaceType); 755 } 756 757 // Verify 758 /** @type {tcuSurface.Surface} */ 759 var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight()); 760 761 errorMask.getAccess().clear(tcuRGBA.RGBA.green.toVec()); 762 763 /** @type {boolean} */ var isOk = this.verify(result.getAccess(), errorMask.getAccess()); 764 765 if (!isOk) { 766 tcuLogImage.logImage('Rendered', 'Rendered image', result.getAccess()); 767 tcuLogImage.logImage('ErrorMask', 'Error mask', errorMask.getAccess()); 768 testFailedOptions('Fail', false); 769 } else 770 testPassedOptions('Pass', true); 771 772 // Cleaning up buffers 773 gl.deleteFramebuffer(fbo); 774 gl.deleteRenderbuffer(rbo); 775 gl.deleteFramebuffer(resFbo); 776 gl.deleteRenderbuffer(resRbo); 777 778 return tcuTestCase.IterateResult.STOP; 779 }; 780 781 /** 782 * @return {Array<number>} 783 */ 784 es3fShaderDerivateTests.TriangleDerivateCase.prototype.getSurfaceThreshold = function() { 785 switch (this.m_surfaceType) { 786 case es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER: 787 /** @type {tcuPixelFormat.PixelFormat} */ var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl); 788 /** @type {Array<number>} */ var channelBits = [pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits]; 789 /** @type {Array<number>} */ var intThreshold = deMath.arrayShiftLeft([1, 1, 1, 1], deMath.subtract([8, 8, 8, 8], channelBits)); 790 /** @type {Array<number>} */ var normThreshold = deMath.scale(intThreshold, 1.0/255.0); 791 792 return normThreshold; 793 794 case es3fShaderDerivateTests.SurfaceType.UNORM_FBO: return deMath.scale([1, 1, 1, 1], 1.0/255.0); 795 case es3fShaderDerivateTests.SurfaceType.FLOAT_FBO: return [0.0, 0.0, 0.0, 0.0]; 796 default: 797 assertMsgOptions(false, 'Surface Type not supported. Falling back to default retun value [0.0, 0.0, 0.0, 0.0]', false, false); 798 return [0.0, 0.0, 0.0, 0.0]; 799 } 800 }; 801 802 /** 803 * @constructor 804 * @extends {es3fShaderDerivateTests.TriangleDerivateCase} 805 * @param {string} name 806 * @param {string} description 807 * @param {es3fShaderDerivateTests.DerivateFunc} func 808 * @param {gluShaderUtil.DataType} type 809 */ 810 es3fShaderDerivateTests.ConstantDerivateCase = function(name, description, func, type) { 811 es3fShaderDerivateTests.TriangleDerivateCase.call(this, name, description); 812 /** @type {es3fShaderDerivateTests.DerivateFunc} */ this.m_func = func; 813 this.m_dataType = type; 814 this.m_precision = gluShaderUtil.precision.PRECISION_HIGHP; 815 this.m_coordDataType = this.m_dataType; 816 this.m_coordPrecision = this.m_precision; 817 }; 818 819 es3fShaderDerivateTests.ConstantDerivateCase.prototype = Object.create(es3fShaderDerivateTests.TriangleDerivateCase.prototype); 820 es3fShaderDerivateTests.ConstantDerivateCase.prototype.constructor = es3fShaderDerivateTests.ConstantDerivateCase; 821 822 es3fShaderDerivateTests.ConstantDerivateCase.prototype.init = function() { 823 /** @type {string} */ var fragmentTmpl = '' + 824 '#version 300 es\n' + 825 'layout(location = 0) out mediump vec4 o_color;\n' + 826 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 827 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 828 'void main (void)\n' + 829 '{\n' + 830 ' ${PRECISION} ${DATATYPE} res = ${FUNC}(${VALUE}) * u_scale + u_bias;\n' + 831 ' o_color = ${CAST_TO_OUTPUT};\n' + 832 '}\n'; 833 834 /** @type {Object} */ var fragmentParams = {}; 835 fragmentParams['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_precision); 836 fragmentParams['DATATYPE'] = gluShaderUtil.getDataTypeName(this.m_dataType); 837 fragmentParams['FUNC'] = es3fShaderDerivateTests.getDerivateFuncName(this.m_func); 838 fragmentParams['VALUE'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'vec4(1.0, 7.2, -1e5, 0.0)' : 839 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec3(1e2, 8.0, 0.01)' : 840 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec2(-0.0, 2.7)' : 841 '7.7'; 842 fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'res' : 843 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec4(res, 1.0)' : 844 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec4(res, 0.0, 1.0)' : 845 'vec4(res, 0.0, 0.0, 1.0)'; 846 847 this.m_fragmentSrc = tcuStringTemplate.specialize(fragmentTmpl, fragmentParams); 848 849 this.m_derivScale = [1e3, 1e3, 1e3, 1e3]; 850 this.m_derivBias = [0.5, 0.5, 0.5, 0.5]; 851 }; 852 853 /** 854 * @param {tcuTexture.ConstPixelBufferAccess} result 855 * @param {tcuTexture.PixelBufferAccess} errorMask 856 * @return {boolean} 857 */ 858 es3fShaderDerivateTests.ConstantDerivateCase.prototype.verify = function(result, errorMask) { 859 /** @type {Array<number>} */ var reference = [0.0, 0.0, 0.0, 0.0]; // Derivate of constant argument should always be 0 860 /** @type {Array<number>} */ var threshold = deMath.divide(this.getSurfaceThreshold(), deMath.abs(this.m_derivScale)); 861 return es3fShaderDerivateTests.verifyConstantDerivate(result, errorMask, this.m_dataType, 862 reference, threshold, this.m_derivScale, this.m_derivBias); 863 }; 864 865 /** 866 * @constructor 867 * @extends {es3fShaderDerivateTests.TriangleDerivateCase} 868 * @param {string} name 869 * @param {string} description 870 * @param {es3fShaderDerivateTests.DerivateFunc} func 871 * @param {gluShaderUtil.DataType} type 872 * @param {gluShaderUtil.precision} precision 873 * @param {number} hint 874 * @param {es3fShaderDerivateTests.SurfaceType} surfaceType 875 * @param {number} numSamples 876 * @param {string} fragmentSrcTmpl 877 */ 878 es3fShaderDerivateTests.LinearDerivateCase = function(name, description, func, type, precision, hint, surfaceType, numSamples, fragmentSrcTmpl) { 879 es3fShaderDerivateTests.TriangleDerivateCase.call(this, name, description); 880 /** @type {es3fShaderDerivateTests.DerivateFunc} */ this.m_func = func; 881 /** @type {string} */ this.m_fragmentTmpl = fragmentSrcTmpl; 882 this.m_dataType = type; 883 this.m_precision = precision; 884 this.m_coordDataType = this.m_dataType; 885 this.m_coordPrecision = this.m_precision; 886 this.m_hint = hint; 887 this.m_surfaceType = surfaceType; 888 this.m_numSamples = numSamples; 889 }; 890 891 es3fShaderDerivateTests.LinearDerivateCase.prototype = Object.create(es3fShaderDerivateTests.TriangleDerivateCase.prototype); 892 es3fShaderDerivateTests.LinearDerivateCase.prototype.constructor = es3fShaderDerivateTests.LinearDerivateCase; 893 894 es3fShaderDerivateTests.LinearDerivateCase.prototype.init = function() { 895 /** @type {Array<number>} */ var viewportSize = this.getViewportSize(); 896 /** @type {number} */ var w = viewportSize[0]; 897 /** @type {number} */ var h = viewportSize[1]; 898 /** @type {boolean} */ var packToInt = this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO; 899 900 /** @type {Object} */ var fragmentParams = {}; 901 fragmentParams['OUTPUT_TYPE'] = gluShaderUtil.getDataTypeName(packToInt ? gluShaderUtil.DataType.UINT_VEC4 : gluShaderUtil.DataType.FLOAT_VEC4); 902 fragmentParams['OUTPUT_PREC'] = gluShaderUtil.getPrecisionName(packToInt ? gluShaderUtil.precision.PRECISION_HIGHP : this.m_precision); 903 fragmentParams['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_precision); 904 fragmentParams['DATATYPE'] = gluShaderUtil.getDataTypeName(this.m_dataType); 905 fragmentParams['FUNC'] = es3fShaderDerivateTests.getDerivateFuncName(this.m_func); 906 907 if (packToInt) { 908 fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'floatBitsToUint(res)' : 909 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'floatBitsToUint(vec4(res, 1.0))' : 910 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'floatBitsToUint(vec4(res, 0.0, 1.0))' : 911 'floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))'; 912 } else { 913 fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'res' : 914 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec4(res, 1.0)' : 915 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec4(res, 0.0, 1.0)' : 916 'vec4(res, 0.0, 0.0, 1.0)'; 917 } 918 919 this.m_fragmentSrc = tcuStringTemplate.specialize(this.m_fragmentTmpl, fragmentParams); 920 921 switch (this.m_precision) { 922 case gluShaderUtil.precision.PRECISION_HIGHP: 923 this.m_coordMin = [-97., 0.2, 71., 74.]; 924 this.m_coordMax = [-13.2, -77., 44., 76.]; 925 break; 926 927 case gluShaderUtil.precision.PRECISION_MEDIUMP: 928 this.m_coordMin = [-37.0, 47., -7., 0.0]; 929 this.m_coordMax = [-1.0, 12., 7., 19.]; 930 break; 931 932 case gluShaderUtil.precision.PRECISION_LOWP: 933 this.m_coordMin = [0.0, -1.0, 0.0, 1.0]; 934 this.m_coordMax = [1.0, 1.0, -1.0, -1.0]; 935 break; 936 937 default: 938 throw new Error('Precision not supported: ' + this.m_precision); 939 } 940 941 if (this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO) { 942 // No scale or bias used for accuracy. 943 this.m_derivScale = [1.0, 1.0, 1.0, 1.0]; 944 this.m_derivBias = [0.0, 0.0, 0.0, 0.0]; 945 } else { 946 // Compute scale - bias that normalizes to 0..1 range. 947 /** @type {Array<number>} */ var dx = deMath.divide(deMath.subtract(this.m_coordMax, this.m_coordMin), [w, w, w * 0.5, -w * 0.5]); 948 /** @type {Array<number>} */ var dy = deMath.divide(deMath.subtract(this.m_coordMax, this.m_coordMin), [h, h, h * 0.5, -h * 0.5]); 949 950 switch (this.m_func) { 951 case es3fShaderDerivateTests.DerivateFunc.DFDX: 952 this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dx); 953 break; 954 955 case es3fShaderDerivateTests.DerivateFunc.DFDY: 956 this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dy); 957 break; 958 959 case es3fShaderDerivateTests.DerivateFunc.FWIDTH: 960 this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], deMath.add(deMath.abs(dx), deMath.abs(dy))); 961 break; 962 963 default: 964 throw new Error('Derivate Function not supported: ' + this.m_func); 965 } 966 967 this.m_derivBias = [0.0, 0.0, 0.0, 0.0]; 968 } 969 }; 970 971 /** 972 * @param {tcuTexture.ConstPixelBufferAccess} result 973 * @param {tcuTexture.PixelBufferAccess} errorMask 974 * @return {boolean} 975 */ 976 es3fShaderDerivateTests.LinearDerivateCase.prototype.verify = function(result, errorMask) { 977 /** @type {Array<number>} */ var xScale = [1.0, 0.0, 0.5, -0.5]; 978 /** @type {Array<number>} */ var yScale = [0.0, 1.0, 0.5, -0.5]; 979 /** @type {Array<number>} */ var surfaceThreshold = deMath.divide(this.getSurfaceThreshold(), deMath.abs(this.m_derivScale)); 980 981 /** @type {number} */ var w; 982 /** @type {number} */ var h; 983 /** @type {Array<number>} */ var reference; 984 /** @type {Array<number>} */ var threshold; 985 986 if (this.m_func === es3fShaderDerivateTests.DerivateFunc.DFDX || this.m_func === es3fShaderDerivateTests.DerivateFunc.DFDY) { 987 /** @type {boolean} */ var isX = this.m_func === es3fShaderDerivateTests.DerivateFunc.DFDX; 988 /** @type {number} */ var div = isX ? result.getWidth() : result.getHeight(); 989 /** @type {Array<number>} */ var scale = isX ? xScale : yScale; 990 reference = deMath.multiply(deMath.scale(deMath.subtract(this.m_coordMax, this.m_coordMin), 1/div), scale); 991 /** @type {Array<number>} */ var opThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_coordMin, scale), deMath.multiply(this.m_coordMax, scale), reference); 992 threshold = deMath.max(surfaceThreshold, opThreshold); 993 bufferedLogToConsole('Verifying result image.\n' + 994 '\tValid derivative is ' + reference + ' with threshold ' + threshold); 995 996 // short circuit if result is strictly within the normal value error bounds. 997 // This improves performance significantly. 998 if (es3fShaderDerivateTests.verifyConstantDerivate(result, errorMask, 999 this.m_dataType, reference, threshold, this.m_derivScale, 1000 this.m_derivBias, es3fShaderDerivateTests.VerificationLogging.LOG_NOTHING)) { 1001 bufferedLogToConsole('No incorrect derivatives found, result valid.'); 1002 return true; 1003 } 1004 1005 // some pixels exceed error bounds calculated for normal values. Verify that these 1006 // potentially invalid pixels are in fact valid due to (for example) subnorm flushing. 1007 1008 bufferedLogToConsole('Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n' + 1009 '\tVerifying each result derivative is within its range of legal result values.'); 1010 1011 /** @type {Array<number>} */ var viewportSize = this.getViewportSize(); 1012 /** @type {Array<number>} */ var valueRamp = deMath.subtract(this.m_coordMax, this.m_coordMin); 1013 /** @type {es3fShaderDerivateTests.Linear2DFunctionEvaluator} */ var function_ = new es3fShaderDerivateTests.Linear2DFunctionEvaluator(); 1014 w = viewportSize[0]; 1015 h = viewportSize[1]; 1016 1017 function_.matrix.setRow(0, [valueRamp[0] / w, 0.0, this.m_coordMin[0]]); 1018 function_.matrix.setRow(1, [0.0, valueRamp[1] / h, this.m_coordMin[1]]); 1019 function_.matrix.setRow(2, deMath.scale([valueRamp[2] / w, valueRamp[2] / h, this.m_coordMin[2] + this.m_coordMin[2]], 1 / 2.0)); 1020 function_.matrix.setRow(3, deMath.scale([-valueRamp[3] / w, -valueRamp[3] / h, this.m_coordMax[3] + this.m_coordMax[3]], 1 / 2.0)); 1021 1022 return es3fShaderDerivateTests.reverifyConstantDerivateWithFlushRelaxations( 1023 result, errorMask, this.m_dataType, this.m_precision, this.m_derivScale, 1024 this.m_derivBias, surfaceThreshold, this.m_func, function_); 1025 } else { 1026 assertMsgOptions(this.m_func === es3fShaderDerivateTests.DerivateFunc.FWIDTH, 'Expected DerivateFunc.FWIDTH', false, true); 1027 w = result.getWidth(); 1028 h = result.getHeight(); 1029 1030 /** @type {Array<number>} */ var dx = deMath.multiply(deMath.scale(deMath.subtract(this.m_coordMax, this.m_coordMin), 1 / w), xScale); 1031 /** @type {Array<number>} */ var dy = deMath.multiply(deMath.scale(deMath.subtract(this.m_coordMax, this.m_coordMin), 1 / h), yScale); 1032 reference = deMath.add(deMath.abs(dx), deMath.abs(dy)); 1033 /** @type {Array<number>} */ var dxThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_coordMin, xScale), deMath.multiply(this.m_coordMax, xScale), dx); 1034 /** @type {Array<number>} */ var dyThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_coordMin, yScale), deMath.multiply(this.m_coordMax, yScale), dy); 1035 threshold = deMath.max(surfaceThreshold, deMath.max(dxThreshold, dyThreshold)); 1036 1037 return es3fShaderDerivateTests.verifyConstantDerivate(result, errorMask, this.m_dataType, 1038 reference, threshold, this.m_derivScale, this.m_derivBias); 1039 } 1040 }; 1041 1042 /** 1043 * @constructor 1044 * @extends {es3fShaderDerivateTests.TriangleDerivateCase} 1045 * @param {string} name 1046 * @param {string} description 1047 * @param {es3fShaderDerivateTests.DerivateFunc} func 1048 * @param {gluShaderUtil.DataType} type 1049 * @param {gluShaderUtil.precision} precision 1050 * @param {number} hint 1051 * @param {es3fShaderDerivateTests.SurfaceType} surfaceType 1052 * @param {number} numSamples 1053 */ 1054 es3fShaderDerivateTests.TextureDerivateCase = function(name, description, func, type, precision, hint, surfaceType, numSamples) { 1055 es3fShaderDerivateTests.TriangleDerivateCase.call(this, name, description); 1056 /** @type {es3fShaderDerivateTests.DerivateFunc} */ this.m_func = func; 1057 /** @type {gluTexture.Texture2D} */ this.m_texture = null; 1058 /** @type {Array<number>} */ this.m_texValueMin = []; 1059 /** @type {Array<number>} */ this.m_texValueMax = []; 1060 this.m_dataType = type; 1061 this.m_precision = precision; 1062 this.m_coordDataType = gluShaderUtil.DataType.FLOAT_VEC2; 1063 this.m_coordPrecision = gluShaderUtil.precision.PRECISION_HIGHP; 1064 this.m_hint = hint; 1065 this.m_surfaceType = surfaceType; 1066 this.m_numSamples = numSamples; 1067 }; 1068 1069 es3fShaderDerivateTests.TextureDerivateCase.prototype = Object.create(es3fShaderDerivateTests.TriangleDerivateCase.prototype); 1070 es3fShaderDerivateTests.TextureDerivateCase.prototype.constructor = es3fShaderDerivateTests.TextureDerivateCase; 1071 1072 es3fShaderDerivateTests.TextureDerivateCase.prototype.deinit = function() { 1073 this.m_texture = null; 1074 }; 1075 1076 es3fShaderDerivateTests.TextureDerivateCase.prototype.init = function() { 1077 // Generate shader 1078 /** @type {string} */ var fragmentTmpl = '' + 1079 '#version 300 es\n' + 1080 'in highp vec2 v_coord;\n' + 1081 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1082 'uniform ${PRECISION} sampler2D u_sampler;\n' + 1083 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1084 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1085 'void main (void)\n' + 1086 '{\n' + 1087 ' ${PRECISION} vec4 tex = texture(u_sampler, v_coord);\n' + 1088 ' ${PRECISION} ${DATATYPE} res = ${FUNC}(tex${SWIZZLE}) * u_scale + u_bias;\n' + 1089 ' o_color = ${CAST_TO_OUTPUT};\n' + 1090 '}\n'; 1091 1092 /** @type {boolean} */ var packToInt = this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO; 1093 /** @type {Object} */ var fragmentParams = {}; 1094 /** @type {Array<number>} */ var viewportSize; 1095 fragmentParams['OUTPUT_TYPE'] = gluShaderUtil.getDataTypeName(packToInt ? gluShaderUtil.DataType.UINT_VEC4 : gluShaderUtil.DataType.FLOAT_VEC4); 1096 fragmentParams['OUTPUT_PREC'] = gluShaderUtil.getPrecisionName(packToInt ? gluShaderUtil.precision.PRECISION_HIGHP : this.m_precision); 1097 fragmentParams['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_precision); 1098 fragmentParams['DATATYPE'] = gluShaderUtil.getDataTypeName(this.m_dataType); 1099 fragmentParams['FUNC'] = es3fShaderDerivateTests.getDerivateFuncName(this.m_func); 1100 fragmentParams['SWIZZLE'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? '' : 1101 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? '.xyz' : 1102 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? '.xy' : 1103 '.x'; 1104 1105 if (packToInt) { 1106 fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'floatBitsToUint(res)' : 1107 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'floatBitsToUint(vec4(res, 1.0))' : 1108 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'floatBitsToUint(vec4(res, 0.0, 1.0))' : 1109 'floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))'; 1110 } else { 1111 fragmentParams['CAST_TO_OUTPUT'] = this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC4 ? 'res' : 1112 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC3 ? 'vec4(res, 1.0)' : 1113 this.m_dataType === gluShaderUtil.DataType.FLOAT_VEC2 ? 'vec4(res, 0.0, 1.0)' : 1114 'vec4(res, 0.0, 0.0, 1.0)'; 1115 } 1116 1117 this.m_fragmentSrc = tcuStringTemplate.specialize(fragmentTmpl, fragmentParams); 1118 1119 // Texture size matches viewport and nearest sampling is used. Thus texture sampling 1120 // is equal to just interpolating the texture value range. 1121 1122 // Determine value range for texture. 1123 1124 switch (this.m_precision) { 1125 case gluShaderUtil.precision.PRECISION_HIGHP: 1126 this.m_texValueMin = [-97., 0.2, 71., 74.]; 1127 this.m_texValueMax = [-13.2, -77., 44., 76.]; 1128 break; 1129 1130 case gluShaderUtil.precision.PRECISION_MEDIUMP: 1131 this.m_texValueMin = [-37.0, 47., -7., 0.0]; 1132 this.m_texValueMax = [-1.0, 12., 7., 19.]; 1133 break; 1134 1135 case gluShaderUtil.precision.PRECISION_LOWP: 1136 this.m_texValueMin = [0.0, -1.0, 0.0, 1.0]; 1137 this.m_texValueMax = [1.0, 1.0, -1.0, -1.0]; 1138 break; 1139 1140 default: 1141 throw new Error(false, 'Precision not supported:' + this.m_precision); 1142 } 1143 1144 // Lowp and mediump cases use RGBA16F format, while highp uses RGBA32F. 1145 viewportSize = this.getViewportSize(); 1146 assertMsgOptions(!this.m_texture, 'Texture not null', false, true); 1147 this.m_texture = gluTexture.texture2DFromInternalFormat(gl, this.m_precision === gluShaderUtil.precision.PRECISION_HIGHP ? gl.RGBA32F : gl.RGBA16F, viewportSize[0], viewportSize[1]); 1148 this.m_texture.getRefTexture().allocLevel(0); 1149 1150 // Texture coordinates 1151 this.m_coordMin = [0.0, 0.0, 0.0, 0.0]; 1152 this.m_coordMax = [1.0, 1.0, 1.0, 1.0]; 1153 1154 // Fill with gradients. 1155 /** @type {tcuTexture.PixelBufferAccess} */ var level0 = this.m_texture.getRefTexture().getLevel(0); 1156 for (var y = 0; y < level0.getHeight(); y++) { 1157 for (var x = 0; x < level0.getWidth(); x++) { 1158 /** @type {number} */ var xf = (x + 0.5) / level0.getWidth(); 1159 /** @type {number} */ var yf = (y + 0.5) / level0.getHeight(); 1160 /** @type {Array<number>} */ var s = [xf, yf, (xf + yf) / 2.0, 1.0 - (xf + yf) / 2.0]; 1161 1162 level0.setPixel(deMath.add(this.m_texValueMin, deMath.multiply(deMath.subtract(this.m_texValueMax, this.m_texValueMin), s)), x, y); 1163 } 1164 } 1165 1166 this.m_texture.upload(); 1167 1168 if (this.m_surfaceType === es3fShaderDerivateTests.SurfaceType.FLOAT_FBO) { 1169 // No scale or bias used for accuracy. 1170 this.m_derivScale = [1.0, 1.0, 1.0, 1.0]; 1171 this.m_derivBias = [0.0, 0.0, 0.0, 0.0]; 1172 } else { 1173 // Compute scale - bias that normalizes to 0..1 range. 1174 viewportSize = this.getViewportSize(); 1175 /** @type {number} */ var w = viewportSize[0]; 1176 /** @type {number} */ var h = viewportSize[1]; 1177 /** @type {Array<number>} */ var dx = deMath.divide(deMath.subtract(this.m_texValueMax, this.m_texValueMin), [w, w, w * 0.5, -w * 0.5]); 1178 /** @type {Array<number>} */ var dy = deMath.divide(deMath.subtract(this.m_texValueMax, this.m_texValueMin), [h, h, h * 0.5, -h * 0.5]); 1179 1180 switch (this.m_func) { 1181 case es3fShaderDerivateTests.DerivateFunc.DFDX: 1182 this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dx); 1183 break; 1184 1185 case es3fShaderDerivateTests.DerivateFunc.DFDY: 1186 this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], dy); 1187 break; 1188 1189 case es3fShaderDerivateTests.DerivateFunc.FWIDTH: 1190 this.m_derivScale = deMath.divide([0.5, 0.5, 0.5, 0.5], deMath.add(deMath.abs(dx), deMath.abs(dy))); 1191 break; 1192 1193 default: 1194 throw new Error('Derivate Function not supported: ' + this.m_func); 1195 } 1196 1197 this.m_derivBias = [0.0, 0.0, 0.0, 0.0]; 1198 } 1199 }; 1200 1201 /** 1202 * @param {WebGLProgram} program 1203 */ 1204 es3fShaderDerivateTests.TextureDerivateCase.prototype.setupRenderState = function(program) { 1205 /** @type {number} */ var texUnit = 1; 1206 1207 gl.activeTexture(gl.TEXTURE0 + texUnit); 1208 gl.bindTexture(gl.TEXTURE_2D, this.m_texture.getGLTexture()); 1209 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 1210 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 1211 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 1212 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 1213 1214 gl.uniform1i(gl.getUniformLocation(program, 'u_sampler'), texUnit); 1215 }; 1216 1217 /** 1218 * @param {tcuTexture.PixelBufferAccess} result 1219 * @param {tcuTexture.PixelBufferAccess} errorMask 1220 * @return {boolean} 1221 */ 1222 es3fShaderDerivateTests.TextureDerivateCase.prototype.verify = function(result, errorMask) { 1223 // \note Edges are ignored in comparison 1224 if (result.getWidth() < 2 || result.getHeight() < 2) 1225 throw new Error('Too small viewport'); 1226 1227 /** @type {tcuTexture.PixelBufferAccess} */ var compareArea = tcuTextureUtil.getSubregion(result, 1, 1, 0, result.getWidth() - 2, result.getHeight() - 2, 1); 1228 /** @type {tcuTexture.PixelBufferAccess} */ var maskArea = tcuTextureUtil.getSubregion(errorMask, 1, 1, 0, errorMask.getWidth() - 2, errorMask.getHeight() - 2, 1); 1229 /** @type {Array<number>} */ var xScale = [1.0, 0.0, 0.5, -0.5]; 1230 /** @type {Array<number>} */ var yScale = [0.0, 1.0, 0.5, -0.5]; 1231 /** @type {number} */ var w = result.getWidth(); 1232 /** @type {number} */ var h = result.getHeight(); 1233 1234 /** @type {Array<number>} */ var surfaceThreshold = deMath.divide(this.getSurfaceThreshold(), deMath.abs(this.m_derivScale)); 1235 /** @type {Array<number>} */ var reference; 1236 /** @type {Array<number>} */ var threshold; 1237 if (this.m_func == es3fShaderDerivateTests.DerivateFunc.DFDX || this.m_func == es3fShaderDerivateTests.DerivateFunc.DFDY) { 1238 /** @type {boolean} */ var isX = this.m_func == es3fShaderDerivateTests.DerivateFunc.DFDX; 1239 /** @type {number} */ var div = isX ? w : h; 1240 /** @type {Array<number>} */ var scale = isX ? xScale : yScale; 1241 reference = deMath.multiply(deMath.scale(deMath.subtract(this.m_texValueMax, this.m_texValueMin), 1 / div), scale); 1242 /** @type {Array<number>} */ var opThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_texValueMin, scale), deMath.multiply(this.m_texValueMax, scale), reference); 1243 threshold = deMath.max(surfaceThreshold, opThreshold); 1244 1245 bufferedLogToConsole('Verifying result image.\n'+ 1246 '\tValid derivative is ' + reference + ' with threshold ' + threshold); 1247 1248 // short circuit if result is strictly within the normal value error bounds. 1249 // This improves performance significantly. 1250 if (es3fShaderDerivateTests.verifyConstantDerivate(compareArea, maskArea, this.m_dataType, 1251 reference, threshold, this.m_derivScale, this.m_derivBias, 1252 es3fShaderDerivateTests.VerificationLogging.LOG_NOTHING)) { 1253 bufferedLogToConsole('No incorrect derivatives found, result valid.'); 1254 return true; 1255 } 1256 // some pixels exceed error bounds calculated for normal values. Verify that these 1257 // potentially invalid pixels are in fact valid due to (for example) subnorm flushing. 1258 1259 bufferedLogToConsole('Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n' + 1260 '\tVerifying each result derivative is within its range of legal result values.'); 1261 1262 /** @type {Array<number>} */ var valueRamp = deMath.subtract(this.m_texValueMax, this.m_texValueMin); 1263 /** @type {es3fShaderDerivateTests.Linear2DFunctionEvaluator} */ var function_ = new es3fShaderDerivateTests.Linear2DFunctionEvaluator(); 1264 1265 function_.matrix.setRow(0, [valueRamp[0] / w, 0.0, this.m_texValueMin[0]]); 1266 function_.matrix.setRow(1, [0.0, valueRamp[1] / h, this.m_texValueMin[1]]); 1267 function_.matrix.setRow(2, deMath.scale([valueRamp[2] / w, valueRamp[2] / h, this.m_texValueMin[2] + this.m_texValueMin[2]], 1 / 2.0)); 1268 function_.matrix.setRow(3, deMath.scale([-valueRamp[3] / w, -valueRamp[3] / h, this.m_texValueMax[3] + this.m_texValueMax[3]], 1 / 2.0)); 1269 1270 return es3fShaderDerivateTests.reverifyConstantDerivateWithFlushRelaxations(compareArea, maskArea, this.m_dataType, this.m_precision, 1271 this.m_derivScale, this.m_derivBias, surfaceThreshold, this.m_func, function_); 1272 } else { 1273 assertMsgOptions(this.m_func == es3fShaderDerivateTests.DerivateFunc.FWIDTH, 'Expected Derivate Function FWIDTH', false, true); 1274 /** @type {Array<number>} */ var dx = deMath.multiply(deMath.scale(deMath.subtract(this.m_texValueMax, this.m_texValueMin), 1 / w), xScale); 1275 /** @type {Array<number>} */ var dy = deMath.multiply(deMath.scale(deMath.subtract(this.m_texValueMax, this.m_texValueMin), 1 / h), yScale); 1276 reference = deMath.add(deMath.abs(dx), deMath.abs(dy)); 1277 /** @type {Array<number>} */ var dxThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_texValueMin, xScale), deMath.multiply(this.m_texValueMax, xScale), dx); 1278 /** @type {Array<number>} */ var dyThreshold = es3fShaderDerivateTests.getDerivateThreshold(this.m_precision, deMath.multiply(this.m_texValueMin, yScale), deMath.multiply(this.m_texValueMax, yScale), dy); 1279 threshold = deMath.max(surfaceThreshold, deMath.max(dxThreshold, dyThreshold)); 1280 1281 return es3fShaderDerivateTests.verifyConstantDerivate(compareArea, maskArea, this.m_dataType, 1282 reference, threshold, this.m_derivScale, this.m_derivBias); 1283 }; 1284 }; 1285 1286 /** 1287 * @constructor 1288 * @extends {tcuTestCase.DeqpTest} 1289 */ 1290 es3fShaderDerivateTests.ShaderDerivateTests = function() { 1291 tcuTestCase.DeqpTest.call(this, 'derivate', 'Derivate Function Tests'); 1292 }; 1293 1294 es3fShaderDerivateTests.ShaderDerivateTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 1295 es3fShaderDerivateTests.ShaderDerivateTests.prototype.constructor = es3fShaderDerivateTests.ShaderDerivateTests 1296 1297 /** 1298 * @struct 1299 * @constructor 1300 * @param {string} name 1301 * @param {es3fShaderDerivateTests.DerivateFunc} func 1302 * @param {gluShaderUtil.DataType} dataType_ 1303 * @param {gluShaderUtil.precision} precision_ 1304 */ 1305 es3fShaderDerivateTests.FunctionSpec = function(name, func, dataType_, precision_) { 1306 this.name = name; 1307 this.function_ = func; 1308 this.dataType = dataType_; 1309 this.precision = precision_; 1310 }; 1311 1312 es3fShaderDerivateTests.ShaderDerivateTests.prototype.init = function() { 1313 var testGroup = tcuTestCase.runner.testCases; 1314 /** 1315 * @struct 1316 * @constructor 1317 * @param {string} name 1318 * @param {string} description 1319 * @param {string} source 1320 */ 1321 var LinearDerivateCase = function(name, description, source) { 1322 /** @type {string} */ this.name = name; 1323 /** @type {string} */ this.description = description; 1324 /** @type {string} */ this.source = source; 1325 }; 1326 1327 /** @type {Array<LinearDerivateCase>} */ 1328 var s_linearDerivateCases = [ 1329 new LinearDerivateCase( 1330 'linear', 1331 'Basic derivate of linearly interpolated argument', 1332 '#version 300 es\n' + 1333 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1334 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1335 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1336 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1337 'void main (void)\n' + 1338 '{\n' + 1339 ' ${PRECISION} ${DATATYPE} res = ${FUNC}(v_coord) * u_scale + u_bias;\n' + 1340 ' o_color = ${CAST_TO_OUTPUT};\n' + 1341 '}\n'), 1342 new LinearDerivateCase( 1343 'in_function', 1344 'Derivate of linear function argument', 1345 '#version 300 es\n' + 1346 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1347 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1348 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1349 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1350 '\n' + 1351 '${PRECISION} ${DATATYPE} computeRes (${PRECISION} ${DATATYPE} value)\n' + 1352 '{\n' + 1353 ' return ${FUNC}(v_coord) * u_scale + u_bias;\n' + 1354 '}\n' + 1355 '\n' + 1356 'void main (void)\n' + 1357 '{\n' + 1358 ' ${PRECISION} ${DATATYPE} res = computeRes(v_coord);\n' + 1359 ' o_color = ${CAST_TO_OUTPUT};\n' + 1360 '}\n'), 1361 new LinearDerivateCase( 1362 'static_if', 1363 'Derivate of linearly interpolated value in static if', 1364 '#version 300 es\n' + 1365 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1366 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1367 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1368 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1369 'void main (void)\n' + 1370 '{\n' + 1371 ' ${PRECISION} ${DATATYPE} res;\n' + 1372 ' if (false)\n' + 1373 ' res = ${FUNC}(-v_coord) * u_scale + u_bias;\n' + 1374 ' else\n' + 1375 ' res = ${FUNC}(v_coord) * u_scale + u_bias;\n' + 1376 ' o_color = ${CAST_TO_OUTPUT};\n' + 1377 '}\n'), 1378 new LinearDerivateCase( 1379 'static_loop', 1380 'Derivate of linearly interpolated value in static loop', 1381 '#version 300 es\n' + 1382 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1383 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1384 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1385 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1386 'void main (void)\n' + 1387 '{\n' + 1388 ' ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n' + 1389 ' for (int i = 0; i < 2; i++)\n' + 1390 ' res += ${FUNC}(v_coord * float(i));\n' + 1391 ' res = res * u_scale + u_bias;\n' + 1392 ' o_color = ${CAST_TO_OUTPUT};\n' + 1393 '}\n'), 1394 new LinearDerivateCase( 1395 'static_switch', 1396 'Derivate of linearly interpolated value in static switch', 1397 '#version 300 es\n' + 1398 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1399 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1400 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1401 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1402 'void main (void)\n' + 1403 '{\n' + 1404 ' ${PRECISION} ${DATATYPE} res;\n' + 1405 ' switch (1)\n' + 1406 ' {\n' + 1407 ' case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias; break;\n' + 1408 ' case 1: res = ${FUNC}(v_coord) * u_scale + u_bias; break;\n' + 1409 ' }\n' + 1410 ' o_color = ${CAST_TO_OUTPUT};\n' + 1411 '}\n'), 1412 new LinearDerivateCase( 1413 'uniform_if', 1414 'Derivate of linearly interpolated value in uniform if', 1415 '#version 300 es\n' + 1416 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1417 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1418 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1419 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1420 'uniform bool ub_true;\n' + 1421 'void main (void)\n' + 1422 '{\n' + 1423 ' ${PRECISION} ${DATATYPE} res;\n' + 1424 ' if (ub_true)\n' + 1425 ' res = ${FUNC}(v_coord) * u_scale + u_bias;\n' + 1426 ' else\n' + 1427 ' res = ${FUNC}(-v_coord) * u_scale + u_bias;\n' + 1428 ' o_color = ${CAST_TO_OUTPUT};\n' + 1429 '}\n'), 1430 new LinearDerivateCase( 1431 'uniform_loop', 1432 'Derivate of linearly interpolated value in uniform loop', 1433 '#version 300 es\n' + 1434 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1435 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1436 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1437 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1438 'uniform int ui_two;\n' + 1439 'void main (void)\n' + 1440 '{\n' + 1441 ' ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n' + 1442 ' for (int i = 0; i < ui_two; i++)\n' + 1443 ' res += ${FUNC}(v_coord * float(i));\n' + 1444 ' res = res * u_scale + u_bias;\n' + 1445 ' o_color = ${CAST_TO_OUTPUT};\n' + 1446 '}\n'), 1447 new LinearDerivateCase( 1448 'uniform_switch', 1449 'Derivate of linearly interpolated value in uniform switch', 1450 '#version 300 es\n' + 1451 'in ${PRECISION} ${DATATYPE} v_coord;\n' + 1452 'layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n' + 1453 'uniform ${PRECISION} ${DATATYPE} u_scale;\n' + 1454 'uniform ${PRECISION} ${DATATYPE} u_bias;\n' + 1455 'uniform int ui_one;\n' + 1456 'void main (void)\n' + 1457 '{\n' + 1458 ' ${PRECISION} ${DATATYPE} res;\n' + 1459 ' switch (ui_one)\n' + 1460 ' {\n' + 1461 ' case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias; break;\n' + 1462 ' case 1: res = ${FUNC}(v_coord) * u_scale + u_bias; break;\n' + 1463 ' }\n' + 1464 ' o_color = ${CAST_TO_OUTPUT};\n' + 1465 '}\n') 1466 ]; 1467 1468 /** 1469 * @struct 1470 * @constructor 1471 * @param {string} name 1472 * @param {es3fShaderDerivateTests.SurfaceType} surfaceType 1473 * @param {number} numSamples 1474 */ 1475 var FboConfig = function(name, surfaceType, numSamples) { 1476 /** @type {string} */ this.name = name; 1477 /** @type {es3fShaderDerivateTests.SurfaceType} */ this.surfaceType = surfaceType; 1478 /** @type {number} */ this.numSamples = numSamples; 1479 }; 1480 1481 /** @type {Array<FboConfig>} */ var s_fboConfigs = [ 1482 new FboConfig('fbo', es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER, 0), 1483 new FboConfig('fbo_msaa2', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 2), 1484 new FboConfig('fbo_msaa4', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 4), 1485 new FboConfig('fbo_float', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0) 1486 ]; 1487 1488 /** 1489 * @struct 1490 * @constructor 1491 * @param {string} name 1492 * @param {number} hint 1493 */ 1494 var Hint = function(name, hint) { 1495 /** @type {string} */ this.name = name; 1496 /** @type {number} */ this.hint = hint; 1497 }; 1498 1499 /** @type {Array<Hint>} */ var s_hints = [ 1500 new Hint('fastest', gl.FASTEST), 1501 new Hint('nicest', gl.NICEST) 1502 ]; 1503 1504 /** 1505 * @struct 1506 * @constructor 1507 * @param {string} name 1508 * @param {es3fShaderDerivateTests.SurfaceType} surfaceType 1509 * @param {number} numSamples 1510 */ 1511 var HintFboConfig = function(name, surfaceType, numSamples) { 1512 /** @type {string} */ this.name = name; 1513 /** @type {es3fShaderDerivateTests.SurfaceType} */ this.surfaceType = surfaceType; 1514 /** @type {number} */ this.numSamples = numSamples; 1515 }; 1516 1517 /** @type {Array<HintFboConfig>} */ var s_hintFboConfigs = [ 1518 new HintFboConfig('default', es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER, 0), 1519 new HintFboConfig('fbo_msaa4', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 4), 1520 new HintFboConfig('fbo_float', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0) 1521 ]; 1522 1523 /** 1524 * @struct 1525 * @constructor 1526 * @param {string} name 1527 * @param {es3fShaderDerivateTests.SurfaceType} surfaceType 1528 * @param {number} numSamples 1529 * @param {number} hint 1530 */ 1531 var TextureConfig = function(name, surfaceType, numSamples, hint) { 1532 /** @type {string} */ this.name = name; 1533 /** @type {es3fShaderDerivateTests.SurfaceType} */ this.surfaceType = surfaceType; 1534 /** @type {number} */ this.numSamples = numSamples; 1535 /** @type {number} */ this.hint = hint; 1536 }; 1537 1538 /** @type {Array<TextureConfig>} */ var s_textureConfigs = [ 1539 new TextureConfig('basic', es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER, 0, gl.DONT_CARE), 1540 new TextureConfig('msaa4', es3fShaderDerivateTests.SurfaceType.UNORM_FBO, 4, gl.DONT_CARE), 1541 new TextureConfig('float_fastest', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0, gl.FASTEST), 1542 new TextureConfig('float_nicest', es3fShaderDerivateTests.SurfaceType.FLOAT_FBO, 0, gl.NICEST) 1543 ]; 1544 1545 /** @type {gluShaderUtil.DataType} */ var dataType; 1546 /** @type {string} */ var source; 1547 /** @type {gluShaderUtil.precision} */ var precision; 1548 /** @type {es3fShaderDerivateTests.SurfaceType} */ var surfaceType; 1549 /** @type {number} */ var numSamples; 1550 /** @type {number} */ var hint; 1551 /** @type {string} */ var caseName; 1552 /** @type {tcuTestCase.DeqpTest} */ var fboGroup; 1553 1554 // .dfdx, .dfdy, .fwidth 1555 for (var funcNdx in es3fShaderDerivateTests.DerivateFunc) { 1556 /** @type {es3fShaderDerivateTests.DerivateFunc} */ var function_ = es3fShaderDerivateTests.DerivateFunc[funcNdx]; 1557 /** @type {tcuTestCase.DeqpTest} */ var functionGroup = tcuTestCase.newTest(es3fShaderDerivateTests.getDerivateFuncCaseName(function_), es3fShaderDerivateTests.getDerivateFuncName(function_)); 1558 testGroup.addChild(functionGroup); 1559 1560 // .constant - no precision variants, checks that derivate of constant arguments is 0 1561 /** @type {tcuTestCase.DeqpTest} */ var constantGroup = tcuTestCase.newTest('constant', 'Derivate of constant argument'); 1562 functionGroup.addChild(constantGroup); 1563 1564 for (var vecSize = 1; vecSize <= 4; vecSize++) { 1565 dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT; 1566 constantGroup.addChild(new es3fShaderDerivateTests.ConstantDerivateCase(gluShaderUtil.getDataTypeName(dataType), '', function_, dataType)); 1567 } 1568 1569 // Cases based on LinearDerivateCase 1570 for (var caseNdx = 0; caseNdx < s_linearDerivateCases.length; caseNdx++) { 1571 /** @type {tcuTestCase.DeqpTest} */ var linearCaseGroup = tcuTestCase.newTest(s_linearDerivateCases[caseNdx].name, s_linearDerivateCases[caseNdx].description); 1572 source = s_linearDerivateCases[caseNdx].source; 1573 functionGroup.addChild(linearCaseGroup); 1574 1575 for (var vecSize = 1; vecSize <= 4; vecSize++) 1576 for (var precNdx in gluShaderUtil.precision) { 1577 dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT; 1578 precision = gluShaderUtil.precision[precNdx]; 1579 surfaceType = es3fShaderDerivateTests.SurfaceType.DEFAULT_FRAMEBUFFER; 1580 numSamples = 0; 1581 hint = gl.DONT_CARE; 1582 1583 if (caseNdx !== 0 && precision === gluShaderUtil.precision.PRECISION_LOWP) 1584 continue; // Skip as lowp doesn't actually produce any bits when rendered to default FB. 1585 1586 caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision); 1587 1588 linearCaseGroup.addChild(new es3fShaderDerivateTests.LinearDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples, source)); 1589 } 1590 } 1591 1592 // Fbo cases 1593 for (var caseNdx = 0; caseNdx < s_fboConfigs.length; caseNdx++) { 1594 fboGroup = tcuTestCase.newTest(s_fboConfigs[caseNdx].name, 'Derivate usage when rendering into FBO'); 1595 source = s_linearDerivateCases[0].source; // use source from .linear group 1596 surfaceType = s_fboConfigs[caseNdx].surfaceType; 1597 numSamples = s_fboConfigs[caseNdx].numSamples; 1598 functionGroup.addChild(fboGroup); 1599 1600 for (var vecSize = 1; vecSize <= 4; vecSize++) 1601 for (var precNdx in gluShaderUtil.precision) { 1602 dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT; 1603 precision = gluShaderUtil.precision[precNdx]; 1604 hint = gl.DONT_CARE; 1605 1606 if (surfaceType !== es3fShaderDerivateTests.SurfaceType.FLOAT_FBO && precision === gluShaderUtil.precision.PRECISION_LOWP) 1607 continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT. 1608 1609 caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision); 1610 1611 fboGroup.addChild(new es3fShaderDerivateTests.LinearDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples, source)); 1612 } 1613 } 1614 1615 // .fastest, .nicest 1616 for (var hintCaseNdx = 0; hintCaseNdx < s_hints.length; hintCaseNdx++) { 1617 /** @type {tcuTestCase.DeqpTest} */ var hintGroup = tcuTestCase.newTest(s_hints[hintCaseNdx].name, 'Shader derivate hints'); 1618 source = s_linearDerivateCases[0].source; // use source from .linear group 1619 hint = s_hints[hintCaseNdx].hint; 1620 functionGroup.addChild(hintGroup); 1621 1622 for (var fboCaseNdx = 0; fboCaseNdx < s_hintFboConfigs.length; fboCaseNdx++) { 1623 fboGroup = tcuTestCase.newTest(s_hintFboConfigs[fboCaseNdx].name, ''); 1624 surfaceType = s_hintFboConfigs[fboCaseNdx].surfaceType; 1625 numSamples = s_hintFboConfigs[fboCaseNdx].numSamples; 1626 hintGroup.addChild(fboGroup); 1627 1628 for (var vecSize = 1; vecSize <= 4; vecSize++) 1629 for (var precNdx in gluShaderUtil.precision) { 1630 dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT; 1631 precision = gluShaderUtil.precision[precNdx]; 1632 1633 if (surfaceType !== es3fShaderDerivateTests.SurfaceType.FLOAT_FBO && precision === gluShaderUtil.precision.PRECISION_LOWP) 1634 continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT. 1635 1636 caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision); 1637 1638 fboGroup.addChild(new es3fShaderDerivateTests.LinearDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples, source)); 1639 } 1640 } 1641 } 1642 1643 // .texture 1644 /** @type {tcuTestCase.DeqpTest} */ var textureGroup = tcuTestCase.newTest('texture', 'Derivate of texture lookup result'); 1645 functionGroup.addChild(textureGroup); 1646 1647 for (var texCaseNdx = 0; texCaseNdx < s_textureConfigs.length; texCaseNdx++) { 1648 /** @type {tcuTestCase.DeqpTest} */ var caseGroup = tcuTestCase.newTest(s_textureConfigs[texCaseNdx].name, ''); 1649 surfaceType = s_textureConfigs[texCaseNdx].surfaceType; 1650 numSamples = s_textureConfigs[texCaseNdx].numSamples; 1651 hint = s_textureConfigs[texCaseNdx].hint; 1652 textureGroup.addChild(caseGroup); 1653 1654 for (var vecSize = 1; vecSize <= 4; vecSize++) 1655 for (var precNdx in gluShaderUtil.precision) { 1656 dataType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT; 1657 precision = gluShaderUtil.precision[precNdx]; 1658 1659 if (surfaceType !== es3fShaderDerivateTests.SurfaceType.FLOAT_FBO && precision === gluShaderUtil.precision.PRECISION_LOWP) 1660 continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT. 1661 1662 caseName = gluShaderUtil.getDataTypeName(dataType) + '_' + gluShaderUtil.getPrecisionName(precision); 1663 1664 caseGroup.addChild(new es3fShaderDerivateTests.TextureDerivateCase(caseName, '', function_, dataType, precision, hint, surfaceType, numSamples)); 1665 } 1666 } 1667 } 1668 }; 1669 1670 /** 1671 * Run test 1672 * @param {WebGL2RenderingContext} context 1673 */ 1674 es3fShaderDerivateTests.run = function(context, range) { 1675 gl = context; 1676 //Set up Test Root parameters 1677 var state = tcuTestCase.runner; 1678 state.setRoot(new es3fShaderDerivateTests.ShaderDerivateTests()); 1679 1680 //Set up name and description of this test series. 1681 setCurrentTestName(state.testCases.fullName()); 1682 description(state.testCases.getDescription()); 1683 1684 try { 1685 if (range) 1686 state.setRange(range); 1687 //Run test cases 1688 tcuTestCase.runTestCases(); 1689 } 1690 catch (err) { 1691 testFailedOptions('Failed to es3fShaderDerivateTests.run tests', false); 1692 tcuTestCase.runner.terminate(); 1693 } 1694 }; 1695 1696 });