tor-browser

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

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 });