tcuTexCompareVerifier.js (64603B)
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('framework.common.tcuTexCompareVerifier'); 23 goog.require('framework.common.tcuTexVerifierUtil'); 24 goog.require('framework.common.tcuTexture'); 25 goog.require('framework.common.tcuTextureUtil'); 26 goog.require('framework.delibs.debase.deMath'); 27 28 goog.scope(function() { 29 30 var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier; 31 var tcuTexture = framework.common.tcuTexture; 32 var deMath = framework.delibs.debase.deMath; 33 var tcuTextureUtil = framework.common.tcuTextureUtil; 34 var tcuTexVerifierUtil = framework.common.tcuTexVerifierUtil; 35 36 /** 37 * \brief Texture compare (shadow) lookup precision parameters. 38 * @constructor 39 * @struct 40 * @param {Array<number>=} coordBits 41 * @param {Array<number>=} uvwBits 42 * @param {number=} pcfBits 43 * @param {number=} referenceBits 44 * @param {number=} resultBits 45 */ 46 tcuTexCompareVerifier.TexComparePrecision = function(coordBits, uvwBits, pcfBits, referenceBits, resultBits) { 47 this.coordBits = coordBits === undefined ? [22, 22, 22] : coordBits; 48 this.uvwBits = uvwBits === undefined ? [22, 22, 22] : uvwBits; 49 this.pcfBits = pcfBits === undefined ? 16 : pcfBits; 50 this.referenceBits = referenceBits === undefined ? 16 : referenceBits; 51 this.resultBits = resultBits === undefined ? 16 : resultBits; 52 }; 53 54 /** 55 * @constructor 56 * @struct 57 */ 58 tcuTexCompareVerifier.CmpResultSet = function() { 59 this.isTrue = false; 60 this.isFalse = false; 61 }; 62 63 /** 64 * @param {tcuTexture.CompareMode} compareMode 65 * @param {number} cmpValue_ 66 * @param {number} cmpReference_ 67 * @param {number} referenceBits 68 * @param {boolean} isFixedPoint 69 * @return {tcuTexCompareVerifier.CmpResultSet} 70 */ 71 tcuTexCompareVerifier.execCompare = function(compareMode, 72 cmpValue_, 73 cmpReference_, 74 referenceBits, 75 isFixedPoint) { 76 var clampValues = isFixedPoint; // if comparing against a floating point texture, ref (and value) is not clamped 77 var cmpValue = (clampValues) ? (deMath.clamp(cmpValue_, 0, 1)) : (cmpValue_); 78 var cmpReference = (clampValues) ? (deMath.clamp(cmpReference_, 0, 1)) : (cmpReference_); 79 var err = tcuTexVerifierUtil.computeFixedPointError(referenceBits); 80 var res = new tcuTexCompareVerifier.CmpResultSet(); 81 82 switch (compareMode) { 83 case tcuTexture.CompareMode.COMPAREMODE_LESS: 84 res.isTrue = cmpReference - err < cmpValue; 85 res.isFalse = cmpReference + err >= cmpValue; 86 break; 87 88 case tcuTexture.CompareMode.COMPAREMODE_LESS_OR_EQUAL: 89 res.isTrue = cmpReference - err <= cmpValue; 90 res.isFalse = cmpReference + err > cmpValue; 91 break; 92 93 case tcuTexture.CompareMode.COMPAREMODE_GREATER: 94 res.isTrue = cmpReference + err > cmpValue; 95 res.isFalse = cmpReference - err <= cmpValue; 96 break; 97 98 case tcuTexture.CompareMode.COMPAREMODE_GREATER_OR_EQUAL: 99 res.isTrue = cmpReference + err >= cmpValue; 100 res.isFalse = cmpReference - err < cmpValue; 101 break; 102 103 case tcuTexture.CompareMode.COMPAREMODE_EQUAL: 104 res.isTrue = deMath.deInRange32(cmpValue, cmpReference - err, cmpReference + err); 105 res.isFalse = err != 0 || cmpValue != cmpReference; 106 break; 107 108 case tcuTexture.CompareMode.COMPAREMODE_NOT_EQUAL: 109 res.isTrue = err != 0 || cmpValue != cmpReference; 110 res.isFalse = deMath.deInRange32(cmpValue, cmpReference - err, cmpReference + err); 111 break; 112 113 case tcuTexture.CompareMode.COMPAREMODE_ALWAYS: 114 res.isTrue = true; 115 break; 116 117 case tcuTexture.CompareMode.COMPAREMODE_NEVER: 118 res.isFalse = true; 119 break; 120 121 default: 122 throw new Error('Invalid compare mode:' + compareMode); 123 } 124 125 assertMsgOptions(res.isTrue || res.isFalse, 'Both tests failed!', false, true); 126 return res; 127 }; 128 129 /** 130 * @param {tcuTexture.TextureFormat} format 131 * @return {boolean} 132 */ 133 tcuTexCompareVerifier.isFixedPointDepthTextureFormat = function(format) { 134 var channelClass = tcuTexture.getTextureChannelClass(format.type); 135 136 if (format.order == tcuTexture.ChannelOrder.D) { 137 // depth internal formats cannot be non-normalized integers 138 return channelClass != tcuTexture.TextureChannelClass.FLOATING_POINT; 139 } else if (format.order == tcuTexture.ChannelOrder.DS) { 140 // combined formats have no single channel class, detect format manually 141 switch (format.type) { 142 case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return false; 143 case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return true; 144 145 default: 146 throw new Error('Invalid texture format: ' + format); 147 } 148 } 149 150 return false; 151 }; 152 153 /** 154 * @param {tcuTexture.CompareMode} compareMode 155 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 156 * @param {Array<number>} depths 157 * @param {Array<number>} fBounds 158 * @param {number} cmpReference 159 * @param {number} result 160 * @param {boolean} isFixedPointDepth 161 * @return {boolean} 162 */ 163 tcuTexCompareVerifier.isLinearCompareValid = function(compareMode, prec, depths, fBounds, cmpReference, result, isFixedPointDepth) { 164 assertMsgOptions(fBounds[0] >= 0 && fBounds[0] <= fBounds[1] && fBounds[1] <= 1, 'Invalid fBounds', false, true); 165 166 var d0 = depths[0]; 167 var d1 = depths[1]; 168 169 var cmp0 = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth); 170 var cmp1 = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth); 171 var cmp = [cmp0, cmp1]; 172 173 var isTrue = getMask(cmp, function(x) {return x.isTrue;}); 174 var isFalse = getMask(cmp, function(x) {return x.isFalse;}); 175 176 var f0 = fBounds[0]; 177 var f1 = fBounds[1]; 178 179 var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits); 180 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits); 181 var totalErr = pcfErr + resErr; 182 183 for (var comb = 0; comb < 4; comb++) { 184 if (((comb & isTrue) | (~comb & isFalse )) != 3) 185 continue; 186 187 var cmp0True = ((comb >> 0) & 1) != 0; 188 var cmp1True = ((comb >> 1) & 1) != 0; 189 190 var ref0 = cmp0True ? 1 : 0; 191 var ref1 = cmp1True ? 1 : 0; 192 193 var v0 = ref0 * (1 - f0) + ref1 * f0; 194 var v1 = ref0 * (1 - f1) + ref1 * f1; 195 var minV = Math.min(v0, v1); 196 var maxV = Math.max(v0, v1); 197 var minR = minV - totalErr; 198 var maxR = maxV + totalErr; 199 200 if (deMath.deInRange32(result, minR, maxR)) 201 return true; 202 } 203 return false; 204 }; 205 206 /** 207 * @param {number} val 208 * @param {number} offset 209 * @return {Array<boolean>} 210 */ 211 tcuTexCompareVerifier.extractBVec4 = function(val, offset) { 212 return [ 213 ((val >> (offset + 0)) & 1) != 0, 214 ((val >> (offset + 1)) & 1) != 0, 215 ((val >> (offset + 2)) & 1) != 0, 216 ((val >> (offset + 3)) & 1) != 0]; 217 }; 218 219 /** 220 * Values are in order (0,0), (1,0), (0,1), (1,1) 221 * @param {Array<number>} values 222 * @param {number} x 223 * @param {number} y 224 * @return {number} 225 */ 226 tcuTexCompareVerifier.bilinearInterpolate = function(values, x, y) { 227 var v00 = values[0]; 228 var v10 = values[1]; 229 var v01 = values[2]; 230 var v11 = values[3]; 231 var res = v00 * (1 - x) * (1 - y) + v10 * x * (1 - y) + v01 * (1 - x) * y + v11 * x * y; 232 return res; 233 }; 234 235 /** 236 * @param {tcuTexture.CompareMode} compareMode 237 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 238 * @param {Array<number>} depths vec4 239 * @param {number} cmpReference 240 * @param {number} result 241 * @param {boolean} isFixedPointDepth 242 * @return {boolean} 243 */ 244 tcuTexCompareVerifier.isBilinearAnyCompareValid = function(compareMode, 245 prec, 246 depths, 247 cmpReference, 248 result, 249 isFixedPointDepth) { 250 assertMsgOptions(prec.pcfBits === 0, 'PCF bits must be 0', false, true); 251 252 var d0 = depths[0]; 253 var d1 = depths[1]; 254 var d2 = depths[2]; 255 var d3 = depths[3]; 256 257 var cmp0 = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth); 258 var cmp1 = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth); 259 var cmp2 = tcuTexCompareVerifier.execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth); 260 var cmp3 = tcuTexCompareVerifier.execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth); 261 262 var canBeTrue = cmp0.isTrue || cmp1.isTrue || cmp2.isTrue || cmp3.isTrue; 263 var canBeFalse = cmp0.isFalse || cmp1.isFalse || cmp2.isFalse || cmp3.isFalse; 264 265 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits); 266 267 var minBound = canBeFalse ? 0 : 1; 268 var maxBound = canBeTrue ? 1 : 0; 269 270 return deMath.deInRange32(result, minBound - resErr, maxBound + resErr); 271 }; 272 273 /** 274 * @param {Array<tcuTexCompareVerifier.CmpResultSet>} arr 275 * @param {function(tcuTexCompareVerifier.CmpResultSet): boolean} getValue 276 * @return {number} 277 */ 278 var getMask = function(arr, getValue) { 279 var mask = 0; 280 for (var i = 0; i < arr.length; i++) { 281 var val = getValue(arr[i]); 282 if (val) 283 mask |= 1 << i; 284 } 285 return mask; 286 }; 287 288 /** 289 * @param {tcuTexture.CompareMode} compareMode 290 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 291 * @param {Array<number>} depths vec4 292 * @param {Array<number>} xBounds vec2 293 * @param {Array<number>} yBounds vec2 294 * @param {number} cmpReference 295 * @param {number} result 296 * @param {boolean} isFixedPointDepth 297 * @return {boolean} 298 */ 299 tcuTexCompareVerifier.isBilinearPCFCompareValid = function(compareMode, 300 prec, 301 depths, 302 xBounds, 303 yBounds, 304 cmpReference, 305 result, 306 isFixedPointDepth) { 307 assertMsgOptions(0.0 <= xBounds[0] && xBounds[0] <= xBounds[1] && xBounds[1] <= 1.0, 'x coordinate out of bounds', false, true); 308 assertMsgOptions(0.0 <= yBounds[0] && yBounds[0] <= yBounds[1] && yBounds[1] <= 1.0, 'y coordinate out of bounds', false, true); 309 assertMsgOptions(prec.pcfBits > 0, 'PCF bits must be > 0', false, true); 310 311 var d0 = depths[0]; 312 var d1 = depths[1]; 313 var d2 = depths[2]; 314 var d3 = depths[3]; 315 316 /** @type {Array<tcuTexCompareVerifier.CmpResultSet>} */ var cmp = []; 317 cmp[0] = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth); 318 cmp[1] = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth); 319 cmp[2] = tcuTexCompareVerifier.execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth); 320 cmp[3] = tcuTexCompareVerifier.execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth); 321 322 var isTrue = getMask(cmp, function(x) {return x.isTrue}); 323 var isFalse = getMask(cmp, function(x) {return x.isFalse}); 324 325 // Interpolation parameters 326 var x0 = xBounds[0]; 327 var x1 = xBounds[1]; 328 var y0 = yBounds[0]; 329 var y1 = yBounds[1]; 330 331 // Error parameters 332 var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits); 333 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits); 334 var totalErr = pcfErr + resErr; 335 336 // Iterate over all valid combinations. 337 // \note It is not enough to compute minmax over all possible result sets, as ranges may 338 // not necessarily overlap, i.e. there are gaps between valid ranges. 339 for (var comb = 0; comb < (1 << 4); comb++) { 340 // Filter out invalid combinations: 341 // 1) True bit is set in comb but not in isTrue => sample can not be true 342 // 2) True bit is NOT set in comb and not in isFalse => sample can not be false 343 if (((comb & isTrue) | (~comb & isFalse)) != (1 << 4) - 1) 344 continue; 345 346 var cmpTrue = tcuTexCompareVerifier.extractBVec4(comb, 0); 347 var refVal = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue); 348 349 var v0 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x0, y0); 350 var v1 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x1, y0); 351 var v2 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x0, y1); 352 var v3 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x1, y1); 353 var minV = Math.min(v0, v1, v2, v3); 354 var maxV = Math.max(v0, v1, v2, v3); 355 var minR = minV - totalErr; 356 var maxR = maxV + totalErr; 357 358 if (deMath.deInRange32(result, minR, maxR)) 359 return true; 360 } 361 362 return false; 363 }; 364 365 /** 366 * @param {tcuTexture.CompareMode} compareMode 367 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 368 * @param {Array<number>} depths vec4 369 * @param {Array<number>} xBounds vec2 370 * @param {Array<number>} yBounds vec2 371 * @param {number} cmpReference 372 * @param {number} result 373 * @param {boolean} isFixedPointDepth 374 * @return {boolean} 375 */ 376 tcuTexCompareVerifier.isBilinearCompareValid = function(compareMode, 377 prec, 378 depths, 379 xBounds, 380 yBounds, 381 cmpReference, 382 result, 383 isFixedPointDepth) { 384 if (prec.pcfBits > 0) 385 return tcuTexCompareVerifier.isBilinearPCFCompareValid(compareMode, prec, depths, xBounds, yBounds, cmpReference, result, isFixedPointDepth); 386 else 387 return tcuTexCompareVerifier.isBilinearAnyCompareValid(compareMode, prec, depths, cmpReference, result, isFixedPointDepth); 388 }; 389 /** 390 * @param {tcuTexture.ConstPixelBufferAccess} level 391 * @param {tcuTexture.Sampler} sampler 392 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 393 * @param {Array<number>} coord vec2 texture coordinates 394 * @param {number} coordZ 395 * @param {number} cmpReference 396 * @param {number} result 397 * @return {boolean} 398 */ 399 tcuTexCompareVerifier.isLinearCompareResultValid = function(level, 400 sampler, 401 prec, 402 coord, 403 coordZ, 404 cmpReference, 405 result) { 406 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level.getFormat()); 407 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]); 408 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]); 409 410 // Integer coordinate bounds for (x0,y0) - without wrap mode 411 var minI = Math.floor(uBounds[0] - 0.5); 412 var maxI = Math.floor(uBounds[1] - 0.5); 413 var minJ = Math.floor(vBounds[0] - 0.5); 414 var maxJ = Math.floor(vBounds[1] - 0.5); 415 416 var w = level.getWidth(); 417 var h = level.getHeight(); 418 419 // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode. 420 421 for (var j = minJ; j <= maxJ; j++) { 422 for (var i = minI; i <= maxI; i++) { 423 // Wrapped coordinates 424 var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w); 425 var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w); 426 var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j, h); 427 var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j + 1, h); 428 429 // Bounds for filtering factors 430 var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1); 431 var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1); 432 var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1); 433 var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1); 434 435 var depths = [ 436 level.getPixDepth(x0, y0, coordZ), 437 level.getPixDepth(x1, y0, coordZ), 438 level.getPixDepth(x0, y1, coordZ), 439 level.getPixDepth(x1, y1, coordZ) 440 ]; 441 442 if (tcuTexCompareVerifier.isBilinearCompareValid(sampler.compare, prec, depths, [minA, maxA], [minB, maxB], cmpReference, result, isFixedPointDepth)) 443 return true; 444 } 445 } 446 447 return false; 448 }; 449 450 /** 451 * @param {tcuTexCompareVerifier.CmpResultSet} resultSet 452 * @param {number} result 453 * @param {number} resultBits 454 */ 455 tcuTexCompareVerifier.isResultInSet = function(resultSet, result, resultBits) { 456 var err = tcuTexVerifierUtil.computeFixedPointError(resultBits); 457 var minR = result - err; 458 var maxR = result + err; 459 460 return (resultSet.isTrue && deMath.deInRange32(1, minR, maxR)) || 461 (resultSet.isFalse && deMath.deInRange32(0, minR, maxR)); 462 }; 463 464 /** 465 * @param {tcuTexture.ConstPixelBufferAccess} level 466 * @param {tcuTexture.Sampler} sampler 467 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 468 * @param {Array<number>} coord vec2 texture coordinates 469 * @param {number} coordZ 470 * @param {number} cmpReference 471 * @param {number} result 472 * @return {boolean} 473 */ 474 tcuTexCompareVerifier.isNearestCompareResultValid = function(level, 475 sampler, 476 prec, 477 coord, 478 coordZ, 479 cmpReference, 480 result) { 481 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level.getFormat()); 482 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]); 483 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]); 484 485 // Integer coordinates - without wrap mode 486 var minI = Math.floor(uBounds[0]); 487 var maxI = Math.floor(uBounds[1]); 488 var minJ = Math.floor(vBounds[0]); 489 var maxJ = Math.floor(vBounds[1]); 490 491 for (var j = minJ; j <= maxJ; j++) { 492 for (var i = minI; i <= maxI; i++) { 493 var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth()); 494 var y = tcuTexVerifierUtil.wrap(sampler.wrapT, j, level.getHeight()); 495 var depth = level.getPixDepth(x, y, coordZ); 496 var resSet = tcuTexCompareVerifier.execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth); 497 498 if (tcuTexCompareVerifier.isResultInSet(resSet, result, prec.resultBits)) 499 return true; 500 } 501 } 502 503 return false; 504 }; 505 506 /** 507 * @param {tcuTexture.ConstPixelBufferAccess} level 508 * @param {tcuTexture.Sampler} sampler 509 * @param {tcuTexture.FilterMode} filterMode 510 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 511 * @param {Array<number>} coord vec2 texture coordinates 512 * @param {number} coordZ 513 * @param {number} cmpReference 514 * @param {number} result 515 * @return {boolean} 516 */ 517 tcuTexCompareVerifier.isLevelCompareResultValid = function(level, 518 sampler, 519 filterMode, 520 prec, 521 coord, 522 coordZ, 523 cmpReference, 524 result) { 525 if (filterMode == tcuTexture.FilterMode.LINEAR) 526 return tcuTexCompareVerifier.isLinearCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result); 527 else 528 return tcuTexCompareVerifier.isNearestCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result); 529 }; 530 531 /** 532 * @param {tcuTexture.CompareMode} compareMode 533 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 534 * @param {Array<number>} depths0 vec4 535 * @param {Array<number>} depths1 vec4 536 * @param {number} cmpReference 537 * @param {number} result 538 * @param {boolean} isFixedPointDepth 539 * @return {boolean} 540 */ 541 tcuTexCompareVerifier.isTrilinearAnyCompareValid = function(compareMode, 542 prec, 543 depths0, 544 depths1, 545 cmpReference, 546 result, 547 isFixedPointDepth) { 548 assertMsgOptions(prec.pcfBits === 0, 'PCF bits must be 0', false, true); 549 550 var cmp00 = tcuTexCompareVerifier.execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth); 551 var cmp01 = tcuTexCompareVerifier.execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth); 552 var cmp02 = tcuTexCompareVerifier.execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth); 553 var cmp03 = tcuTexCompareVerifier.execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth); 554 var cmp10 = tcuTexCompareVerifier.execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth); 555 var cmp11 = tcuTexCompareVerifier.execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth); 556 var cmp12 = tcuTexCompareVerifier.execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth); 557 var cmp13 = tcuTexCompareVerifier.execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth); 558 559 var canBeTrue = cmp00.isTrue || 560 cmp01.isTrue || 561 cmp02.isTrue || 562 cmp03.isTrue || 563 cmp10.isTrue || 564 cmp11.isTrue || 565 cmp12.isTrue || 566 cmp13.isTrue; 567 var canBeFalse = cmp00.isFalse || 568 cmp01.isFalse || 569 cmp02.isFalse || 570 cmp03.isFalse || 571 cmp10.isFalse || 572 cmp11.isFalse || 573 cmp12.isFalse || 574 cmp13.isFalse; 575 576 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits); 577 578 var minBound = canBeFalse ? 0 : 1; 579 var maxBound = canBeTrue ? 1 : 0; 580 581 return deMath.deInRange32(result, minBound - resErr, maxBound + resErr); 582 }; 583 584 /** 585 * @param {tcuTexture.CompareMode} compareMode 586 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 587 * @param {Array<number>} depths0 vec4 588 * @param {Array<number>} depths1 vec4 589 * @param {Array<number>} xBounds0 590 * @param {Array<number>} yBounds0 591 * @param {Array<number>} xBounds1 592 * @param {Array<number>} yBounds1 593 * @param {Array<number>} fBounds 594 * @param {number} cmpReference 595 * @param {number} result 596 * @param {boolean} isFixedPointDepth 597 * @return {boolean} 598 */ 599 tcuTexCompareVerifier.isTrilinearPCFCompareValid = function(compareMode, 600 prec, 601 depths0, 602 depths1, 603 xBounds0, 604 yBounds0, 605 xBounds1, 606 yBounds1, 607 fBounds, 608 cmpReference, 609 result, 610 isFixedPointDepth) { 611 assertMsgOptions(0.0 <= xBounds0[0] && xBounds0[0] <= xBounds0[1] && xBounds0[1] <= 1.0, 'x0 coordinate out of bounds', false, true); 612 assertMsgOptions(0.0 <= yBounds0[0] && yBounds0[0] <= yBounds0[1] && yBounds0[1] <= 1.0, 'y0 coordinate out of bounds', false, true); 613 assertMsgOptions(0.0 <= xBounds1[0] && xBounds1[0] <= xBounds1[1] && xBounds1[1] <= 1.0, 'x1 coordinate out of bounds', false, true); 614 assertMsgOptions(0.0 <= yBounds1[0] && yBounds1[0] <= yBounds1[1] && yBounds1[1] <= 1.0, 'y1 coordinate out of bounds', false, true); 615 assertMsgOptions(0.0 <= fBounds[0] && fBounds[0] <= fBounds[1] && fBounds[1] <= 1.0, 'linear factor out of bounds', false, true); 616 assertMsgOptions(prec.pcfBits > 0, 'PCF bits must be > 0', false, true); 617 618 /** @type {Array<tcuTexCompareVerifier.CmpResultSet>} */ var cmp = []; 619 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth)); 620 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth)); 621 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth)); 622 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth)); 623 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth)); 624 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth)); 625 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth)); 626 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth)); 627 628 var isTrue = getMask(cmp, function(x) {return x.isTrue}); 629 var isFalse = getMask(cmp, function(x) {return x.isFalse}); 630 631 // Error parameters 632 var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits); 633 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits); 634 var totalErr = pcfErr + resErr; 635 636 // Iterate over all valid combinations. 637 for (var comb = 0; comb < (1 << 8); comb++) { 638 // Filter out invalid combinations. 639 if (((comb & isTrue) | (~comb & isFalse)) != (1 << 8) - 1) 640 continue; 641 642 var cmpTrue0 = tcuTexCompareVerifier.extractBVec4(comb, 0); 643 var cmpTrue1 = tcuTexCompareVerifier.extractBVec4(comb, 4); 644 var refVal0 = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue0); 645 var refVal1 = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue1); 646 647 // Bilinear interpolation within levels. 648 var v00 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[0], yBounds0[0]); 649 var v01 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[1], yBounds0[0]); 650 var v02 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[0], yBounds0[1]); 651 var v03 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[1], yBounds0[1]); 652 var minV0 = Math.min(v00, v01, v02, v03); 653 var maxV0 = Math.max(v00, v01, v02, v03); 654 655 var v10 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[0], yBounds1[0]); 656 var v11 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[1], yBounds1[0]); 657 var v12 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[0], yBounds1[1]); 658 var v13 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[1], yBounds1[1]); 659 var minV1 = Math.min(v10, v11, v12, v13); 660 var maxV1 = Math.max(v10, v11, v12, v13); 661 662 // Compute min-max bounds by filtering between minimum bounds and maximum bounds between levels. 663 // HW can end up choosing pretty much any of samples between levels, and thus interpolating 664 // between minimums should yield lower bound for range, and same for upper bound. 665 // \todo [2013-07-17 pyry] This seems separable? Can this be optimized? At least ranges could be pre-computed and later combined. 666 var minF0 = minV0 * (1 - fBounds[0]) + minV1 * fBounds[0]; 667 var minF1 = minV0 * (1 - fBounds[1]) + minV1 * fBounds[1]; 668 var maxF0 = maxV0 * (1 - fBounds[0]) + maxV1 * fBounds[0]; 669 var maxF1 = maxV0 * (1 - fBounds[1]) + maxV1 * fBounds[1]; 670 671 var minF = Math.min(minF0, minF1); 672 var maxF = Math.max(maxF0, maxF1); 673 674 var minR = minF - totalErr; 675 var maxR = maxF + totalErr; 676 677 if (deMath.deInRange32(result, minR, maxR)) 678 return true; 679 } 680 681 return false; 682 683 }; 684 685 /** 686 * @param {tcuTexture.CompareMode} compareMode 687 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 688 * @param {Array<number>} depths0 vec4 689 * @param {Array<number>} depths1 vec4 690 * @param {Array<number>} xBounds0 691 * @param {Array<number>} yBounds0 692 * @param {Array<number>} xBounds1 693 * @param {Array<number>} yBounds1 694 * @param {Array<number>} fBounds 695 * @param {number} cmpReference 696 * @param {number} result 697 * @param {boolean} isFixedPointDepth 698 * @return {boolean} 699 */ 700 tcuTexCompareVerifier.isTrilinearCompareValid = function(compareMode, 701 prec, 702 depths0, 703 depths1, 704 xBounds0, 705 yBounds0, 706 xBounds1, 707 yBounds1, 708 fBounds, 709 cmpReference, 710 result, 711 isFixedPointDepth) { 712 if (prec.pcfBits > 0) 713 return tcuTexCompareVerifier.isTrilinearPCFCompareValid(compareMode, prec, depths0, depths1, xBounds0, yBounds0, xBounds1, yBounds1, fBounds, cmpReference, result, isFixedPointDepth); 714 else 715 return tcuTexCompareVerifier.isTrilinearAnyCompareValid(compareMode, prec, depths0, depths1, cmpReference, result, isFixedPointDepth); 716 }; 717 718 /** 719 * @param {tcuTexture.ConstPixelBufferAccess} level0 720 * @param {tcuTexture.ConstPixelBufferAccess} level1 721 * @param {tcuTexture.Sampler} sampler 722 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 723 * @param {Array<number>} coord vec2 texture coordinates 724 * @param {number} coordZ 725 * @param {Array<number>} fBounds vec2 726 * @param {number} cmpReference 727 * @param {number} result 728 * @return {boolean} 729 */ 730 tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid = function(level0, 731 level1, 732 sampler, 733 prec, 734 coord, 735 coordZ, 736 fBounds, 737 cmpReference, 738 result) { 739 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level0.getFormat()); 740 741 // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent. 742 // Right now this allows pairing any two valid bilinear quads. 743 744 var w0 = level0.getWidth(); 745 var w1 = level1.getWidth(); 746 var h0 = level0.getHeight(); 747 var h1 = level1.getHeight(); 748 749 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]); 750 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]); 751 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]); 752 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]); 753 754 // Integer coordinates - without wrap mode 755 var minI0 = Math.floor(uBounds0[0] - 0.5); 756 var maxI0 = Math.floor(uBounds0[1] - 0.5); 757 var minI1 = Math.floor(uBounds1[0] - 0.5); 758 var maxI1 = Math.floor(uBounds1[1] - 0.5); 759 var minJ0 = Math.floor(vBounds0[0] - 0.5); 760 var maxJ0 = Math.floor(vBounds0[1] - 0.5); 761 var minJ1 = Math.floor(vBounds1[0] - 0.5); 762 var maxJ1 = Math.floor(vBounds1[1] - 0.5); 763 764 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 765 for (var i0 = minI0; i0 <= maxI0; i0++) { 766 var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1); 767 var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1); 768 var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1); 769 var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1); 770 var depths0 = []; 771 772 var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0); 773 var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0 + 1, w0); 774 var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0); 775 var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0 + 1, h0); 776 777 depths0[0] = level0.getPixDepth(x0, y0, coordZ); 778 depths0[1] = level0.getPixDepth(x1, y0, coordZ); 779 depths0[2] = level0.getPixDepth(x0, y1, coordZ); 780 depths0[3] = level0.getPixDepth(x1, y1, coordZ); 781 782 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 783 for (var i1 = minI1; i1 <= maxI1; i1++) { 784 var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1); 785 var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1); 786 var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1); 787 var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1); 788 var depths1 = []; 789 790 x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1); 791 x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1 + 1, w1); 792 y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1); 793 y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1 + 1, h1); 794 795 depths1[0] = level1.getPixDepth(x0, y0, coordZ); 796 depths1[1] = level1.getPixDepth(x1, y0, coordZ); 797 depths1[2] = level1.getPixDepth(x0, y1, coordZ); 798 depths1[3] = level1.getPixDepth(x1, y1, coordZ); 799 800 if (tcuTexCompareVerifier.isTrilinearCompareValid(sampler.compare, prec, depths0, depths1, 801 [minA0, maxA0], [minB0, maxB0], 802 [minA1, maxA1], [minB1, maxB1], 803 fBounds, cmpReference, result, isFixedPointDepth)) 804 return true; 805 } 806 } 807 } 808 } 809 810 return false; 811 }; 812 813 /** 814 * @param {tcuTexture.ConstPixelBufferAccess} level0 815 * @param {tcuTexture.ConstPixelBufferAccess} level1 816 * @param {tcuTexture.Sampler} sampler 817 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 818 * @param {Array<number>} coord vec2 texture coordinates 819 * @param {number} coordZ 820 * @param {Array<number>} fBounds vec2 821 * @param {number} cmpReference 822 * @param {number} result 823 * @return {boolean} 824 */ 825 tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid = function(level0, 826 level1, 827 sampler, 828 prec, 829 coord, 830 coordZ, 831 fBounds, 832 cmpReference, 833 result) { 834 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level0.getFormat()); 835 836 var w0 = level0.getWidth(); 837 var w1 = level1.getWidth(); 838 var h0 = level0.getHeight(); 839 var h1 = level1.getHeight(); 840 841 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]); 842 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]); 843 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]); 844 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]); 845 846 var minI0 = Math.floor(uBounds0[0]); 847 var maxI0 = Math.floor(uBounds0[1]); 848 var minI1 = Math.floor(uBounds1[0]); 849 var maxI1 = Math.floor(uBounds1[1]); 850 var minJ0 = Math.floor(vBounds0[0]); 851 var maxJ0 = Math.floor(vBounds0[1]); 852 var minJ1 = Math.floor(vBounds1[0]); 853 var maxJ1 = Math.floor(vBounds1[1]); 854 855 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 856 for (var i0 = minI0; i0 <= maxI0; i0++) { 857 var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0); 858 var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0); 859 860 // Derivated from C++ dEQP function lookupDepth() 861 // Since x0 and y0 are wrapped, here lookupDepth() returns the same result as getPixDepth() 862 assertMsgOptions(deMath.deInBounds32(x0, 0, level0.getWidth()) && deMath.deInBounds32(y0, 0, level0.getHeight()) && deMath.deInBounds32(coordZ, 0, level0.getDepth()), 'x0, y0 or coordZ out of bound.', false, true); 863 var depth0 = level0.getPixDepth(x0, y0, coordZ); 864 865 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 866 for (var i1 = minI1; i1 <= maxI1; i1++) { 867 var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1); 868 var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1); 869 870 // Derivated from C++ dEQP function lookupDepth() 871 // Since x1 and y1 are wrapped, here lookupDepth() returns the same result as getPixDepth() 872 assertMsgOptions(deMath.deInBounds32(x1, 0, level1.getWidth()) && deMath.deInBounds32(y1, 0, level1.getHeight()), 'x1 or y1 out of bound.', false, true); 873 var depth1 = level1.getPixDepth(x1, y1, coordZ); 874 875 if (tcuTexCompareVerifier.isLinearCompareValid(sampler.compare, prec, [depth0, depth1], fBounds, cmpReference, result, isFixedPointDepth)) 876 return true; 877 } 878 } 879 } 880 } 881 882 return false; 883 }; 884 885 /** 886 * @param {tcuTexture.ConstPixelBufferAccess} level0 887 * @param {tcuTexture.ConstPixelBufferAccess} level1 888 * @param {tcuTexture.Sampler} sampler 889 * @param {tcuTexture.FilterMode} levelFilter 890 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 891 * @param {Array<number>} coord vec2 texture coordinates 892 * @param {number} coordZ 893 * @param {Array<number>} fBounds vec2 894 * @param {number} cmpReference 895 * @param {number} result 896 * @return {boolean} 897 */ 898 tcuTexCompareVerifier.isMipmapLinearCompareResultValid = function(level0, 899 level1, 900 sampler, 901 levelFilter, 902 prec, 903 coord, 904 coordZ, 905 fBounds, 906 cmpReference, 907 result) { 908 if (levelFilter == tcuTexture.FilterMode.LINEAR) 909 return tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result); 910 else 911 return tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result); 912 }; 913 914 /** 915 * @param {tcuTexture.Texture2DView} texture 916 * @param {tcuTexture.Sampler} sampler 917 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 918 * @param {Array<number>} coord vec2 texture coordinates 919 * @param {Array<number>} lodBounds vec2 level-of-detail bounds 920 * @param {number} cmpReference 921 * @param {number} result 922 * @return {boolean} 923 */ 924 tcuTexCompareVerifier.isTexCompareResultValid2D = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) { 925 var minLod = lodBounds[0]; 926 var maxLod = lodBounds[1]; 927 var canBeMagnified = minLod <= sampler.lodThreshold; 928 var canBeMinified = maxLod > sampler.lodThreshold; 929 930 if (canBeMagnified) { 931 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, cmpReference, result)) 932 return true; 933 } 934 935 if (canBeMinified) { 936 var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter); 937 var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter); 938 var minTexLevel = 0; 939 var maxTexLevel = texture.getNumLevels() - 1; 940 941 assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true); 942 943 if (isLinearMipmap) { 944 var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1); 945 var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1); 946 947 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true); 948 949 for (var level = minLevel; level <= maxLevel; level++) { 950 var minF = deMath.clamp(minLod - level, 0, 1); 951 var maxF = deMath.clamp(maxLod - level, 0, 1); 952 953 if (tcuTexCompareVerifier.isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, [minF, maxF], cmpReference, result)) 954 return true; 955 } 956 } else if (isNearestMipmap) { 957 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made 958 // decision to allow floor(lod + 0.5) as well. 959 var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel); 960 var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel); 961 962 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true); 963 964 for (var level = minLevel; level <= maxLevel; level++) { 965 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, cmpReference, result)) 966 return true; 967 } 968 } else { 969 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, cmpReference, result)) 970 return true; 971 } 972 } 973 974 return false; 975 }; 976 977 /** 978 * @param {tcuTexture.TextureCubeView} texture 979 * @param {number} baseLevelNdx 980 * @param {tcuTexture.Sampler} sampler 981 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 982 * @param {tcuTexture.CubeFaceCoords} coords 983 * @param {Array<number>} fBounds vec2 984 * @param {number} cmpReference 985 * @param {number} result 986 * @return {boolean} 987 */ 988 tcuTexCompareVerifier.isSeamplessLinearMipmapLinearCompareResultValid = function(texture, 989 baseLevelNdx, 990 sampler, 991 prec, 992 coords, 993 fBounds, 994 cmpReference, 995 result) { 996 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(texture.getLevelFace(baseLevelNdx, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X).getFormat()); 997 var size0 = texture.getLevelFace(baseLevelNdx, coords.face).getWidth(); 998 var size1 = texture.getLevelFace(baseLevelNdx + 1, coords.face).getWidth(); 999 1000 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.s, prec.coordBits[0], prec.uvwBits[0]); 1001 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.s, prec.coordBits[0], prec.uvwBits[0]); 1002 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.t, prec.coordBits[1], prec.uvwBits[1]); 1003 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.t, prec.coordBits[1], prec.uvwBits[1]); 1004 1005 // Integer coordinates - without wrap mode 1006 var minI0 = Math.floor(uBounds0[0] - 0.5); 1007 var maxI0 = Math.floor(uBounds0[1] - 0.5); 1008 var minI1 = Math.floor(uBounds1[0] - 0.5); 1009 var maxI1 = Math.floor(uBounds1[1] - 0.5); 1010 var minJ0 = Math.floor(vBounds0[0] - 0.5); 1011 var maxJ0 = Math.floor(vBounds0[1] - 0.5); 1012 var minJ1 = Math.floor(vBounds1[0] - 0.5); 1013 var maxJ1 = Math.floor(vBounds1[1] - 0.5); 1014 1015 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces0 = []; 1016 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces1 = []; 1017 1018 for (var key in tcuTexture.CubeFace) { 1019 var face = tcuTexture.CubeFace[key]; 1020 faces0[face] = texture.getLevelFace(baseLevelNdx, face); 1021 faces1[face] = texture.getLevelFace(baseLevelNdx + 1, face); 1022 } 1023 1024 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 1025 for (var i0 = minI0; i0 <= maxI0; i0++) { 1026 var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1); 1027 var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1); 1028 var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1); 1029 var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1); 1030 var depths0 = []; 1031 1032 var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 0]), size0); 1033 var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 0]), size0); 1034 var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 1]), size0); 1035 var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 1]), size0); 1036 1037 // If any of samples is out of both edges, implementations can do pretty much anything according to spec. 1038 // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color. 1039 if (c00 == null || c01 == null || c10 == null || c11 == null) 1040 return true; 1041 1042 depths0[0] = faces0[c00.face].getPixDepth(c00.s, c00.t); 1043 depths0[1] = faces0[c10.face].getPixDepth(c10.s, c10.t); 1044 depths0[2] = faces0[c01.face].getPixDepth(c01.s, c01.t); 1045 depths0[3] = faces0[c11.face].getPixDepth(c11.s, c11.t); 1046 1047 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 1048 for (var i1 = minI1; i1 <= maxI1; i1++) { 1049 var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1); 1050 var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1); 1051 var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1); 1052 var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1); 1053 var depths1 = []; 1054 1055 c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 0]), size1); 1056 c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 0]), size1); 1057 c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 1]), size1); 1058 c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 1]), size1); 1059 1060 if (c00 == null || c01 == null || c10 == null || c11 == null) 1061 return true; 1062 1063 depths1[0] = faces1[c00.face].getPixDepth(c00.s, c00.t); 1064 depths1[1] = faces1[c10.face].getPixDepth(c10.s, c10.t); 1065 depths1[2] = faces1[c01.face].getPixDepth(c01.s, c01.t); 1066 depths1[3] = faces1[c11.face].getPixDepth(c11.s, c11.t); 1067 1068 if (tcuTexCompareVerifier.isTrilinearCompareValid(sampler.compare, prec, depths0, depths1, 1069 [minA0, maxA0], [minB0, maxB0], 1070 [minA1, maxA1], [minB1, maxB1], 1071 fBounds, cmpReference, result, isFixedPointDepth)) 1072 return true; 1073 } 1074 } 1075 } 1076 } 1077 1078 return false; 1079 }; 1080 1081 /** 1082 * @param {tcuTexture.TextureCubeView} texture 1083 * @param {number} levelNdx 1084 * @param {tcuTexture.Sampler} sampler 1085 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 1086 * @param {tcuTexture.CubeFaceCoords} coords 1087 * @param {number} cmpReference 1088 * @param {number} result 1089 * @return {boolean} 1090 */ 1091 1092 tcuTexCompareVerifier.isSeamlessLinearCompareResultValid = function(texture, 1093 levelNdx, 1094 sampler, 1095 prec, 1096 coords, 1097 cmpReference, 1098 result) { 1099 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(texture.getLevelFace(levelNdx, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X).getFormat()); 1100 var size = texture.getLevelFace(levelNdx, coords.face).getWidth(); 1101 1102 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits[0], prec.uvwBits[0]); 1103 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits[1], prec.uvwBits[1]); 1104 1105 // Integer coordinate bounds for (x0,y0) - without wrap mode 1106 var minI = Math.floor(uBounds[0] - 0.5); 1107 var maxI = Math.floor(uBounds[1] - 0.5); 1108 var minJ = Math.floor(vBounds[0] - 0.5); 1109 var maxJ = Math.floor(vBounds[1] - 0.5); 1110 1111 // Face accesses 1112 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces = []; 1113 1114 for (var key in tcuTexture.CubeFace) { 1115 var face = tcuTexture.CubeFace[key]; 1116 faces[face] = texture.getLevelFace(levelNdx, face); 1117 } 1118 1119 for (var j = minJ; j <= maxJ; j++) { 1120 for (var i = minI; i <= maxI; i++) { 1121 var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 0]), size); 1122 var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 0]), size); 1123 var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 1]), size); 1124 var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 1]), size); 1125 1126 // If any of samples is out of both edges, implementations can do pretty much anything according to spec. 1127 // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color. 1128 if (!c00 || !c01 || !c10 || !c11) 1129 return true; 1130 1131 // Bounds for filtering factors 1132 var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1); 1133 var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1); 1134 var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1); 1135 var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1); 1136 1137 var depths = []; 1138 depths[0] = faces[c00.face].getPixDepth(c00.s, c00.t); 1139 depths[1] = faces[c10.face].getPixDepth(c10.s, c10.t); 1140 depths[2] = faces[c01.face].getPixDepth(c01.s, c01.t); 1141 depths[3] = faces[c11.face].getPixDepth(c11.s, c11.t); 1142 1143 if (tcuTexCompareVerifier.isBilinearCompareValid(sampler.compare, prec, depths, [minA, maxA], [minB, maxB], cmpReference, result, isFixedPointDepth)) 1144 return true; 1145 } 1146 } 1147 1148 return false; 1149 }; 1150 1151 /** 1152 * @param {tcuTexture.TextureCubeView} texture 1153 * @param {number} levelNdx 1154 * @param {tcuTexture.Sampler} sampler 1155 * @param {tcuTexture.FilterMode} filterMode 1156 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 1157 * @param {tcuTexture.CubeFaceCoords} coords 1158 * @param {number} cmpReference 1159 * @param {number} result 1160 * @return {boolean} 1161 */ 1162 tcuTexCompareVerifier.isCubeLevelCompareResultValid = function(texture, 1163 levelNdx, 1164 sampler, 1165 filterMode, 1166 prec, 1167 coords, 1168 cmpReference, 1169 result) { 1170 if (filterMode == tcuTexture.FilterMode.LINEAR) { 1171 if (sampler.seamlessCubeMap) 1172 return tcuTexCompareVerifier.isSeamlessLinearCompareResultValid(texture, levelNdx, sampler, prec, coords, cmpReference, result); 1173 else 1174 return tcuTexCompareVerifier.isLinearCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, [coords.s, coords.t], 0, cmpReference, result); 1175 } else 1176 return tcuTexCompareVerifier.isNearestCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, [coords.s, coords.t], 0, cmpReference, result); 1177 }; 1178 1179 /** 1180 * @param {tcuTexture.TextureCubeView} texture 1181 * @param {number} baseLevelNdx 1182 * @param {tcuTexture.Sampler} sampler 1183 * @param {tcuTexture.FilterMode} levelFilter 1184 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 1185 * @param {tcuTexture.CubeFaceCoords} coords 1186 * @param {Array<number>} fBounds vec2 1187 * @param {number} cmpReference 1188 * @param {number} result 1189 * @return {boolean} 1190 */ 1191 tcuTexCompareVerifier.isCubeMipmapLinearCompareResultValid = function(texture, 1192 baseLevelNdx, 1193 sampler, 1194 levelFilter, 1195 prec, 1196 coords, 1197 fBounds, 1198 cmpReference, 1199 result) { 1200 if (levelFilter == tcuTexture.FilterMode.LINEAR) { 1201 if (sampler.seamlessCubeMap) 1202 return tcuTexCompareVerifier.isSeamplessLinearMipmapLinearCompareResultValid(texture, baseLevelNdx, sampler, prec, coords, fBounds, cmpReference, result); 1203 else 1204 return tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx, coords.face), 1205 texture.getLevelFace(baseLevelNdx + 1, coords.face), 1206 sampler, prec, [coords.s, coords.t], 0, fBounds, cmpReference, result); 1207 } else 1208 return tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx, coords.face), 1209 texture.getLevelFace(baseLevelNdx + 1, coords.face), 1210 sampler, prec, [coords.s, coords.t], 0, fBounds, cmpReference, result); 1211 }; 1212 1213 /** 1214 * @param {tcuTexture.TextureCubeView} texture 1215 * @param {tcuTexture.Sampler} sampler 1216 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 1217 * @param {Array<number>} coord vec2 texture coordinates 1218 * @param {Array<number>} lodBounds vec2 level-of-detail bounds 1219 * @param {number} cmpReference 1220 * @param {number} result 1221 * @return {boolean} 1222 */ 1223 tcuTexCompareVerifier.isTexCompareResultValidCube = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) { 1224 /** @type {Array<tcuTexture.CubeFace>} */var possibleFaces = tcuTexVerifierUtil.getPossibleCubeFaces(coord, prec.coordBits); 1225 1226 if (!possibleFaces) 1227 return true; // Result is undefined. 1228 1229 for (var tryFaceNdx = 0; tryFaceNdx < possibleFaces.length; tryFaceNdx++) { 1230 var face = possibleFaces[tryFaceNdx]; 1231 var faceCoords = new tcuTexture.CubeFaceCoords(face, tcuTexture.projectToFace(face, coord)); 1232 var minLod = lodBounds[0]; 1233 var maxLod = lodBounds[1]; 1234 var canBeMagnified = minLod <= sampler.lodThreshold; 1235 var canBeMinified = maxLod > sampler.lodThreshold; 1236 1237 if (canBeMagnified) { 1238 if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, 0, sampler, sampler.magFilter, prec, faceCoords, cmpReference, result)) 1239 return true; 1240 } 1241 1242 if (canBeMinified) { 1243 var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter); 1244 var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter); 1245 var minTexLevel = 0; 1246 var maxTexLevel = texture.getNumLevels() - 1; 1247 1248 assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true); 1249 1250 if (isLinearMipmap) { 1251 var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1); 1252 var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1); 1253 1254 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true); 1255 1256 for (var level = minLevel; level <= maxLevel; level++) { 1257 var minF = deMath.clamp(minLod - level, 0, 1); 1258 var maxF = deMath.clamp(maxLod - level, 0, 1); 1259 1260 if (tcuTexCompareVerifier.isCubeMipmapLinearCompareResultValid(texture, level, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, [minF, maxF], cmpReference, result)) 1261 return true; 1262 } 1263 } else if (isNearestMipmap) { 1264 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made 1265 // decision to allow floor(lod + 0.5) as well. 1266 var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel); 1267 var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel); 1268 1269 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true); 1270 1271 for (var level = minLevel; level <= maxLevel; level++) { 1272 if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, level, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, cmpReference, result)) 1273 return true; 1274 } 1275 } else { 1276 if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, 0, sampler, sampler.minFilter, prec, faceCoords, cmpReference, result)) 1277 return true; 1278 } 1279 } 1280 } 1281 1282 return false; 1283 }; 1284 1285 /** 1286 * @param {tcuTexture.Texture2DArrayView} texture 1287 * @param {tcuTexture.Sampler} sampler 1288 * @param {tcuTexCompareVerifier.TexComparePrecision} prec 1289 * @param {Array<number>} coord vec3 texture coordinates 1290 * @param {Array<number>} lodBounds vec2 level-of-detail bounds 1291 * @param {number} cmpReference 1292 * @param {number} result 1293 * @return {boolean} 1294 */ 1295 tcuTexCompareVerifier.isTexCompareResultValid2DArray = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) { 1296 var depthErr = tcuTexVerifierUtil.computeFloatingPointError(coord[2], prec.coordBits[2]) + tcuTexVerifierUtil.computeFixedPointError(prec.uvwBits[2]); 1297 var minZ = coord[2] - depthErr; 1298 var maxZ = coord[2] + depthErr; 1299 var minLayer = deMath.clamp(Math.floor(minZ + 0.5), 0, texture.getNumLayers() - 1); 1300 var maxLayer = deMath.clamp(Math.floor(maxZ + 0.5), 0, texture.getNumLayers() - 1); 1301 1302 for (var layer = minLayer; layer <= maxLayer; layer++) { 1303 var minLod = lodBounds[0]; 1304 var maxLod = lodBounds[1]; 1305 var canBeMagnified = minLod <= sampler.lodThreshold; 1306 var canBeMinified = maxLod > sampler.lodThreshold; 1307 1308 if (canBeMagnified) { 1309 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result)) 1310 return true; 1311 } 1312 1313 if (canBeMinified) { 1314 var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter); 1315 var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter); 1316 var minTexLevel = 0; 1317 var maxTexLevel = texture.getNumLevels() - 1; 1318 1319 assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true); 1320 1321 if (isLinearMipmap) { 1322 var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1); 1323 var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1); 1324 1325 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true); 1326 1327 for (var level = minLevel; level <= maxLevel; level++) { 1328 var minF = deMath.clamp(minLod - level, 0, 1); 1329 var maxF = deMath.clamp(maxLod - level, 0, 1); 1330 1331 if (tcuTexCompareVerifier.isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, deMath.swizzle(coord, [0, 1]), layer, [minF, maxF], cmpReference, result)) 1332 return true; 1333 } 1334 } else if (isNearestMipmap) { 1335 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made 1336 // decision to allow floor(lod + 0.5) as well. 1337 var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel); 1338 var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel); 1339 1340 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true); 1341 1342 for (var level = minLevel; level <= maxLevel; level++) { 1343 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result)) 1344 return true; 1345 } 1346 } else { 1347 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result)) 1348 return true; 1349 } 1350 } 1351 } 1352 1353 return false; 1354 }; 1355 1356 });