tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tcuTexCompareVerifier.js (64603B)


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