tcuTexLookupVerifier.js (116440B)
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.tcuTexLookupVerifier'); 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 tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier; 31 var tcuTexture = framework.common.tcuTexture; 32 var tcuTextureUtil = framework.common.tcuTextureUtil; 33 var tcuTexVerifierUtil = framework.common.tcuTexVerifierUtil; 34 var deMath = framework.delibs.debase.deMath; 35 36 /** @typedef {(tcuTexLookupVerifier.LookupPrecision|{tcuTexLookupVerifier.LookupPrecision})} */ 37 tcuTexLookupVerifier.PrecType; 38 39 /** 40 * Generic lookup precision parameters 41 * @constructor 42 * @struct 43 * @param {Array<number>=} coordBits 44 * @param {Array<number>=} uvwBits 45 * @param {Array<number>=} colorThreshold 46 * @param {Array<boolean>=} colorMask 47 */ 48 tcuTexLookupVerifier.LookupPrecision = function(coordBits, uvwBits, colorThreshold, colorMask) { 49 /** @type {Array<number>} */ this.coordBits = coordBits || [22, 22, 22]; 50 /** @type {Array<number>} */ this.uvwBits = uvwBits || [16, 16, 16]; 51 /** @type {Array<number>} */ this.colorThreshold = colorThreshold || [0, 0, 0, 0]; 52 /** @type {Array<boolean>} */ this.colorMask = colorMask || [true, true, true, true]; 53 }; 54 55 /** 56 * Lod computation precision parameters 57 * @constructor 58 * @struct 59 * @param {number=} derivateBits 60 * @param {number=} lodBits 61 */ 62 tcuTexLookupVerifier.LodPrecision = function(derivateBits, lodBits) { 63 /** @type {number} */ this.derivateBits = derivateBits === undefined ? 22 : derivateBits; 64 /** @type {number} */ this.lodBits = lodBits === undefined ? 16 : lodBits; 65 }; 66 67 /** 68 * @enum {number} 69 */ 70 tcuTexLookupVerifier.TexLookupScaleMode = { 71 MINIFY: 0, 72 MAGNIFY: 1 73 }; 74 75 // Generic utilities 76 77 /** 78 * @param {tcuTexture.Sampler} sampler 79 * @return {boolean} 80 */ 81 tcuTexLookupVerifier.isSamplerSupported = function(sampler) { 82 return sampler.compare == tcuTexture.CompareMode.COMPAREMODE_NONE && 83 tcuTexVerifierUtil.isWrapModeSupported(sampler.wrapS) && 84 tcuTexVerifierUtil.isWrapModeSupported(sampler.wrapT) && 85 tcuTexVerifierUtil.isWrapModeSupported(sampler.wrapR); 86 }; 87 88 // Color read & compare utilities 89 90 /** 91 * @param {tcuTexture.ConstPixelBufferAccess} access 92 * @param {number} x 93 * @param {number} y 94 * @param {number} z 95 * @return {boolean} 96 */ 97 tcuTexLookupVerifier.coordsInBounds = function(access, x, y, z) { 98 return deMath.deInBounds32(x, 0, access.getWidth()) && deMath.deInBounds32(y, 0, access.getHeight()) && deMath.deInBounds32(z, 0, access.getDepth()); 99 }; 100 101 /** 102 * @param {tcuTexture.TextureFormat} format 103 * @return {boolean} 104 */ 105 tcuTexLookupVerifier.isSRGB = function(format) { 106 return format.order == tcuTexture.ChannelOrder.sRGB || format.order == tcuTexture.ChannelOrder.sRGBA; 107 }; 108 109 /** 110 * @param {tcuTexture.ConstPixelBufferAccess} access 111 * @param {tcuTexture.Sampler} sampler 112 * @param {number} i 113 * @param {number} j 114 * @param {number} k 115 * @return {Array<number>} 116 */ 117 tcuTexLookupVerifier.lookupScalar = function(access, sampler, i, j, k) { 118 if (tcuTexLookupVerifier.coordsInBounds(access, i, j, k)) 119 return access.getPixel(i, j, k); 120 else 121 return deMath.toIVec(sampler.borderColor); 122 }; 123 124 /** 125 * @param {tcuTexture.ConstPixelBufferAccess} access 126 * @param {tcuTexture.Sampler} sampler 127 * @param {number} i 128 * @param {number} j 129 * @param {number} k 130 * @return {Array<number>} 131 */ 132 tcuTexLookupVerifier.lookupFloat = function(access, sampler, i, j, k) { 133 // Specialization for float lookups: sRGB conversion is performed as specified in format. 134 if (tcuTexLookupVerifier.coordsInBounds(access, i, j, k)) { 135 /** @type {Array<number>} */ var p = access.getPixel(i, j, k); 136 return tcuTexLookupVerifier.isSRGB(access.getFormat()) ? tcuTextureUtil.sRGBToLinear(p) : p; 137 } else 138 return sampler.borderColor; 139 }; 140 /** 141 * @param {tcuTexLookupVerifier.LookupPrecision} prec 142 * @param {Array<number>} ref 143 * @param {Array<number>} result 144 * @return {boolean} 145 */ 146 tcuTexLookupVerifier.isColorValid = function(prec, ref, result) { 147 return deMath.boolAll( 148 deMath.logicalOrBool( 149 deMath.lessThanEqual(deMath.absDiff(ref, result), prec.colorThreshold), 150 deMath.logicalNotBool(prec.colorMask))); 151 }; 152 153 /** 154 * @constructor 155 * @struct 156 * @param {Array<number>=} p00 157 * @param {Array<number>=} p01 158 * @param {Array<number>=} p10 159 * @param {Array<number>=} p11 160 */ 161 tcuTexLookupVerifier.ColorQuad = function(p00, p01, p10, p11) { 162 /** @type {Array<number>} */ this.p00 = p00 || null; //!< (0, 0) 163 /** @type {Array<number>} */ this.p01 = p01 || null; //!< (1, 0) 164 /** @type {Array<number>} */ this.p10 = p10 || null; //!< (0, 1) 165 /** @type {Array<number>} */ this.p11 = p11 || null; //!< (1, 1) 166 }; 167 168 /** 169 * @param {tcuTexture.ConstPixelBufferAccess} level 170 * @param {tcuTexture.Sampler} sampler 171 * @param {number} x0 172 * @param {number} x1 173 * @param {number} y0 174 * @param {number} y1 175 * @param {number} z 176 * @return {tcuTexLookupVerifier.ColorQuad} 177 */ 178 tcuTexLookupVerifier.lookupQuad = function(level, sampler, x0, x1, y0, y1, z) { 179 var p00 = tcuTexLookupVerifier.lookupFloat(level, sampler, x0, y0, z); 180 var p10 = tcuTexLookupVerifier.lookupFloat(level, sampler, x1, y0, z); 181 var p01 = tcuTexLookupVerifier.lookupFloat(level, sampler, x0, y1, z); 182 var p11 = tcuTexLookupVerifier.lookupFloat(level, sampler, x1, y1, z); 183 return new tcuTexLookupVerifier.ColorQuad(p00, p01, p10, p11); 184 }; 185 186 /** 187 * @constructor 188 * @struct 189 * @param {Array<number>=} p0 190 * @param {Array<number>=} p1 191 */ 192 tcuTexLookupVerifier.ColorLine = function(p0, p1) { 193 /** @type {Array<number>} */ this.p0 = p0 || null; //!< 0 194 /** @type {Array<number>} */ this.p1 = p1 || null; //!< 1 195 }; 196 197 /** 198 * @param {tcuTexture.ConstPixelBufferAccess} level 199 * @param {tcuTexture.Sampler} sampler 200 * @param {number} x0 201 * @param {number} x1 202 * @param {number} y 203 * @return {tcuTexLookupVerifier.ColorLine} 204 */ 205 tcuTexLookupVerifier.lookupLine = function(level, sampler, x0, x1, y) { 206 return new tcuTexLookupVerifier.ColorLine( 207 tcuTexLookupVerifier.lookupFloat(level, sampler, x0, y, 0), 208 tcuTexLookupVerifier.lookupFloat(level, sampler, x1, y, 0) 209 ); 210 }; 211 212 /** 213 * @param {Array<number>} vec 214 * @return {number} 215 */ 216 tcuTexLookupVerifier.minComp = function(vec) { 217 /** @type {number} */ var minVal = vec[0]; 218 for (var ndx = 1; ndx < vec.length; ndx++) 219 minVal = Math.min(minVal, vec[ndx]); 220 return minVal; 221 }; 222 223 /** 224 * @param {Array<number>} vec 225 * @return {number} 226 */ 227 tcuTexLookupVerifier.maxComp = function(vec) { 228 /** @type {number} */ var maxVal = vec[0]; 229 for (var ndx = 1; ndx < vec.length; ndx++) 230 maxVal = Math.max(maxVal, vec[ndx]); 231 return maxVal; 232 }; 233 234 /** 235 * @param {tcuTexLookupVerifier.LookupPrecision} prec 236 * @param {tcuTexLookupVerifier.ColorLine} line 237 * @return {number} 238 */ 239 tcuTexLookupVerifier.computeBilinearSearchStepFromFloatLine = function(prec, line) { 240 assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true); 241 242 /** @type {number} */ var maxSteps = 1 << 16; 243 /** @type {Array<number>} */ var d = deMath.absDiff(line.p1, line.p0); 244 /** @type {Array<number>} */ var stepCount = deMath.divide([d, d, d, d], prec.colorThreshold); 245 /** @type {Array<number>} */ 246 var minStep = deMath.divide([1, 1, 1, 1], deMath.add(stepCount, [1, 1, 1, 1])); 247 /** @type {number} */ var step = Math.max(tcuTexLookupVerifier.minComp(minStep), 1 / maxSteps); 248 249 return step; 250 }; 251 252 /** 253 * @param {tcuTexLookupVerifier.LookupPrecision} prec 254 * @param {tcuTexLookupVerifier.ColorQuad} quad 255 * @return {number} 256 */ 257 tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad = function(prec, quad) { 258 assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true); 259 260 /** @type {number} */ var maxSteps = 1 << 16; 261 /** @type {Array<number>} */ var d0 = deMath.absDiff(quad.p10, quad.p00); 262 /** @type {Array<number>} */ var d1 = deMath.absDiff(quad.p01, quad.p00); 263 /** @type {Array<number>} */ var d2 = deMath.absDiff(quad.p11, quad.p10); 264 /** @type {Array<number>} */ var d3 = deMath.absDiff(quad.p11, quad.p01); 265 /** @type {Array<number>} */ var maxD = deMath.max(d0, deMath.max(d1, deMath.max(d2, d3))); 266 /** @type {Array<number>} */ var stepCount = deMath.divide(maxD, prec.colorThreshold); 267 /** @type {Array<number>} */ var minStep = deMath.divide([1, 1, 1, 1], deMath.add(stepCount, [1, 1, 1, 1])); 268 /** @type {number} */ var step = Math.max(tcuTexLookupVerifier.minComp(minStep), 1 / maxSteps); 269 270 return step; 271 }; 272 273 /** 274 * @param {tcuTexLookupVerifier.LookupPrecision} prec 275 * @return {number} 276 */ 277 tcuTexLookupVerifier.computeBilinearSearchStepForUnorm = function(prec) { 278 assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true); 279 280 /** @type {Array<number>} */ var stepCount = deMath.divide([1, 1, 1, 1], prec.colorThreshold); 281 /** @type {Array<number>} */ var minStep = deMath.divide([1, 1, 1, 1], (deMath.add(stepCount, [1, 1, 1, 1]))); 282 /** @type {number} */ var step = tcuTexLookupVerifier.minComp(minStep); 283 284 return step; 285 }; 286 287 /** 288 * @param {tcuTexLookupVerifier.LookupPrecision} prec 289 * @return {number} 290 */ 291 tcuTexLookupVerifier.computeBilinearSearchStepForSnorm = function(prec) { 292 assertMsgOptions(deMath.boolAll(deMath.greaterThan(prec.colorThreshold, [0, 0, 0, 0])), 'Threshold not greater than 0.', false, true); 293 294 /** @type {Array<number>} */ var stepCount = deMath.divide([2.0, 2.0, 2.0, 2.0], prec.colorThreshold); 295 /** @type {Array<number>} */ var minStep = deMath.divide([1, 1, 1, 1], deMath.add(stepCount, [1, 1, 1, 1])); 296 /** @type {number} */ var step = tcuTexLookupVerifier.minComp(minStep); 297 298 return step; 299 }; 300 301 /** 302 * @param {tcuTexLookupVerifier.ColorLine} line 303 * @return {Array<number>} 304 */ 305 tcuTexLookupVerifier.minLine = function(line) { 306 return deMath.min(line.p0, line.p1); 307 }; 308 309 /** 310 * @param {tcuTexLookupVerifier.ColorLine} line 311 * @return {Array<number>} 312 */ 313 tcuTexLookupVerifier.maxLine = function(line) { 314 var max = deMath.max; 315 return max(line.p0, line.p1); 316 }; 317 318 /** 319 * @param {tcuTexLookupVerifier.ColorQuad} quad 320 * @return {Array<number>} 321 */ 322 tcuTexLookupVerifier.minQuad = function(quad) { 323 var min = deMath.min; 324 return min(quad.p00, min(quad.p10, min(quad.p01, quad.p11))); 325 }; 326 327 /** 328 * @param {tcuTexLookupVerifier.ColorQuad} quad 329 * @return {Array<number>} 330 */ 331 tcuTexLookupVerifier.maxQuad = function(quad) { 332 var max = deMath.max; 333 return max(quad.p00, max(quad.p10, max(quad.p01, quad.p11))); 334 }; 335 336 /** 337 * @param {tcuTexLookupVerifier.LookupPrecision} prec 338 * @param {tcuTexLookupVerifier.ColorQuad} quad 339 * @param {Array<number>} result 340 * @return {boolean} 341 */ 342 tcuTexLookupVerifier.isInColorBounds_1Quad = function(prec, quad, result) { 343 var quadMin = tcuTexLookupVerifier.minQuad; 344 var quadMax = tcuTexLookupVerifier.maxQuad; 345 /** @type {Array<number>} */ var minVal = deMath.subtract(quadMin(quad), prec.colorThreshold); 346 /** @type {Array<number>} */ var maxVal = deMath.add(quadMax(quad), prec.colorThreshold); 347 return deMath.boolAll( 348 deMath.logicalOrBool( 349 deMath.logicalAndBool( 350 deMath.greaterThanEqual(result, minVal), 351 deMath.lessThanEqual(result, maxVal)), 352 deMath.logicalNotBool(prec.colorMask))); 353 }; 354 355 /** 356 * @param {tcuTexLookupVerifier.LookupPrecision} prec 357 * @param {tcuTexLookupVerifier.ColorQuad} quad0 358 * @param {tcuTexLookupVerifier.ColorQuad} quad1 359 * @param {Array<number>} result 360 * @return {boolean} 361 */ 362 tcuTexLookupVerifier.isInColorBounds_2Quad = function(prec, quad0, quad1, result) { 363 var min = deMath.min; 364 var max = deMath.max; 365 var quadMin = tcuTexLookupVerifier.minQuad; 366 var quadMax = tcuTexLookupVerifier.maxQuad; 367 /** @type {Array<number>} */ var minVal = deMath.subtract(min(quadMin(quad0), quadMin(quad1)), prec.colorThreshold); 368 /** @type {Array<number>} */ var maxVal = deMath.add(max(quadMax(quad0), quadMax(quad1)), prec.colorThreshold); 369 return deMath.boolAll( 370 deMath.logicalOrBool( 371 deMath.logicalAndBool( 372 deMath.greaterThanEqual(result, minVal), 373 deMath.lessThanEqual(result, maxVal)), 374 deMath.logicalNotBool(prec.colorMask))); 375 }; 376 377 /** 378 * @param {tcuTexLookupVerifier.LookupPrecision} prec 379 * @param {tcuTexLookupVerifier.ColorLine} line0 380 * @param {tcuTexLookupVerifier.ColorLine} line1 381 * @param {Array<number>} result 382 * @return {boolean} 383 */ 384 tcuTexLookupVerifier.isInColorBounds_2Line = function(prec, line0, line1, result) { 385 var min = deMath.min; 386 var max = deMath.max; 387 var lineMin = tcuTexLookupVerifier.minLine; 388 var lineMax = tcuTexLookupVerifier.maxLine; 389 /** @type {Array<number>} */ var minVal = deMath.subtract(min(lineMin(line0), lineMin(line1)), prec.colorThreshold); 390 /** @type {Array<number>} */ var maxVal = deMath.add(max(lineMax(line0), lineMax(line1)), prec.colorThreshold); 391 return deMath.boolAll( 392 deMath.logicalOrBool( 393 deMath.logicalAndBool( 394 deMath.greaterThanEqual(result, minVal), 395 deMath.lessThanEqual(result, maxVal)), 396 deMath.logicalNotBool(prec.colorMask))); 397 }; 398 399 /** 400 * @param {tcuTexLookupVerifier.LookupPrecision} prec 401 * @param {tcuTexLookupVerifier.ColorQuad} quad00 402 * @param {tcuTexLookupVerifier.ColorQuad} quad01 403 * @param {tcuTexLookupVerifier.ColorQuad} quad10 404 * @param {tcuTexLookupVerifier.ColorQuad} quad11 405 * @param {Array<number>} result 406 * @return {boolean} 407 */ 408 tcuTexLookupVerifier.isInColorBounds_4Quad = function(prec, quad00, quad01, quad10, quad11, result) { 409 var min = deMath.min; 410 var max = deMath.max; 411 var quadMin = tcuTexLookupVerifier.minQuad; 412 var quadMax = tcuTexLookupVerifier.maxQuad; 413 /** @type {Array<number>} */ var minVal = deMath.subtract(min(quadMin(quad00), min(quadMin(quad01), min(quadMin(quad10), quadMin(quad11)))), prec.colorThreshold); 414 /** @type {Array<number>} */ var maxVal = deMath.add(max(quadMax(quad00), max(quadMax(quad01), max(quadMax(quad10), quadMax(quad11)))), prec.colorThreshold); 415 return deMath.boolAll( 416 deMath.logicalOrBool( 417 deMath.logicalAndBool( 418 deMath.greaterThanEqual(result, minVal), 419 deMath.lessThanEqual(result, maxVal)), 420 deMath.logicalNotBool(prec.colorMask))); 421 }; 422 423 // Range search utilities 424 425 /** 426 * @param {tcuTexLookupVerifier.LookupPrecision} prec 427 * @param {Array<number>} c0 428 * @param {Array<number>} c1 429 * @param {Array<number>} fBounds 430 * @param {Array<number>} result 431 * @return {boolean} 432 */ 433 tcuTexLookupVerifier.isLinearRangeValid = function(prec, c0, c1, fBounds, result) { 434 // This is basically line segment - AABB test. Valid interpolation line is checked 435 // against result AABB constructed by applying threshold. 436 437 /** @type {Array<number>} */ var rMin = deMath.subtract(result, prec.colorThreshold); 438 /** @type {Array<number>} */ var rMax = deMath.add(result, prec.colorThreshold); 439 440 // Algorithm: For each component check whether segment endpoints are inside, or intersect with slab. 441 // If all intersect or are inside, line segment intersects the whole 4D AABB. 442 for (var compNdx = 0; compNdx < 4; compNdx++) { 443 if (!prec.colorMask[compNdx]) 444 continue; 445 446 /** @type {number} */ var i0 = c0[compNdx] * (1 - fBounds[0]) + c1[compNdx] * fBounds[0]; 447 /** @type {number} */ var i1 = c0[compNdx] * (1 - fBounds[1]) + c1[compNdx] * fBounds[1]; 448 if ((i0 > rMax[compNdx] && i1 > rMax[compNdx]) || 449 (i0 < rMin[compNdx] && i1 < rMin[compNdx])) { 450 return false; 451 } 452 } 453 454 return true; 455 }; 456 457 /** 458 * @param {tcuTexLookupVerifier.LookupPrecision} prec 459 * @param {tcuTexLookupVerifier.ColorQuad} quad 460 * @param {Array<number>} xBounds 461 * @param {Array<number>} yBounds 462 * @param {number} searchStep 463 * @param {Array<number>} result 464 * @return {boolean} 465 */ 466 tcuTexLookupVerifier.isBilinearRangeValid = function(prec, quad, xBounds, yBounds, searchStep, result) { 467 assertMsgOptions(xBounds[0] <= xBounds[1], 'Out of bounds: X direction.', false, true); 468 assertMsgOptions(yBounds[0] <= yBounds[1], 'Out of bounds: Y direction.', false, true); 469 470 if (!tcuTexLookupVerifier.isInColorBounds_1Quad(prec, quad, result)) 471 return false; 472 473 for (var x = xBounds[0]; x < xBounds[1] + searchStep; x += searchStep) { 474 /** @type {number} */ var a = Math.min(x, xBounds[1]); 475 /** @type {Array<number>} */ var c0 = deMath.add(deMath.scale(quad.p00, (1 - a)), deMath.scale(quad.p10, a)); 476 /** @type {Array<number>} */ var c1 = deMath.add(deMath.scale(quad.p01, (1 - a)), deMath.scale(quad.p11, a)); 477 478 if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, yBounds, result)) 479 return true; 480 } 481 482 return false; 483 }; 484 485 /** 486 * @param {tcuTexLookupVerifier.LookupPrecision} prec 487 * @param {tcuTexLookupVerifier.ColorQuad} quad0 488 * @param {tcuTexLookupVerifier.ColorQuad} quad1 489 * @param {Array<number>} xBounds 490 * @param {Array<number>} yBounds 491 * @param {Array<number>} zBounds 492 * @param {number} searchStep 493 * @param {Array<number>} result 494 * @return {boolean} 495 */ 496 tcuTexLookupVerifier.isTrilinearRangeValid = function(prec, quad0, quad1, xBounds, yBounds, zBounds, searchStep, result) { 497 assertMsgOptions(xBounds[0] <= xBounds[1], 'Out of bounds: X direction.', false, true); 498 assertMsgOptions(yBounds[0] <= yBounds[1], 'Out of bounds: Y direction.', false, true); 499 assertMsgOptions(zBounds[0] <= zBounds[1], 'Out of bounds: Z direction.', false, true); 500 501 if (!tcuTexLookupVerifier.isInColorBounds_2Quad(prec, quad0, quad1, result)) 502 return false; 503 504 for (var x = xBounds[0]; x < xBounds[1] + searchStep; x += searchStep) { 505 for (var y = yBounds[0]; y < yBounds[1] + searchStep; y += searchStep) { 506 /** @type {number} */ var a = Math.min(x, xBounds[1]); 507 /** @type {number} */ var b = Math.min(y, yBounds[1]); 508 /** @type {Array<number>} */ 509 var c0 = deMath.add( 510 deMath.add( 511 deMath.add( 512 deMath.scale(quad0.p00, (1 - a) * (1 - b)), 513 deMath.scale(quad0.p10, a * (1 - b))), 514 deMath.scale(quad0.p01, (1 - a) * b)), 515 deMath.scale(quad0.p11, a * b)); 516 /** @type {Array<number>} */ 517 var c1 = deMath.add( 518 deMath.add( 519 deMath.add( 520 deMath.scale(quad1.p00, (1 - a) * (1 - b)), 521 deMath.scale(quad1.p10, a * (1 - b))), 522 deMath.scale(quad1.p01, (1 - a) * b)), 523 deMath.scale(quad1.p11, a * b)); 524 525 if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, zBounds, result)) 526 return true; 527 } 528 } 529 530 return false; 531 }; 532 533 /** 534 * @param {tcuTexLookupVerifier.LookupPrecision} prec 535 * @param {tcuTexLookupVerifier.ColorQuad} quad0 536 * @param {tcuTexLookupVerifier.ColorQuad} quad1 537 * @param {Array<number>} xBounds0 538 * @param {Array<number>} yBounds0 539 * @param {Array<number>} xBounds1 540 * @param {Array<number>} yBounds1 541 * @param {Array<number>} zBounds 542 * @param {number} searchStep 543 * @param {Array<number>} result 544 * @return {boolean} 545 */ 546 tcuTexLookupVerifier.is2DTrilinearFilterResultValid = function(prec, quad0, quad1, xBounds0, yBounds0, xBounds1, yBounds1, zBounds, searchStep, result) { 547 assertMsgOptions(xBounds0[0] <= xBounds0[1], 'Out of bounds: X direction.', false, true); 548 assertMsgOptions(yBounds0[0] <= yBounds0[1], 'Out of bounds: Y direction.', false, true); 549 assertMsgOptions(xBounds1[0] <= xBounds1[1], 'Out of bounds: X direction.', false, true); 550 assertMsgOptions(yBounds1[0] <= yBounds1[1], 'Out of bounds: Y direction.', false, true); 551 552 if (!tcuTexLookupVerifier.isInColorBounds_2Quad(prec, quad0, quad1, result)) 553 return false; 554 555 for (var x0 = xBounds0[0]; x0 < xBounds0[1] + searchStep; x0 += searchStep) { 556 for (var y0 = yBounds0[0]; y0 < yBounds0[1] + searchStep; y0 += searchStep) { 557 /** @type {number} */ var a0 = Math.min(x0, xBounds0[1]); 558 /** @type {number} */ var b0 = Math.min(y0, yBounds0[1]); 559 /** @type {Array<number>} */ 560 var c0 = deMath.add( 561 deMath.add( 562 deMath.add( 563 deMath.scale(quad0.p00, (1 - a0) * (1 - b0)), 564 deMath.scale(quad0.p10, a0 * (1 - b0))), 565 deMath.scale(quad0.p01, (1 - a0) * b0)), 566 deMath.scale(quad0.p11, a0 * b0)); 567 568 for (var x1 = xBounds1[0]; x1 <= xBounds1[1]; x1 += searchStep) { 569 for (var y1 = yBounds1[0]; y1 <= yBounds1[1]; y1 += searchStep) { 570 /** @type {number} */ var a1 = Math.min(x1, xBounds1[1]); 571 /** @type {number} */ var b1 = Math.min(y1, yBounds1[1]); 572 /** @type {Array<number>} */ 573 var c1 = deMath.add( 574 deMath.add( 575 deMath.add( 576 deMath.scale(quad1.p00, (1 - a1) * (1 - b1)), 577 deMath.scale(quad1.p10, a1 * (1 - b1))), 578 deMath.scale(quad1.p01, (1 - a1) * b1)), 579 deMath.scale(quad1.p11, a1 * b1)); 580 581 if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, zBounds, result)) 582 return true; 583 } 584 } 585 } 586 } 587 588 return false; 589 }; 590 591 /** 592 * @param {tcuTexLookupVerifier.LookupPrecision} prec 593 * @param {tcuTexLookupVerifier.ColorQuad} quad00 594 * @param {tcuTexLookupVerifier.ColorQuad} quad01 595 * @param {tcuTexLookupVerifier.ColorQuad} quad10 596 * @param {tcuTexLookupVerifier.ColorQuad} quad11 597 * @param {Array<number>} xBounds0 598 * @param {Array<number>} yBounds0 599 * @param {Array<number>} zBounds0 600 * @param {Array<number>} xBounds1 601 * @param {Array<number>} yBounds1 602 * @param {Array<number>} zBounds1 603 * @param {Array<number>} wBounds 604 * @param {number} searchStep 605 * @param {Array<number>} result 606 * @return {boolean} 607 */ 608 tcuTexLookupVerifier.is3DTrilinearFilterResultValid = function(prec, quad00, quad01, quad10, quad11, xBounds0, yBounds0, zBounds0, xBounds1, yBounds1, zBounds1, wBounds, searchStep, result) { 609 assertMsgOptions(xBounds0[0] <= xBounds0[1], 'Out of bounds: X direction.', false, true); 610 assertMsgOptions(yBounds0[0] <= yBounds0[1], 'Out of bounds: Y direction.', false, true); 611 assertMsgOptions(zBounds0[0] <= zBounds0[1], 'Out of bounds: Z direction.', false, true); 612 assertMsgOptions(xBounds1[0] <= xBounds1[1], 'Out of bounds: X direction.', false, true); 613 assertMsgOptions(yBounds1[0] <= yBounds1[1], 'Out of bounds: Y direction.', false, true); 614 assertMsgOptions(zBounds1[0] <= zBounds1[1], 'Out of bounds: Z direction.', false, true); 615 616 if (!tcuTexLookupVerifier.isInColorBounds_4Quad(prec, quad00, quad01, quad10, quad11, result)) 617 return false; 618 619 function biInterp(result, p00, p01, p10, p11, s00, s01, s10, s11) { 620 for (var ii = 0; ii < 4; ++ii) { 621 result[ii] = p00[ii] * s00 + p10[ii] * s10 + p01[ii] * s01 + p11[ii] * s11; 622 } 623 } 624 625 function interp(result, p0, p1, s) { 626 for (var ii = 0; ii < 4; ++ii) { 627 result[ii] = p0[ii] * (1 - s) + p1[ii] * s; 628 } 629 } 630 631 /** @type {Array<number>} */ var c00 = [0, 0, 0, 0]; 632 /** @type {Array<number>} */ var c01 = [0, 0, 0, 0]; 633 /** @type {Array<number>} */ var c10 = [0, 0, 0, 0]; 634 /** @type {Array<number>} */ var c11 = [0, 0, 0, 0]; 635 /** @type {Array<number>} */ var cz0 = [0, 0, 0, 0]; 636 /** @type {Array<number>} */ var cz1 = [0, 0, 0, 0]; 637 638 for (var x0 = xBounds0[0]; x0 < xBounds0[1] + searchStep; x0 += searchStep) { 639 for (var y0 = yBounds0[0]; y0 < yBounds0[1] + searchStep; y0 += searchStep) { 640 /** @type {number} */ var a0 = Math.min(x0, xBounds0[1]); 641 /** @type {number} */ var b0 = Math.min(y0, yBounds0[1]); 642 643 /** @type {number} */ var s00 = (1 - a0) * (1 - b0); 644 /** @type {number} */ var s01 = (1 - a0) * b0; 645 /** @type {number} */ var s10 = a0 * (1 - b0); 646 /** @type {number} */ var s11 = a0 * b0; 647 648 biInterp(c00, quad00.p00, quad00.p01, quad00.p10, quad00.p11, s00, s01, s10, s11); 649 biInterp(c01, quad01.p00, quad01.p01, quad01.p10, quad01.p11, s00, s01, s10, s11); 650 651 for (var z0 = zBounds0[0]; z0 < zBounds0[1] + searchStep; z0 += searchStep) { 652 /** @type {number} */ var c0 = Math.min(z0, zBounds0[1]); 653 interp(cz0, c00, c01, c0); 654 655 for (var x1 = xBounds1[0]; x1 < xBounds1[1] + searchStep; x1 += searchStep) { 656 for (var y1 = yBounds1[0]; y1 < yBounds1[1] + searchStep; y1 += searchStep) { 657 /** @type {number} */ var a1 = Math.min(x1, xBounds1[1]); 658 /** @type {number} */ var b1 = Math.min(y1, yBounds1[1]); 659 660 /** @type {number} */ var t00 = (1 - a1) * (1 - b1); 661 /** @type {number} */ var t01 = (1 - a1) * b1; 662 /** @type {number} */ var t10 = a1 * (1 - b1); 663 /** @type {number} */ var t11 = a1 * b1; 664 665 biInterp(c10, quad10.p00, quad10.p01, quad10.p10, quad10.p11, t00, t01, t10, t11); 666 biInterp(c11, quad11.p00, quad11.p01, quad11.p10, quad11.p11, t00, t01, t10, t11); 667 668 for (var z1 = zBounds1[0]; z1 < zBounds1[1] + searchStep; z1 += searchStep) { 669 /** @type {number} */ var c1 = Math.min(z1, zBounds1[1]); 670 interp(cz1, c10, c11, c1); 671 672 if (tcuTexLookupVerifier.isLinearRangeValid(prec, cz0, cz1, wBounds, result)) 673 return true; 674 } 675 } 676 } 677 } 678 } 679 } 680 681 return false; 682 }; 683 684 /** 685 * @param {tcuTexture.ConstPixelBufferAccess} level 686 * @param {tcuTexture.Sampler} sampler 687 * @param {tcuTexLookupVerifier.LookupPrecision} prec 688 * @param {number} coordX 689 * @param {number} coordY 690 * @param {Array<number>} result 691 * @return {boolean} 692 */ 693 tcuTexLookupVerifier.isNearestSampleResultValid_CoordXYAsNumber = function(level, sampler, prec, coordX, coordY, result) { 694 assertMsgOptions(level.getDepth() == 1, 'Depth must be 1.', false, true); 695 696 /** @type {Array<number>} */ 697 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 698 sampler.normalizedCoords, level.getWidth(), coordX, prec.coordBits[0], prec.uvwBits[0]); 699 700 /** @type {number} */ var minI = Math.floor(uBounds[0]); 701 /** @type {number} */ var maxI = Math.floor(uBounds[1]); 702 703 for (var i = minI; i <= maxI; i++) { 704 /** @type {number} */ var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth()); 705 /** @type {Array<number>} */ var color; 706 if (tcuTexLookupVerifier.isSRGB(level.getFormat())) { 707 color = tcuTexLookupVerifier.lookupFloat(level, sampler, x, coordY, 0); 708 } else { 709 color = tcuTexLookupVerifier.lookupScalar(level, sampler, x, coordY, 0); 710 } 711 712 if (tcuTexLookupVerifier.isColorValid(prec, color, result)) 713 return true; 714 } 715 716 return false; 717 }; 718 719 /** 720 * @param {tcuTexture.ConstPixelBufferAccess} level 721 * @param {tcuTexture.Sampler} sampler 722 * @param {tcuTexLookupVerifier.LookupPrecision} prec 723 * @param {Array<number>} coord vec2 724 * @param {number} coordZ int 725 * @param {Array<number>} result 726 * @return {boolean} 727 */ 728 tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt = function(level, sampler, prec, coord, coordZ, result) { 729 /** @type {Array<number>} */ 730 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 731 sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]); 732 /** @type {Array<number>} */ 733 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 734 sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]); 735 736 // Integer coordinates - without wrap mode 737 /** @type {number} */ var minI = Math.floor(uBounds[0]); 738 /** @type {number} */ var maxI = Math.floor(uBounds[1]); 739 /** @type {number} */ var minJ = Math.floor(vBounds[0]); 740 /** @type {number} */ var maxJ = Math.floor(vBounds[1]); 741 742 // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode. 743 744 for (var j = minJ; j <= maxJ; j++) 745 for (var i = minI; i <= maxI; i++) { 746 /** @type {number} */ var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth()); 747 /** @type {number} */ var y = tcuTexVerifierUtil.wrap(sampler.wrapT, j, level.getHeight()); 748 /** @type {Array<number>} */ var color; 749 if (tcuTexLookupVerifier.isSRGB(level.getFormat())) { 750 color = tcuTexLookupVerifier.lookupFloat(level, sampler, x, y, coordZ); 751 } else { 752 color = tcuTexLookupVerifier.lookupScalar(level, sampler, x, y, coordZ); 753 } 754 755 if (tcuTexLookupVerifier.isColorValid(prec, color, result)) 756 return true; 757 } 758 759 return false; 760 }; 761 762 /** 763 * @param {tcuTexture.ConstPixelBufferAccess} level 764 * @param {tcuTexture.Sampler} sampler 765 * @param {tcuTexLookupVerifier.LookupPrecision} prec 766 * @param {Array<number>} coord vec3 767 * @param {Array<number>} result 768 * @return {boolean} 769 */ 770 tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec3 = function(level, sampler, prec, coord, result) { 771 /** @type {Array<number>} */ 772 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 773 sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]); 774 /** @type {Array<number>} */ 775 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 776 sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]); 777 /** @type {Array<number>} */ 778 var wBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 779 sampler.normalizedCoords, level.getDepth(), coord[2], prec.coordBits[2], prec.uvwBits[2]); 780 781 // Integer coordinates - without wrap mode 782 /** @type {number} */ var minI = Math.floor(uBounds[0]); 783 /** @type {number} */ var maxI = Math.floor(uBounds[1]); 784 /** @type {number} */ var minJ = Math.floor(vBounds[0]); 785 /** @type {number} */ var maxJ = Math.floor(vBounds[1]); 786 /** @type {number} */ var minK = Math.floor(wBounds[0]); 787 /** @type {number} */ var maxK = Math.floor(wBounds[1]); 788 789 // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode. 790 791 for (var k = minK; k <= maxK; k++) { 792 for (var j = minJ; j <= maxJ; j++) { 793 for (var i = minI; i <= maxI; i++) { 794 /** @type {number} */ var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth()); 795 /** @type {number} */ var y = tcuTexVerifierUtil.wrap(sampler.wrapT, j, level.getHeight()); 796 /** @type {number} */ var z = tcuTexVerifierUtil.wrap(sampler.wrapR, k, level.getDepth()); 797 /** @type {Array<number>} */ var color; 798 if (tcuTexLookupVerifier.isSRGB(level.getFormat())) { 799 color = tcuTexLookupVerifier.lookupFloat(level, sampler, x, y, z); 800 } else { 801 color = tcuTexLookupVerifier.lookupScalar(level, sampler, x, y, z); 802 } 803 804 if (tcuTexLookupVerifier.isColorValid(prec, color, result)) 805 return true; 806 } 807 } 808 } 809 810 return false; 811 }; 812 813 /** 814 * @param {tcuTexture.ConstPixelBufferAccess} level 815 * @param {tcuTexture.Sampler} sampler 816 * @param {tcuTexLookupVerifier.LookupPrecision} prec 817 * @param {number} coordX 818 * @param {number} coordY 819 * @param {Array<number>} result 820 * @return {boolean} 821 */ 822 tcuTexLookupVerifier.isLinearSampleResultValid_CoordXYAsNumber = function(level, sampler, prec, coordX, coordY, result) { 823 /** @type {Array<number>} */ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coordX, prec.coordBits[0], prec.uvwBits[0]); 824 825 /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5); 826 /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5); 827 828 /** @type {number} */ var w = level.getWidth(); 829 830 for (var i = minI; i <= maxI; i++) { 831 // Wrapped coordinates 832 /** @type {number} */ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w); 833 /** @type {number} */ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w); 834 835 // Bounds for filtering factors 836 /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1); 837 /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1); 838 839 /** @type {Array<number>} */ var colorA = tcuTexLookupVerifier.lookupFloat(level, sampler, x0, coordY, 0); 840 /** @type {Array<number>} */ var colorB = tcuTexLookupVerifier.lookupFloat(level, sampler, x1, coordY, 0); 841 842 if (tcuTexLookupVerifier.isLinearRangeValid(prec, colorA, colorB, [minA, maxA], result)) 843 return true; 844 } 845 846 return false; 847 }; 848 849 /** 850 * @param {tcuTexture.ConstPixelBufferAccess} level 851 * @param {tcuTexture.Sampler} sampler 852 * @param {tcuTexLookupVerifier.LookupPrecision} prec 853 * @param {Array<number>} coord vec2 854 * @param {number} coordZ int 855 * @param {Array<number>} result 856 * @return {boolean} 857 */ 858 tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec2AndInt = function(level, sampler, prec, coord, coordZ, result) { 859 /** @type {Array<number>} */ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]); 860 /** @type {Array<number>} */ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]); 861 862 // Integer coordinate bounds for (x0,y0) - without wrap mode 863 /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5); 864 /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5); 865 /** @type {number} */ var minJ = Math.floor(vBounds[0] - 0.5); 866 /** @type {number} */ var maxJ = Math.floor(vBounds[1] - 0.5); 867 868 /** @type {number} */ var w = level.getWidth(); 869 /** @type {number} */ var h = level.getHeight(); 870 871 /** @type {tcuTexture.TextureChannelClass} */ 872 var texClass = tcuTexture.getTextureChannelClass(level.getFormat().type); 873 874 /** @type {number} */ 875 var searchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) : 876 (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) : 877 0; // Step is computed for floating-point quads based on texel values. 878 879 // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode. 880 881 for (var j = minJ; j <= maxJ; j++) 882 for (var i = minI; i <= maxI; i++) { 883 // Wrapped coordinates 884 /** @type {number} */ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w); 885 /** @type {number} */ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w); 886 /** @type {number} */ var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j, h); 887 /** @type {number} */ var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j + 1, h); 888 889 // Bounds for filtering factors 890 /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1); 891 /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1); 892 /** @type {number} */ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1); 893 /** @type {number} */ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1); 894 895 /** @type {tcuTexLookupVerifier.ColorQuad} */ 896 var quad = tcuTexLookupVerifier.lookupQuad(level, sampler, x0, x1, y0, y1, coordZ); 897 898 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 899 searchStep = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad); 900 901 if (tcuTexLookupVerifier.isBilinearRangeValid(prec, quad, [minA, maxA], [minB, maxB], searchStep, result)) 902 return true; 903 } 904 905 return false; 906 }; 907 908 /** 909 * @param {tcuTexture.ConstPixelBufferAccess} level 910 * @param {tcuTexture.Sampler} sampler 911 * @param {tcuTexLookupVerifier.LookupPrecision} prec 912 * @param {Array<number>} coord vec3 913 * @param {Array<number>} result 914 * @return {boolean} 915 */ 916 tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec3 = function(level, sampler, prec, coord, result) { 917 /** @type {Array<number>} */ 918 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 919 sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]); 920 /** @type {Array<number>} */ 921 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 922 sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]); 923 /** @type {Array<number>} */ 924 var wBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 925 sampler.normalizedCoords, level.getDepth(), coord[2], prec.coordBits[2], prec.uvwBits[2]); 926 927 // Integer coordinate bounds for (x0,y0) - without wrap mode 928 /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5); 929 /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5); 930 /** @type {number} */ var minJ = Math.floor(vBounds[0] - 0.5); 931 /** @type {number} */ var maxJ = Math.floor(vBounds[1] - 0.5); 932 /** @type {number} */ var minK = Math.floor(wBounds[0] - 0.5); 933 /** @type {number} */ var maxK = Math.floor(wBounds[1] - 0.5); 934 935 /** @type {number} */ var w = level.getWidth(); 936 /** @type {number} */ var h = level.getHeight(); 937 /** @type {number} */ var d = level.getDepth(); 938 939 /** @type {tcuTexture.TextureChannelClass} */ 940 var texClass = tcuTexture.getTextureChannelClass(level.getFormat().type); 941 /** @type {number} */ 942 var searchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) : 943 (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) : 944 0; // Step is computed for floating-point quads based on texel values. 945 946 // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode. 947 948 for (var k = minK; k <= maxK; k++) { 949 for (var j = minJ; j <= maxJ; j++) { 950 for (var i = minI; i <= maxI; i++) { 951 // Wrapped coordinates 952 /** @type {number} */ var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w); 953 /** @type {number} */ var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w); 954 /** @type {number} */ var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j, h); 955 /** @type {number} */ var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j + 1, h); 956 /** @type {number} */ var z0 = tcuTexVerifierUtil.wrap(sampler.wrapR, k, d); 957 /** @type {number} */ var z1 = tcuTexVerifierUtil.wrap(sampler.wrapR, k + 1, d); 958 959 // Bounds for filtering factors 960 /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1); 961 /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1); 962 /** @type {number} */ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1); 963 /** @type {number} */ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1); 964 /** @type {number} */ var minC = deMath.clamp((wBounds[0] - 0.5) - k, 0, 1); 965 /** @type {number} */ var maxC = deMath.clamp((wBounds[1] - 0.5) - k, 0, 1); 966 967 /** @type {tcuTexLookupVerifier.ColorQuad} */ 968 var quad0 = tcuTexLookupVerifier.lookupQuad(level, sampler, x0, x1, y0, y1, z0); 969 /** @type {tcuTexLookupVerifier.ColorQuad} */ 970 var quad1 = tcuTexLookupVerifier.lookupQuad(level, sampler, x0, x1, y0, y1, z1); 971 972 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 973 searchStep = Math.min(tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad0), tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad1)); 974 975 if (tcuTexLookupVerifier.isTrilinearRangeValid(prec, quad0, quad1, [minA, maxA], [minB, maxB], [minC, maxC], searchStep, result)) 976 return true; 977 } 978 } 979 } 980 981 return false; 982 }; 983 984 /** 985 * @param {tcuTexture.ConstPixelBufferAccess} level0 986 * @param {tcuTexture.ConstPixelBufferAccess} level1 987 * @param {tcuTexture.Sampler} sampler 988 * @param {tcuTexLookupVerifier.LookupPrecision} prec 989 * @param {number} coord 990 * @param {number} coordY 991 * @param {Array<number>} fBounds 992 * @param {Array<number>} result 993 * @return {boolean} 994 */ 995 tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordXYAsNumber = function(level0, level1, sampler, prec, coord, coordY, fBounds, result) { 996 /** @type {number} */ var w0 = level0.getWidth(); 997 /** @type {number} */ var w1 = level1.getWidth(); 998 999 /** @type {Array<number>} */ 1000 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1001 sampler.normalizedCoords, w0, coord, prec.coordBits[0], prec.uvwBits[0]); 1002 /** @type {Array<number>} */ 1003 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1004 sampler.normalizedCoords, w1, coord, prec.coordBits[0], prec.uvwBits[0]); 1005 1006 // Integer coordinates - without wrap mode 1007 /** @type {number} */ var minI0 = Math.floor(uBounds0[0]); 1008 /** @type {number} */ var maxI0 = Math.floor(uBounds0[1]); 1009 /** @type {number} */ var minI1 = Math.floor(uBounds1[0]); 1010 /** @type {number} */ var maxI1 = Math.floor(uBounds1[1]); 1011 1012 for (var i0 = minI0; i0 <= maxI0; i0++) { 1013 for (var i1 = minI1; i1 <= maxI1; i1++) { 1014 /** @type {Array<number>} */ 1015 var c0 = tcuTexLookupVerifier.lookupFloat(level0, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0), coordY, 0); 1016 /** @type {Array<number>} */ 1017 var c1 = tcuTexLookupVerifier.lookupFloat(level1, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1), coordY, 0); 1018 1019 if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, fBounds, result)) 1020 return true; 1021 } 1022 } 1023 1024 return false; 1025 }; 1026 1027 /** 1028 * @param {tcuTexture.ConstPixelBufferAccess} level0 1029 * @param {tcuTexture.ConstPixelBufferAccess} level1 1030 * @param {tcuTexture.Sampler} sampler 1031 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1032 * @param {Array<number>} coord 1033 * @param {number} coordZ 1034 * @param {Array<number>} fBounds 1035 * @param {Array<number>} result 1036 * @return {boolean} 1037 */ 1038 tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec2AndInt = function(level0, level1, sampler, prec, coord, coordZ, fBounds, result) { 1039 /** @type {number} */ var w0 = level0.getWidth(); 1040 /** @type {number} */ var w1 = level1.getWidth(); 1041 /** @type {number} */ var h0 = level0.getHeight(); 1042 /** @type {number} */ var h1 = level1.getHeight(); 1043 1044 /** @type {Array<number>} */ 1045 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1046 sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1047 /** @type {Array<number>} */ 1048 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1049 sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1050 /** @type {Array<number>} */ 1051 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1052 sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1053 /** @type {Array<number>} */ 1054 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1055 sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1056 1057 // Integer coordinates - without wrap mode 1058 /** @type {number} */ var minI0 = Math.floor(uBounds0[0]); 1059 /** @type {number} */ var maxI0 = Math.floor(uBounds0[1]); 1060 /** @type {number} */ var minI1 = Math.floor(uBounds1[0]); 1061 /** @type {number} */ var maxI1 = Math.floor(uBounds1[1]); 1062 /** @type {number} */ var minJ0 = Math.floor(vBounds0[0]); 1063 /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1]); 1064 /** @type {number} */ var minJ1 = Math.floor(vBounds1[0]); 1065 /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1]); 1066 1067 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 1068 for (var i0 = minI0; i0 <= maxI0; i0++) { 1069 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 1070 for (var i1 = minI1; i1 <= maxI1; i1++) { 1071 /** @type {Array<number>} */ var c0 = tcuTexLookupVerifier.lookupFloat(level0, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0), tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0), coordZ); 1072 /** @type {Array<number>} */ var c1 = tcuTexLookupVerifier.lookupFloat(level1, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1), tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1), coordZ); 1073 1074 if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, fBounds, result)) 1075 return true; 1076 } 1077 } 1078 } 1079 } 1080 1081 return false; 1082 }; 1083 1084 /** 1085 * @param {tcuTexture.ConstPixelBufferAccess} level0 1086 * @param {tcuTexture.ConstPixelBufferAccess} level1 1087 * @param {tcuTexture.Sampler} sampler 1088 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1089 * @param {Array<number>} coord 1090 * @param {Array<number>} fBounds 1091 * @param {Array<number>} result 1092 * @return {boolean} 1093 */ 1094 tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec3 = function(level0, level1, sampler, prec, coord, fBounds, result) { 1095 /** @type {number} */ var w0 = level0.getWidth(); 1096 /** @type {number} */ var w1 = level1.getWidth(); 1097 /** @type {number} */ var h0 = level0.getHeight(); 1098 /** @type {number} */ var h1 = level1.getHeight(); 1099 /** @type {number} */ var d0 = level0.getDepth(); 1100 /** @type {number} */ var d1 = level1.getDepth(); 1101 1102 /** @type {Array<number>} */ 1103 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1104 sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1105 /** @type {Array<number>} */ 1106 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1107 sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1108 /** @type {Array<number>} */ 1109 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1110 sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1111 /** @type {Array<number>} */ 1112 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1113 sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1114 /** @type {Array<number>} */ 1115 var wBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1116 sampler.normalizedCoords, d0, coord[2], prec.coordBits[2], prec.uvwBits[2]); 1117 /** @type {Array<number>} */ 1118 var wBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1119 sampler.normalizedCoords, d1, coord[2], prec.coordBits[2], prec.uvwBits[2]); 1120 1121 // Integer coordinates - without wrap mode 1122 /** @type {number} */ var minI0 = Math.floor(uBounds0[0]); 1123 /** @type {number} */ var maxI0 = Math.floor(uBounds0[1]); 1124 /** @type {number} */ var minI1 = Math.floor(uBounds1[0]); 1125 /** @type {number} */ var maxI1 = Math.floor(uBounds1[1]); 1126 /** @type {number} */ var minJ0 = Math.floor(vBounds0[0]); 1127 /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1]); 1128 /** @type {number} */ var minJ1 = Math.floor(vBounds1[0]); 1129 /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1]); 1130 /** @type {number} */ var minK0 = Math.floor(wBounds0[0]); 1131 /** @type {number} */ var maxK0 = Math.floor(wBounds0[1]); 1132 /** @type {number} */ var minK1 = Math.floor(wBounds1[0]); 1133 /** @type {number} */ var maxK1 = Math.floor(wBounds1[1]); 1134 1135 for (var k0 = minK0; k0 <= maxK0; k0++) { 1136 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 1137 for (var i0 = minI0; i0 <= maxI0; i0++) { 1138 for (var k1 = minK1; k1 <= maxK1; k1++) { 1139 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 1140 for (var i1 = minI1; i1 <= maxI1; i1++) { 1141 /** @type {Array<number>} */ var c0 = tcuTexLookupVerifier.lookupFloat(level0, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0), tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0), tcuTexVerifierUtil.wrap(sampler.wrapR, k0, d0)); 1142 /** @type {Array<number>} */ var c1 = tcuTexLookupVerifier.lookupFloat(level1, sampler, tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1), tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1), tcuTexVerifierUtil.wrap(sampler.wrapR, k1, d1)); 1143 1144 if (tcuTexLookupVerifier.isLinearRangeValid(prec, c0, c1, fBounds, result)) 1145 return true; 1146 } 1147 } 1148 } 1149 } 1150 } 1151 } 1152 1153 return false; 1154 }; 1155 1156 /** 1157 * @param {tcuTexture.ConstPixelBufferAccess} level0 1158 * @param {tcuTexture.ConstPixelBufferAccess} level1 1159 * @param {tcuTexture.Sampler} sampler 1160 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1161 * @param {Array<number>} coord 1162 * @param {number} coordZ 1163 * @param {Array<number>} fBounds 1164 * @param {Array<number>} result 1165 * @return {boolean} 1166 */ 1167 tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec2AndInt = function(level0, level1, sampler, prec, coord, coordZ, fBounds, result) { 1168 // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent. 1169 // Right now this allows pairing any two valid bilinear quads. 1170 1171 /** @type {number} */ var w0 = level0.getWidth(); 1172 /** @type {number} */ var w1 = level1.getWidth(); 1173 /** @type {number} */ var h0 = level0.getHeight(); 1174 /** @type {number} */ var h1 = level1.getHeight(); 1175 1176 /** @type {Array<number>} */ 1177 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1178 sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1179 /** @type {Array<number>} */ 1180 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1181 sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1182 /** @type {Array<number>} */ 1183 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1184 sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1185 /** @type {Array<number>} */ 1186 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1187 sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1188 1189 // Integer coordinates - without wrap mode 1190 /** @type {number} */ var minI0 = Math.floor(uBounds0[0] - 0.5); 1191 /** @type {number} */ var maxI0 = Math.floor(uBounds0[1] - 0.5); 1192 /** @type {number} */ var minI1 = Math.floor(uBounds1[0] - 0.5); 1193 /** @type {number} */ var maxI1 = Math.floor(uBounds1[1] - 0.5); 1194 /** @type {number} */ var minJ0 = Math.floor(vBounds0[0] - 0.5); 1195 /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1] - 0.5); 1196 /** @type {number} */ var minJ1 = Math.floor(vBounds1[0] - 0.5); 1197 /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1] - 0.5); 1198 1199 /** @type {tcuTexture.TextureChannelClass} */ 1200 var texClass = tcuTexture.getTextureChannelClass(level0.getFormat().type); 1201 /** @type {number} */ var cSearchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) : 1202 (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) : 1203 0; // Step is computed for floating-point quads based on texel values. 1204 1205 /** @type {number} */ var x0; 1206 /** @type {number} */ var x1; 1207 /** @type {number} */ var y0; 1208 /** @type {number} */ var y1; 1209 1210 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 1211 for (var i0 = minI0; i0 <= maxI0; i0++) { 1212 /** @type {number} */ var searchStep0; 1213 1214 x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0); 1215 x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0 + 1, w0); 1216 y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0); 1217 y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0 + 1, h0); 1218 1219 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1220 var quad0 = tcuTexLookupVerifier.lookupQuad(level0, sampler, x0, x1, y0, y1, coordZ); 1221 1222 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 1223 searchStep0 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad0); 1224 else 1225 searchStep0 = cSearchStep; 1226 1227 /** @type {number} */ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1); 1228 /** @type {number} */ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1); 1229 /** @type {number} */ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1); 1230 /** @type {number} */ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1); 1231 1232 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 1233 for (var i1 = minI1; i1 <= maxI1; i1++) { 1234 /** @type {number} */ var searchStep1; 1235 1236 x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1); 1237 x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1 + 1, w1); 1238 y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1); 1239 y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1 + 1, h1); 1240 1241 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1242 var quad1 = tcuTexLookupVerifier.lookupQuad(level1, sampler, x0, x1, y0, y1, coordZ); 1243 1244 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 1245 searchStep1 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad1); 1246 else 1247 searchStep1 = cSearchStep; 1248 1249 /** @type {number} */ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1); 1250 /** @type {number} */ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1); 1251 /** @type {number} */ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1); 1252 /** @type {number} */ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1); 1253 1254 if (tcuTexLookupVerifier.is2DTrilinearFilterResultValid(prec, quad0, quad1, [minA0, maxA0], [minB0, maxB0], [minA1, maxA1], [minB1, maxB1], 1255 fBounds, Math.min(searchStep0, searchStep1), result)) 1256 return true; 1257 } 1258 } 1259 } 1260 } 1261 1262 return false; 1263 }; 1264 1265 /** 1266 * @param {tcuTexture.ConstPixelBufferAccess} level0 1267 * @param {tcuTexture.ConstPixelBufferAccess} level1 1268 * @param {tcuTexture.Sampler} sampler 1269 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1270 * @param {Array<number>} coord 1271 * @param {Array<number>} fBounds 1272 * @param {Array<number>} result 1273 * @return {boolean} 1274 */ 1275 tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec3 = function(level0, level1, sampler, prec, coord, fBounds, result) { 1276 // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent. 1277 // Right now this allows pairing any two valid bilinear quads. 1278 1279 /** @type {number} */ var w0 = level0.getWidth(); 1280 /** @type {number} */ var w1 = level1.getWidth(); 1281 /** @type {number} */ var h0 = level0.getHeight(); 1282 /** @type {number} */ var h1 = level1.getHeight(); 1283 /** @type {number} */ var d0 = level0.getDepth(); 1284 /** @type {number} */ var d1 = level1.getDepth(); 1285 1286 /** @type {Array<number>} */ 1287 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1288 sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1289 /** @type {Array<number>} */ 1290 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1291 sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]); 1292 /** @type {Array<number>} */ 1293 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1294 sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1295 /** @type {Array<number>} */ 1296 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1297 sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]); 1298 /** @type {Array<number>} */ 1299 var wBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1300 sampler.normalizedCoords, d0, coord[2], prec.coordBits[2], prec.uvwBits[2]); 1301 /** @type {Array<number>} */ 1302 var wBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds( 1303 sampler.normalizedCoords, d1, coord[2], prec.coordBits[2], prec.uvwBits[2]); 1304 1305 // Integer coordinates - without wrap mode 1306 /** @type {number} */ var minI0 = Math.floor(uBounds0[0] - 0.5); 1307 /** @type {number} */ var maxI0 = Math.floor(uBounds0[1] - 0.5); 1308 /** @type {number} */ var minI1 = Math.floor(uBounds1[0] - 0.5); 1309 /** @type {number} */ var maxI1 = Math.floor(uBounds1[1] - 0.5); 1310 /** @type {number} */ var minJ0 = Math.floor(vBounds0[0] - 0.5); 1311 /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1] - 0.5); 1312 /** @type {number} */ var minJ1 = Math.floor(vBounds1[0] - 0.5); 1313 /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1] - 0.5); 1314 /** @type {number} */ var minK0 = Math.floor(wBounds0[0] - 0.5); 1315 /** @type {number} */ var maxK0 = Math.floor(wBounds0[1] - 0.5); 1316 /** @type {number} */ var minK1 = Math.floor(wBounds1[0] - 0.5); 1317 /** @type {number} */ var maxK1 = Math.floor(wBounds1[1] - 0.5); 1318 1319 /** @type {tcuTexture.TextureChannelClass} */ 1320 var texClass = tcuTexture.getTextureChannelClass(level0.getFormat().type); 1321 /** @type {number} */ var cSearchStep = texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) : 1322 texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) : 1323 0; // Step is computed for floating-point quads based on texel values. 1324 1325 /** @type {number} */ var x0; 1326 /** @type {number} */ var x1; 1327 /** @type {number} */ var y0; 1328 /** @type {number} */ var y1; 1329 /** @type {number} */ var z0; 1330 /** @type {number} */ var z1; 1331 1332 for (var k0 = minK0; k0 <= maxK0; k0++) { 1333 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 1334 for (var i0 = minI0; i0 <= maxI0; i0++) { 1335 /** @type {number} */ var searchStep0; 1336 1337 x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0); 1338 x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0 + 1, w0); 1339 y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0); 1340 y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0 + 1, h0); 1341 z0 = tcuTexVerifierUtil.wrap(sampler.wrapR, k0, d0); 1342 z1 = tcuTexVerifierUtil.wrap(sampler.wrapR, k0 + 1, d0); 1343 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1344 var quad00 = tcuTexLookupVerifier.lookupQuad(level0, sampler, x0, x1, y0, y1, z0); 1345 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1346 var quad01 = tcuTexLookupVerifier.lookupQuad(level0, sampler, x0, x1, y0, y1, z1); 1347 1348 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 1349 searchStep0 = Math.min(tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad00), tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad01)); 1350 else 1351 searchStep0 = cSearchStep; 1352 1353 /** @type {number} */ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1); 1354 /** @type {number} */ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1); 1355 /** @type {number} */ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1); 1356 /** @type {number} */ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1); 1357 /** @type {number} */ var minC0 = deMath.clamp((wBounds0[0] - 0.5) - k0, 0, 1); 1358 /** @type {number} */ var maxC0 = deMath.clamp((wBounds0[1] - 0.5) - k0, 0, 1); 1359 1360 for (var k1 = minK1; k1 <= maxK1; k1++) { 1361 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 1362 for (var i1 = minI1; i1 <= maxI1; i1++) { 1363 1364 /** @type {number} */ var searchStep1; 1365 1366 x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1); 1367 x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1 + 1, w1); 1368 y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1); 1369 y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1 + 1, h1); 1370 z0 = tcuTexVerifierUtil.wrap(sampler.wrapR, k1, d1); 1371 z1 = tcuTexVerifierUtil.wrap(sampler.wrapR, k1 + 1, d1); 1372 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1373 var quad10 = tcuTexLookupVerifier.lookupQuad(level1, sampler, x0, x1, y0, y1, z0); 1374 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1375 var quad11 = tcuTexLookupVerifier.lookupQuad(level1, sampler, x0, x1, y0, y1, z1); 1376 1377 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 1378 searchStep1 = Math.min(tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad10), tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad11)); 1379 else 1380 searchStep1 = cSearchStep; 1381 1382 /** @type {number} */ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1); 1383 /** @type {number} */ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1); 1384 /** @type {number} */ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1); 1385 /** @type {number} */ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1); 1386 /** @type {number} */ var minC1 = deMath.clamp((wBounds1[0] - 0.5) - k1, 0, 1); 1387 /** @type {number} */ var maxC1 = deMath.clamp((wBounds1[1] - 0.5) - k1, 0, 1); 1388 1389 if (tcuTexLookupVerifier.is3DTrilinearFilterResultValid( 1390 prec, quad00, quad01, quad10, quad11, 1391 [minA0, maxA0], [minB0, maxB0], [minC0, maxC0], 1392 [minA1, maxA1], [minB1, maxB1], [minC1, maxC1], 1393 fBounds, Math.min(searchStep0, searchStep1), result)) 1394 return true; 1395 } 1396 } 1397 } 1398 } 1399 } 1400 } 1401 1402 return false; 1403 }; 1404 1405 /** 1406 * @param {tcuTexture.ConstPixelBufferAccess} level 1407 * @param {tcuTexture.Sampler} sampler 1408 * @param {tcuTexture.FilterMode} filterMode 1409 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1410 * @param {number} coordX 1411 * @param {number} coordY 1412 * @param {Array<number>} result 1413 * @return {boolean} 1414 */ 1415 tcuTexLookupVerifier.isLevelSampleResultValid_CoordXYAsNumber = function(level, sampler, filterMode, prec, coordX, coordY, result) { 1416 if (filterMode == tcuTexture.FilterMode.LINEAR) 1417 return tcuTexLookupVerifier.isLinearSampleResultValid_CoordXYAsNumber(level, sampler, prec, coordX, coordY, result); 1418 else 1419 return tcuTexLookupVerifier.isNearestSampleResultValid_CoordXYAsNumber(level, sampler, prec, coordX, coordY, result); 1420 }; 1421 1422 /** 1423 * @param {tcuTexture.ConstPixelBufferAccess} level 1424 * @param {tcuTexture.Sampler} sampler 1425 * @param {tcuTexture.FilterMode} filterMode 1426 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1427 * @param {Array<number>} coord 1428 * @param {number} coordZ 1429 * @param {Array<number>} result 1430 * @return {boolean} 1431 */ 1432 tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt = function(level, sampler, filterMode, prec, coord, coordZ, result) { 1433 if (filterMode == tcuTexture.FilterMode.LINEAR) 1434 return tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec2AndInt(level, sampler, prec, coord, coordZ, result); 1435 else 1436 return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt(level, sampler, prec, coord, coordZ, result); 1437 }; 1438 1439 /** 1440 * @param {tcuTexture.ConstPixelBufferAccess} level 1441 * @param {tcuTexture.Sampler} sampler 1442 * @param {tcuTexture.FilterMode} filterMode 1443 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1444 * @param {Array<number>} coord 1445 * @param {Array<number>} result 1446 * @return {boolean} 1447 */ 1448 tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3 = function(level, sampler, filterMode, prec, coord, result) { 1449 if (filterMode == tcuTexture.FilterMode.LINEAR) 1450 return tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec3(level, sampler, prec, coord, result); 1451 else 1452 return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec3(level, sampler, prec, coord, result); 1453 }; 1454 1455 /** 1456 * @param {tcuTexture.ConstPixelBufferAccess} level0 1457 * @param {tcuTexture.ConstPixelBufferAccess} level1 1458 * @param {tcuTexture.Sampler} sampler 1459 * @param {tcuTexture.FilterMode} levelFilter 1460 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1461 * @param {Array<number>} coord 1462 * @param {number} coordZ 1463 * @param {Array<number>} fBounds 1464 * @param {Array<number>} result 1465 * @return {boolean} 1466 */ 1467 tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec2AndInt = function(level0, level1, sampler, levelFilter, prec, coord, coordZ, fBounds, result) { 1468 if (levelFilter == tcuTexture.FilterMode.LINEAR) 1469 return tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec2AndInt(level0, level1, sampler, prec, coord, coordZ, fBounds, result); 1470 else 1471 return tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec2AndInt(level0, level1, sampler, prec, coord, coordZ, fBounds, result); 1472 }; 1473 1474 /** 1475 * @param {tcuTexture.ConstPixelBufferAccess} level0 1476 * @param {tcuTexture.ConstPixelBufferAccess} level1 1477 * @param {tcuTexture.Sampler} sampler 1478 * @param {tcuTexture.FilterMode} levelFilter 1479 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1480 * @param {Array<number>} coord 1481 * @param {Array<number>} fBounds 1482 * @param {Array<number>} result 1483 * @return {boolean} 1484 */ 1485 tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec3 = function(level0, level1, sampler, levelFilter, prec, coord, fBounds, result) { 1486 if (levelFilter == tcuTexture.FilterMode.LINEAR) 1487 return tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec3(level0, level1, sampler, prec, coord, fBounds, result); 1488 else 1489 return tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec3(level0, level1, sampler, prec, coord, fBounds, result); 1490 }; 1491 1492 /** 1493 * @param {tcuTexture.Texture2DView} texture 1494 * @param {tcuTexture.Sampler} sampler 1495 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1496 * @param {Array<number>} coord 1497 * @param {Array<number>} lodBounds 1498 * @param {Array<number>} result 1499 * @return {boolean} 1500 */ 1501 tcuTexLookupVerifier.isLookupResultValid_Texture2DView = function(texture, sampler, prec, coord, lodBounds, result) { 1502 /** @type {number} */ var minLod = lodBounds[0]; 1503 /** @type {number} */ var maxLod = lodBounds[1]; 1504 /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold; 1505 /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold; 1506 1507 assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true); 1508 1509 /** @type {number} */ var minLevel; 1510 /** @type {number} */ var maxLevel; 1511 1512 if (canBeMagnified) 1513 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, result)) 1514 return true; 1515 1516 if (canBeMinified) { 1517 /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter); 1518 /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter); 1519 /** @type {number} */ var minTexLevel = 0; 1520 /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1; 1521 1522 assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true); 1523 1524 if (isLinearMipmap && minTexLevel < maxTexLevel) { 1525 minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1); 1526 maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1); 1527 1528 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1529 1530 for (var level = minLevel; level <= maxLevel; level++) { 1531 /** @type {number} */ var minF = deMath.clamp(minLod - level, 0, 1); 1532 /** @type {number} */ var maxF = deMath.clamp(maxLod - level, 0, 1); 1533 1534 if (tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, [minF, maxF], result)) 1535 return true; 1536 } 1537 } else if (isNearestMipmap) { 1538 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made 1539 // decision to allow floor(lod + 0.5) as well. 1540 minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel); 1541 maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel); 1542 1543 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1544 1545 for (var level = minLevel; level <= maxLevel; level++) { 1546 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, result)) 1547 return true; 1548 } 1549 } else { 1550 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, result)) 1551 return true; 1552 } 1553 } 1554 1555 return false; 1556 }; 1557 1558 /** 1559 * @param {tcuTexture.TextureCubeView} texture 1560 * @param {tcuTexture.Sampler} sampler 1561 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1562 * @param {Array<number>} coord 1563 * @param {Array<number>} lodBounds 1564 * @param {Array<number>} result 1565 * @return {boolean} 1566 */ 1567 tcuTexLookupVerifier.isLookupResultValid_TextureCubeView = function(texture, sampler, prec, coord, lodBounds, result) { 1568 /** @type {number} */ var numPossibleFaces = 0; 1569 1570 assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true); 1571 1572 /** @type {Array<tcuTexture.CubeFace>} */ var possibleFaces = tcuTexVerifierUtil.getPossibleCubeFaces(coord, prec.coordBits); 1573 1574 /** @type {number} */ var minLevel; 1575 /** @type {number} */ var maxLevel; 1576 1577 if (!possibleFaces) 1578 return true; // Result is undefined. 1579 1580 for (var tryFaceNdx = 0; tryFaceNdx < possibleFaces.length; tryFaceNdx++) { 1581 /** @type {tcuTexture.CubeFaceCoords} */ 1582 var faceCoords = new tcuTexture.CubeFaceCoords(possibleFaces[tryFaceNdx], tcuTexture.projectToFace(possibleFaces[tryFaceNdx], coord)); 1583 /** @type {number} */ var minLod = lodBounds[0]; 1584 /** @type {number} */ var maxLod = lodBounds[1]; 1585 /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold; 1586 /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold; 1587 1588 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces = []; 1589 if (canBeMagnified) { 1590 tcuTexLookupVerifier.getCubeLevelFaces(texture, 0, faces); 1591 1592 if (tcuTexLookupVerifier.isCubeLevelSampleResultValid(faces, sampler, sampler.magFilter, prec, faceCoords, result)) 1593 return true; 1594 } 1595 1596 if (canBeMinified) { 1597 /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter); 1598 /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter); 1599 /** @type {number} */ var minTexLevel = 0; 1600 /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1; 1601 1602 assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true); 1603 1604 if (isLinearMipmap && minTexLevel < maxTexLevel) { 1605 minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1); 1606 maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1); 1607 1608 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1609 1610 for (var levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++) { 1611 /** @type {number} */ var minF = deMath.clamp(minLod - levelNdx, 0, 1); 1612 /** @type {number} */ var maxF = deMath.clamp(maxLod - levelNdx, 0, 1); 1613 1614 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces0 = []; 1615 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces1 = []; 1616 1617 tcuTexLookupVerifier.getCubeLevelFaces(texture, levelNdx, faces0); 1618 tcuTexLookupVerifier.getCubeLevelFaces(texture, levelNdx + 1, faces1); 1619 1620 if (tcuTexLookupVerifier.isCubeMipmapLinearSampleResultValid(faces0, faces1, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, [minF, maxF], result)) 1621 return true; 1622 } 1623 } else if (isNearestMipmap) { 1624 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made 1625 // decision to allow floor(lod + 0.5) as well. 1626 minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel); 1627 maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel); 1628 1629 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1630 1631 for (var levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++) { 1632 tcuTexLookupVerifier.getCubeLevelFaces(texture, levelNdx, faces); 1633 1634 if (tcuTexLookupVerifier.isCubeLevelSampleResultValid(faces, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, result)) 1635 return true; 1636 } 1637 } else { 1638 tcuTexLookupVerifier.getCubeLevelFaces(texture, 0, faces); 1639 1640 if (tcuTexLookupVerifier.isCubeLevelSampleResultValid(faces, sampler, sampler.minFilter, prec, faceCoords, result)) 1641 return true; 1642 } 1643 } 1644 } 1645 1646 return false; 1647 }; 1648 1649 /** 1650 * @param {tcuTexture.Texture2DArrayView} texture 1651 * @param {tcuTexture.Sampler} sampler 1652 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1653 * @param {Array<number>} coord 1654 * @param {Array<number>} lodBounds 1655 * @param {Array<number>} result 1656 * @return {boolean} 1657 */ 1658 tcuTexLookupVerifier.isLookupResultValid_Texture2DArrayView = function(texture, sampler, prec, coord, lodBounds, result) { 1659 /** @type {Array<number>} */ var layerRange = tcuTexLookupVerifier.computeLayerRange(texture.getNumLayers(), prec.coordBits[2], coord[2]); 1660 /** @type {Array<number>} */ var coordXY = deMath.swizzle(coord, [0, 1]); 1661 /** @type {number} */ var minLod = lodBounds[0]; 1662 /** @type {number} */ var maxLod = lodBounds[1]; 1663 /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold; 1664 /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold; 1665 1666 assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true); 1667 /** @type {number} */ var minLevel; 1668 /** @type {number} */ var maxLevel; 1669 1670 for (var layer = layerRange[0]; layer <= layerRange[1]; layer++) { 1671 if (canBeMagnified) { 1672 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.magFilter, prec, coordXY, layer, result)) 1673 return true; 1674 } 1675 1676 if (canBeMinified) { 1677 /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter); 1678 /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter); 1679 /** @type {number} */ var minTexLevel = 0; 1680 /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1; 1681 1682 assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true); 1683 1684 if (isLinearMipmap && minTexLevel < maxTexLevel) { 1685 minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1); 1686 maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1); 1687 1688 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1689 1690 for (var level = minLevel; level <= maxLevel; level++) { 1691 /** @type {number} */ var minF = deMath.clamp(minLod - level, 0, 1); 1692 /** @type {number} */ var maxF = deMath.clamp(maxLod - level, 0, 1); 1693 1694 if (tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coordXY, layer, [minF, maxF], result)) 1695 return true; 1696 } 1697 } else if (isNearestMipmap) { 1698 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made 1699 // decision to allow floor(lod + 0.5) as well. 1700 minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel); 1701 maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel); 1702 1703 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1704 1705 for (var level = minLevel; level <= maxLevel; level++) { 1706 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coordXY, layer, result)) 1707 return true; 1708 } 1709 } else { 1710 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(texture.getLevel(0), sampler, sampler.minFilter, prec, coordXY, layer, result)) 1711 return true; 1712 } 1713 } 1714 } 1715 1716 return false; 1717 }; 1718 1719 /** 1720 * @param {tcuTexture.Texture3DView} texture 1721 * @param {tcuTexture.Sampler} sampler 1722 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1723 * @param {Array<number>} coord 1724 * @param {Array<number>} lodBounds 1725 * @param {Array<number>} result 1726 * @return {boolean} 1727 */ 1728 tcuTexLookupVerifier.isLookupResultValid = function(texture, sampler, prec, coord, lodBounds, result) { 1729 /** @type {number} */ var minLod = lodBounds[0]; 1730 /** @type {number} */ var maxLod = lodBounds[1]; 1731 /** @type {boolean} */ var canBeMagnified = minLod <= sampler.lodThreshold; 1732 /** @type {boolean} */ var canBeMinified = maxLod > sampler.lodThreshold; 1733 1734 assertMsgOptions(tcuTexLookupVerifier.isSamplerSupported(sampler), 'Sampler not supported.', false, true); 1735 1736 /** @type {number} */ var minLevel; 1737 /** @type {number} */ var maxLevel; 1738 1739 if (canBeMagnified) 1740 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, result)) 1741 return true; 1742 1743 if (canBeMinified) { 1744 /** @type {boolean} */ var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter); 1745 /** @type {boolean} */ var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter); 1746 /** @type {number} */ var minTexLevel = 0; 1747 /** @type {number} */ var maxTexLevel = texture.getNumLevels() - 1; 1748 1749 assertMsgOptions(minTexLevel <= maxTexLevel, 'minTexLevel > maxTexLevel', false, true); 1750 1751 if (isLinearMipmap && minTexLevel < maxTexLevel) { 1752 minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1); 1753 maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1); 1754 1755 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1756 1757 for (var level = minLevel; level <= maxLevel; level++) { 1758 /** @type {number} */ var minF = deMath.clamp(minLod - level, 0, 1); 1759 /** @type {number} */ var maxF = deMath.clamp(maxLod - level, 0, 1); 1760 1761 if (tcuTexLookupVerifier.isMipmapLinearSampleResultValid_CoordAsVec3(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, [minF, maxF], result)) 1762 return true; 1763 } 1764 } else if (isNearestMipmap) { 1765 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made 1766 // decision to allow floor(lod + 0.5) as well. 1767 minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel); 1768 maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel); 1769 1770 assertMsgOptions(minLevel <= maxLevel, 'minLevel > maxLevel', false, true); 1771 1772 for (var level = minLevel; level <= maxLevel; level++) { 1773 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, result)) 1774 return true; 1775 } 1776 } else { 1777 if (tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, result)) 1778 return true; 1779 } 1780 } 1781 1782 return false; 1783 }; 1784 1785 /** 1786 * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces (&faces)[CUBEFACE_LAST] 1787 * @param {tcuTexture.Sampler} sampler 1788 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1789 * @param {tcuTexture.CubeFaceCoords} coords 1790 * @param {Array<number>} result 1791 * @return {boolean} 1792 */ 1793 tcuTexLookupVerifier.isSeamlessLinearSampleResultValid = function(faces, sampler, prec, coords, result) { 1794 /** @type {number} */ var size = faces[coords.face].getWidth(); 1795 1796 /** @type {Array<number>} */ var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits[0], prec.uvwBits[0]); 1797 /** @type {Array<number>} */ var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits[1], prec.uvwBits[1]); 1798 1799 // Integer coordinate bounds for (x0,y0) - without wrap mode 1800 /** @type {number} */ var minI = Math.floor(uBounds[0] - 0.5); 1801 /** @type {number} */ var maxI = Math.floor(uBounds[1] - 0.5); 1802 /** @type {number} */ var minJ = Math.floor(vBounds[0] - 0.5); 1803 /** @type {number} */ var maxJ = Math.floor(vBounds[1] - 0.5); 1804 1805 /** @type {tcuTexture.TextureChannelClass} */ var texClass = tcuTexture.getTextureChannelClass(faces[coords.face].getFormat().type); 1806 /** @type {number} */ var searchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) : 1807 (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) : 1808 0; // Step is computed for floating-point quads based on texel values. 1809 1810 for (var j = minJ; j <= maxJ; j++) { 1811 for (var i = minI; i <= maxI; i++) { 1812 /** @type {tcuTexture.CubeFaceCoords} */ var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 0]), size); 1813 /** @type {tcuTexture.CubeFaceCoords} */ var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 0]), size); 1814 /** @type {tcuTexture.CubeFaceCoords} */ var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 1]), size); 1815 /** @type {tcuTexture.CubeFaceCoords} */ var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 1]), size); 1816 1817 // If any of samples is out of both edges, implementations can do pretty much anything according to spec. 1818 // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color. 1819 if (c00 == null || c01 == null || c10 == null || c11 == null || 1820 c00.face == null || c01.face == null || c10.face == null || c11.face == null) 1821 return true; 1822 1823 // Bounds for filtering factors 1824 /** @type {number} */ var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1); 1825 /** @type {number} */ var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1); 1826 /** @type {number} */ var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1); 1827 /** @type {number} */ var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1); 1828 1829 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1830 var quad = new tcuTexLookupVerifier.ColorQuad([], [], [], []); 1831 quad.p00 = tcuTexLookupVerifier.lookupFloat(faces[c00.face], sampler, c00.s, c00.t, 0); 1832 quad.p10 = tcuTexLookupVerifier.lookupFloat(faces[c10.face], sampler, c10.s, c10.t, 0); 1833 quad.p01 = tcuTexLookupVerifier.lookupFloat(faces[c01.face], sampler, c01.s, c01.t, 0); 1834 quad.p11 = tcuTexLookupVerifier.lookupFloat(faces[c11.face], sampler, c11.s, c11.t, 0); 1835 1836 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 1837 searchStep = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad); 1838 1839 if (tcuTexLookupVerifier.isBilinearRangeValid(prec, quad, [minA, maxA], [minB, maxB], searchStep, result)) 1840 return true; 1841 } 1842 } 1843 1844 return false; 1845 }; 1846 1847 /** 1848 * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces0 (&faces0)[CUBEFACE_LAST] 1849 * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces1 (&faces1)[CUBEFACE_LAST] 1850 * @param {tcuTexture.Sampler} sampler 1851 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1852 * @param {tcuTexture.CubeFaceCoords} coords 1853 * @param {Array<number>} fBounds 1854 * @param {Array<number>} result 1855 * @return {boolean} 1856 */ 1857 tcuTexLookupVerifier.isSeamplessLinearMipmapLinearSampleResultValid = function(faces0, faces1, sampler, prec, coords, fBounds, result) { 1858 // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent. 1859 // Right now this allows pairing any two valid bilinear quads. 1860 /** @type {number} */ var size0 = faces0[coords.face].getWidth(); 1861 /** @type {number} */ var size1 = faces1[coords.face].getWidth(); 1862 1863 /** @type {Array<number>} */ var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.s, prec.coordBits[0], prec.uvwBits[0]); 1864 /** @type {Array<number>} */ var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.s, prec.coordBits[0], prec.uvwBits[0]); 1865 /** @type {Array<number>} */ var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.t, prec.coordBits[1], prec.uvwBits[1]); 1866 /** @type {Array<number>} */ var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.t, prec.coordBits[1], prec.uvwBits[1]); 1867 1868 // Integer coordinates - without wrap mode 1869 /** @type {number} */ var minI0 = Math.floor(uBounds0[0] - 0.5); 1870 /** @type {number} */ var maxI0 = Math.floor(uBounds0[1] - 0.5); 1871 /** @type {number} */ var minI1 = Math.floor(uBounds1[0] - 0.5); 1872 /** @type {number} */ var maxI1 = Math.floor(uBounds1[1] - 0.5); 1873 /** @type {number} */ var minJ0 = Math.floor(vBounds0[0] - 0.5); 1874 /** @type {number} */ var maxJ0 = Math.floor(vBounds0[1] - 0.5); 1875 /** @type {number} */ var minJ1 = Math.floor(vBounds1[0] - 0.5); 1876 /** @type {number} */ var maxJ1 = Math.floor(vBounds1[1] - 0.5); 1877 1878 /** @type {tcuTexture.TextureChannelClass} */ var texClass = tcuTexture.getTextureChannelClass(faces0[coords.face].getFormat().type); 1879 /** @type {number} */ var cSearchStep = (texClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForUnorm(prec) : 1880 (texClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT) ? tcuTexLookupVerifier.computeBilinearSearchStepForSnorm(prec) : 1881 0; // Step is computed for floating-point quads based on texel values. 1882 1883 /** @type {tcuTexture.CubeFaceCoords} */ var c00; 1884 /** @type {tcuTexture.CubeFaceCoords} */ var c10; 1885 /** @type {tcuTexture.CubeFaceCoords} */ var c01; 1886 /** @type {tcuTexture.CubeFaceCoords} */ var c11; 1887 1888 for (var j0 = minJ0; j0 <= maxJ0; j0++) { 1889 for (var i0 = minI0; i0 <= maxI0; i0++) { 1890 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1891 var quad0 = new tcuTexLookupVerifier.ColorQuad([], [], [], []); 1892 /** @type {number} */ var searchStep0; 1893 1894 c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 0]), size0); 1895 c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 0]), size0); 1896 c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 1]), size0); 1897 c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 1]), size0); 1898 1899 // If any of samples is out of both edges, implementations can do pretty much anything according to spec. 1900 // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color. 1901 if (c00 == null || c01 == null || c10 == null || c11 == null || 1902 c00.face == null || c01.face == null || c10.face == null || c11.face == null) 1903 return true; 1904 1905 quad0.p00 = tcuTexLookupVerifier.lookupFloat(faces0[c00.face], sampler, c00.s, c00.t, 0); 1906 quad0.p10 = tcuTexLookupVerifier.lookupFloat(faces0[c10.face], sampler, c10.s, c10.t, 0); 1907 quad0.p01 = tcuTexLookupVerifier.lookupFloat(faces0[c01.face], sampler, c01.s, c01.t, 0); 1908 quad0.p11 = tcuTexLookupVerifier.lookupFloat(faces0[c11.face], sampler, c11.s, c11.t, 0); 1909 1910 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 1911 searchStep0 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad0); 1912 else 1913 searchStep0 = cSearchStep; 1914 1915 /** @type {number} */ var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1); 1916 /** @type {number} */ var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1); 1917 /** @type {number} */ var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1); 1918 /** @type {number} */ var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1); 1919 1920 for (var j1 = minJ1; j1 <= maxJ1; j1++) { 1921 for (var i1 = minI1; i1 <= maxI1; i1++) { 1922 /** @type {tcuTexLookupVerifier.ColorQuad} */ 1923 var quad1 = new tcuTexLookupVerifier.ColorQuad([], [], [], []); 1924 /** @type {number} */ var searchStep1; 1925 1926 c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 0]), size1); 1927 c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 0]), size1); 1928 c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 1]), size1); 1929 c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 1]), size1); 1930 1931 if (c00 == null || c01 == null || c10 == null || c11 == null || 1932 c00.face == null || c01.face == null || c10.face == null || c11.face == null) 1933 return true; 1934 1935 quad1.p00 = tcuTexLookupVerifier.lookupFloat(faces1[c00.face], sampler, c00.s, c00.t, 0); 1936 quad1.p10 = tcuTexLookupVerifier.lookupFloat(faces1[c10.face], sampler, c10.s, c10.t, 0); 1937 quad1.p01 = tcuTexLookupVerifier.lookupFloat(faces1[c01.face], sampler, c01.s, c01.t, 0); 1938 quad1.p11 = tcuTexLookupVerifier.lookupFloat(faces1[c11.face], sampler, c11.s, c11.t, 0); 1939 1940 if (texClass == tcuTexture.TextureChannelClass.FLOATING_POINT) 1941 searchStep1 = tcuTexLookupVerifier.computeBilinearSearchStepFromFloatQuad(prec, quad1); 1942 else 1943 searchStep1 = cSearchStep; 1944 1945 /** @type {number} */ var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1); 1946 /** @type {number} */ var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1); 1947 /** @type {number} */ var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1); 1948 /** @type {number} */ var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1); 1949 1950 if (tcuTexLookupVerifier.is2DTrilinearFilterResultValid(prec, quad0, quad1, [minA0, maxA0], [minB0, maxB0], [minA1, maxA1], [minB1, maxB1], 1951 fBounds, Math.min(searchStep0, searchStep1), result)) 1952 return true; 1953 } 1954 } 1955 } 1956 } 1957 1958 return false; 1959 }; 1960 1961 /** 1962 * @param {Array<tcuTexture.ConstPixelBufferAccess>} level (&level)[CUBEFACE_LAST] 1963 * @param {tcuTexture.Sampler} sampler 1964 * @param {tcuTexture.FilterMode} filterMode 1965 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1966 * @param {tcuTexture.CubeFaceCoords} coords 1967 * @param {Array<number>} result 1968 * @return {boolean} 1969 */ 1970 tcuTexLookupVerifier.isCubeLevelSampleResultValid = function(level, sampler, filterMode, prec, coords, result) { 1971 if (filterMode == tcuTexture.FilterMode.LINEAR) { 1972 if (sampler.seamlessCubeMap) 1973 return tcuTexLookupVerifier.isSeamlessLinearSampleResultValid(level, sampler, prec, coords, result); 1974 else 1975 return tcuTexLookupVerifier.isLinearSampleResultValid_CoordAsVec2AndInt(level[coords.face], sampler, prec, [coords.s, coords.t], 0, result); 1976 } else 1977 return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt(level[coords.face], sampler, prec, [coords.s, coords.t], 0, result); 1978 }; 1979 1980 /** 1981 * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces0 (&faces0)[CUBEFACE_LAST] 1982 * @param {Array<tcuTexture.ConstPixelBufferAccess>} faces1 (&faces1)[CUBEFACE_LAST] 1983 * @param {tcuTexture.Sampler} sampler 1984 * @param {tcuTexture.FilterMode} levelFilter 1985 * @param {tcuTexLookupVerifier.LookupPrecision} prec 1986 * @param {tcuTexture.CubeFaceCoords} coords 1987 * @param {Array<number>} fBounds 1988 * @param {Array<number>} result 1989 * @return {boolean} 1990 */ 1991 tcuTexLookupVerifier.isCubeMipmapLinearSampleResultValid = function(faces0, faces1, sampler, levelFilter, prec, coords, fBounds, result) { 1992 if (levelFilter == tcuTexture.FilterMode.LINEAR) { 1993 if (sampler.seamlessCubeMap) 1994 return tcuTexLookupVerifier.isSeamplessLinearMipmapLinearSampleResultValid(faces0, faces1, sampler, prec, coords, fBounds, result); 1995 else 1996 return tcuTexLookupVerifier.isLinearMipmapLinearSampleResultValid_CoordAsVec2AndInt(faces0[coords.face], faces1[coords.face], sampler, prec, [coords.s, coords.t], 0, fBounds, result); 1997 } else 1998 return tcuTexLookupVerifier.isNearestMipmapLinearSampleResultValid_CoordAsVec2AndInt(faces0[coords.face], faces1[coords.face], sampler, prec, [coords.s, coords.t], 0, fBounds, result); 1999 }; 2000 2001 /** 2002 * @param {tcuTexture.TextureCubeView} texture 2003 * @param {number} levelNdx 2004 * @param {Array<tcuTexture.ConstPixelBufferAccess>} out (&out)[CUBEFACE_LAST] 2005 */ 2006 tcuTexLookupVerifier.getCubeLevelFaces = function(texture, levelNdx, out) { 2007 for (var faceNdx = 0; faceNdx < 6; faceNdx++) 2008 out[faceNdx] = texture.getLevelFace(levelNdx, /** @type {tcuTexture.CubeFace} */ (faceNdx)); 2009 }; 2010 2011 /** 2012 * @param {number} numLayers 2013 * @param {number} numCoordBits 2014 * @param {number} layerCoord 2015 * @return {Array<number>} 2016 */ 2017 tcuTexLookupVerifier.computeLayerRange = function(numLayers, numCoordBits, layerCoord) { 2018 /** @type {number} */ var err = tcuTexVerifierUtil.computeFloatingPointError(layerCoord, numCoordBits); 2019 /** @type {number} */ var minL = Math.floor(layerCoord - err + 0.5); // Round down 2020 /** @type {number} */ var maxL = Math.ceil(layerCoord + err + 0.5) - 1; // Round up 2021 2022 assertMsgOptions(minL <= maxL, 'minL > maxL', false, true); 2023 2024 return [deMath.clamp(minL, 0, numLayers - 1), deMath.clamp(maxL, 0, numLayers - 1)]; 2025 }; 2026 2027 /** 2028 * @param {Array<number>} bits 2029 * @return {Array<number>} 2030 */ 2031 tcuTexLookupVerifier.computeFixedPointThreshold = function(bits) { 2032 return tcuTexVerifierUtil.computeFixedPointError_Vector(bits); 2033 }; 2034 2035 /** 2036 * @param {Array<number>} bits 2037 * @param {Array<number>} value 2038 * @return {Array<number>} 2039 */ 2040 tcuTexLookupVerifier.computeFloatingPointThreshold = function(bits, value) { 2041 return tcuTexVerifierUtil.computeFloatingPointError_Vector(value, bits); 2042 }; 2043 2044 /** 2045 * @param {number} dudx 2046 * @param {number} dvdx 2047 * @param {number} dwdx 2048 * @param {number} dudy 2049 * @param {number} dvdy 2050 * @param {number} dwdy 2051 * @param {tcuTexLookupVerifier.LodPrecision} prec 2052 * @return {Array<number>} 2053 */ 2054 tcuTexLookupVerifier.computeLodBoundsFromDerivates = function(dudx, dvdx, dwdx, dudy, dvdy, dwdy, prec) { 2055 /** @type {number} */ var mu = Math.max(Math.abs(dudx), Math.abs(dudy)); 2056 /** @type {number} */ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy)); 2057 /** @type {number} */ var mw = Math.max(Math.abs(dwdx), Math.abs(dwdy)); 2058 /** @type {number} */ var minDBound = Math.max(Math.max(mu, mv), mw); 2059 /** @type {number} */ var maxDBound = mu + mv + mw; 2060 /** @type {number} */ var minDErr = tcuTexVerifierUtil.computeFloatingPointError(minDBound, prec.derivateBits); 2061 /** @type {number} */ var maxDErr = tcuTexVerifierUtil.computeFloatingPointError(maxDBound, prec.derivateBits); 2062 /** @type {number} */ var minLod = Math.log2(minDBound - minDErr); 2063 /** @type {number} */ var maxLod = Math.log2(maxDBound + maxDErr); 2064 /** @type {number} */ var lodErr = tcuTexVerifierUtil.computeFixedPointError(prec.lodBits); 2065 2066 assertMsgOptions(minLod <= maxLod, 'Error: minLod > maxLod', false, true); 2067 return [minLod - lodErr, maxLod + lodErr]; 2068 }; 2069 2070 /** 2071 * @param {number} dudx 2072 * @param {number} dvdx 2073 * @param {number} dudy 2074 * @param {number} dvdy 2075 * @param {tcuTexLookupVerifier.LodPrecision} prec 2076 * @return {Array<number>} 2077 */ 2078 tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV = function(dudx, dvdx, dudy, dvdy, prec) { 2079 return tcuTexLookupVerifier.computeLodBoundsFromDerivates(dudx, dvdx, 0, dudy, dvdy, 0, prec); 2080 }; 2081 2082 /** 2083 * @param {number} dudx 2084 * @param {number} dudy 2085 * @param {tcuTexLookupVerifier.LodPrecision} prec 2086 * @return {Array<number>} 2087 */ 2088 tcuTexLookupVerifier.computeLodBoundsFromDerivatesU = function(dudx, dudy, prec) { 2089 return tcuTexLookupVerifier.computeLodBoundsFromDerivates(dudx, 0, 0, dudy, 0, 0, prec); 2090 }; 2091 2092 /** 2093 * @param {Array<number>} coord 2094 * @param {Array<number>} coordDx 2095 * @param {Array<number>} coordDy 2096 * @param {number} faceSize 2097 * @param {tcuTexLookupVerifier.LodPrecision} prec 2098 * @return {Array<number>} 2099 */ 2100 tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates = function(coord, coordDx, coordDy, faceSize, prec) { 2101 /** @type {boolean} */ var allowBrokenEdgeDerivate = false; 2102 /** @type {tcuTexture.CubeFace} */ var face = tcuTexture.selectCubeFace(coord); 2103 /** @type {number} */ var maNdx = 0; 2104 /** @type {number} */ var sNdx = 0; 2105 /** @type {number} */ var tNdx = 0; 2106 2107 // \note Derivate signs don't matter when computing lod 2108 switch (face) { 2109 case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: 2110 case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break; 2111 case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: 2112 case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break; 2113 case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: 2114 case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break; 2115 default: 2116 throw new Error('Invalid CubeFace.'); 2117 } 2118 2119 /** @type {number} */ var sc = coord[sNdx]; 2120 /** @type {number} */ var tc = coord[tNdx]; 2121 /** @type {number} */ var ma = Math.abs(coord[maNdx]); 2122 /** @type {number} */ var scdx = coordDx[sNdx]; 2123 /** @type {number} */ var tcdx = coordDx[tNdx]; 2124 /** @type {number} */ var madx = Math.abs(coordDx[maNdx]); 2125 /** @type {number} */ var scdy = coordDy[sNdx]; 2126 /** @type {number} */ var tcdy = coordDy[tNdx]; 2127 /** @type {number} */ var mady = Math.abs(coordDy[maNdx]); 2128 /** @type {number} */ var dudx = faceSize * 0.5 * (scdx * ma - sc * madx) / (ma * ma); 2129 /** @type {number} */ var dvdx = faceSize * 0.5 * (tcdx * ma - tc * madx) / (ma * ma); 2130 /** @type {number} */ var dudy = faceSize * 0.5 * (scdy * ma - sc * mady) / (ma * ma); 2131 /** @type {number} */ var dvdy = faceSize * 0.5 * (tcdy * ma - tc * mady) / (ma * ma); 2132 /** @type {Array<number>} */ var bounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(dudx, dvdx, dudy, dvdy, prec); 2133 2134 // Implementations may compute derivate from projected (s, t) resulting in incorrect values at edges. 2135 if (allowBrokenEdgeDerivate) { 2136 /** @type {Array<number>} */ var dxErr = tcuTexVerifierUtil.computeFloatingPointError_Vector(coordDx, [prec.derivateBits, prec.derivateBits, prec.derivateBits]); 2137 /** @type {Array<number>} */ var dyErr = tcuTexVerifierUtil.computeFloatingPointError_Vector(coordDy, [prec.derivateBits, prec.derivateBits, prec.derivateBits]); 2138 /** @type {Array<number>} */ var xoffs = deMath.add(deMath.abs(coordDx), dxErr); 2139 /** @type {Array<number>} */ var yoffs = deMath.add(deMath.abs(coordDy), dyErr); 2140 2141 if (tcuTexture.selectCubeFace(deMath.add(coord, xoffs)) != face || 2142 tcuTexture.selectCubeFace(deMath.subtract(coord, xoffs)) != face || 2143 tcuTexture.selectCubeFace(deMath.add(coord, yoffs)) != face || 2144 tcuTexture.selectCubeFace(deMath.subtract(coord, yoffs)) != face) { 2145 return [bounds[0], 1000]; 2146 } 2147 } 2148 2149 return bounds; 2150 }; 2151 2152 /** 2153 * @param {Array<number>} lodBounds 2154 * @param {Array<number>} lodMinMax 2155 * @param {tcuTexLookupVerifier.LodPrecision} prec 2156 * @return {Array<number>} 2157 */ 2158 tcuTexLookupVerifier.clampLodBounds = function(lodBounds, lodMinMax, prec) { 2159 /** @type {number} */ var lodErr = tcuTexVerifierUtil.computeFixedPointError(prec.lodBits); 2160 /** @type {number} */ var a = lodMinMax[0]; 2161 /** @type {number} */ var b = lodMinMax[1]; 2162 return [deMath.clamp(lodBounds[0], a - lodErr, b - lodErr), deMath.clamp(lodBounds[1], a + lodErr, b + lodErr)]; 2163 }; 2164 2165 /** 2166 * @param {tcuTexture.ConstPixelBufferAccess} access 2167 * @param {tcuTexture.Sampler} sampler 2168 * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode 2169 * @param {tcuTexLookupVerifier.LookupPrecision} prec 2170 * @param {Array<number>} coord 2171 * @param {number} coordZ 2172 * @param {Array<number>} result 2173 * @return {boolean} 2174 */ 2175 tcuTexLookupVerifier.isLevel2DLookupResultValid = function(access, sampler, scaleMode, prec, coord, coordZ, result) { 2176 /** @type {tcuTexture.FilterMode} */ 2177 var filterMode = (scaleMode == tcuTexLookupVerifier.TexLookupScaleMode.MAGNIFY) ? sampler.magFilter : sampler.minFilter; 2178 return tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec2AndInt(access, sampler, filterMode, prec, coord, coordZ, result); 2179 }; 2180 2181 /** 2182 * @param {tcuTexture.ConstPixelBufferAccess} access 2183 * @param {tcuTexture.Sampler} sampler 2184 * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode 2185 * @param {tcuTexLookupVerifier.LookupPrecision} prec 2186 * @param {Array<number>} coord 2187 * @param {number} coordZ 2188 * @param {Array<number>} result 2189 * @return {boolean} 2190 */ 2191 tcuTexLookupVerifier.isLevel2DLookupResultValid_Int = function(access, sampler, scaleMode, prec, coord, coordZ, result) { 2192 assertMsgOptions(sampler.minFilter == tcuTexture.FilterMode.NEAREST && sampler.magFilter == tcuTexture.FilterMode.NEAREST, 'minFilter and magFilter must be NEAREST', false, true); 2193 return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec2AndInt(access, sampler, prec, coord, coordZ, result); 2194 }; 2195 2196 /** 2197 * @param {tcuTexture.ConstPixelBufferAccess} access 2198 * @param {tcuTexture.Sampler} sampler 2199 * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode 2200 * @param {tcuTexLookupVerifier.LookupPrecision} prec 2201 * @param {Array<number>} coord 2202 * @param {Array<number>} result 2203 * @return {boolean} 2204 */ 2205 tcuTexLookupVerifier.isLevel3DLookupResultValid = function(access, sampler, scaleMode, prec, coord, result) { 2206 /** @type {tcuTexture.FilterMode} */ 2207 var filterMode = (scaleMode == tcuTexLookupVerifier.TexLookupScaleMode.MAGNIFY) ? sampler.magFilter : sampler.minFilter; 2208 return tcuTexLookupVerifier.isLevelSampleResultValid_CoordAsVec3(access, sampler, filterMode, prec, coord, result); 2209 }; 2210 2211 /** 2212 * @param {tcuTexture.ConstPixelBufferAccess} access 2213 * @param {tcuTexture.Sampler} sampler 2214 * @param {tcuTexLookupVerifier.TexLookupScaleMode} scaleMode 2215 * @param {tcuTexLookupVerifier.LookupPrecision} prec 2216 * @param {Array<number>} coord 2217 * @param {Array<number>} result 2218 * @return {boolean} 2219 */ 2220 tcuTexLookupVerifier.isLevel3DLookupResultValid_Int = function(access, sampler, scaleMode, prec, coord, result) { 2221 assertMsgOptions(sampler.minFilter == tcuTexture.FilterMode.NEAREST && sampler.magFilter == tcuTexture.FilterMode.NEAREST, 'minFilter and magFilter must be NEAREST', false, true); 2222 return tcuTexLookupVerifier.isNearestSampleResultValid_CoordAsVec3(access, sampler, prec, coord, result); 2223 }; 2224 2225 });