tor-browser

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

es3fTextureShadowTests.js (49444B)


      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 'use strict';
     21 goog.provide('functional.gles3.es3fTextureShadowTests');
     22 goog.require('framework.common.tcuImageCompare');
     23 goog.require('framework.common.tcuLogImage');
     24 goog.require('framework.common.tcuPixelFormat');
     25 goog.require('framework.common.tcuRGBA');
     26 goog.require('framework.common.tcuSurface');
     27 goog.require('framework.common.tcuTestCase');
     28 goog.require('framework.common.tcuTexCompareVerifier');
     29 goog.require('framework.common.tcuTexLookupVerifier');
     30 goog.require('framework.common.tcuTexture');
     31 goog.require('framework.common.tcuTextureUtil');
     32 goog.require('framework.delibs.debase.deMath');
     33 goog.require('framework.delibs.debase.deString');
     34 goog.require('framework.delibs.debase.deUtil');
     35 goog.require('framework.opengl.gluShaderUtil');
     36 goog.require('framework.opengl.gluTexture');
     37 goog.require('framework.opengl.gluTextureUtil');
     38 goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
     39 goog.require('modules.shared.glsTextureTestUtil');
     40 
     41 goog.scope(function() {
     42 
     43 var es3fTextureShadowTests = functional.gles3.es3fTextureShadowTests;
     44 var tcuTestCase = framework.common.tcuTestCase;
     45 var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
     46 var gluShaderUtil = framework.opengl.gluShaderUtil;
     47 var gluTexture = framework.opengl.gluTexture;
     48 var gluTextureUtil = framework.opengl.gluTextureUtil;
     49 var tcuTexture = framework.common.tcuTexture;
     50 var tcuImageCompare = framework.common.tcuImageCompare;
     51 var tcuLogImage = framework.common.tcuLogImage;
     52 var tcuTextureUtil = framework.common.tcuTextureUtil;
     53 var tcuRGBA = framework.common.tcuRGBA;
     54 var deMath = framework.delibs.debase.deMath;
     55 var tcuPixelFormat = framework.common.tcuPixelFormat;
     56 var tcuSurface = framework.common.tcuSurface;
     57 var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier;
     58 var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier;
     59 var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
     60 var deString = framework.delibs.debase.deString;
     61 var deUtil = framework.delibs.debase.deUtil;
     62 
     63    es3fTextureShadowTests.version = '300 es';
     64 
     65    /** @const */ var VIEWPORT_WIDTH = 64;
     66    /** @const */ var VIEWPORT_HEIGHT = 64;
     67    /** @const */ var MIN_VIEWPORT_WIDTH = 64;
     68    /** @const */ var MIN_VIEWPORT_HEIGHT = 64;
     69 
     70    var DE_ASSERT = function(x) {
     71        if (!x)
     72            throw new Error('Assert failed');
     73    };
     74 
     75    /**
     76     * @param {tcuTexture.TextureFormat} format
     77     * @return {boolean}
     78     */
     79    es3fTextureShadowTests.isFloatingPointDepthFormat = function(format) {
     80        // Only two depth and depth-stencil formats are floating point
     81        return (format.order == tcuTexture.ChannelOrder.D && format.type == tcuTexture.ChannelType.FLOAT) || (format.order == tcuTexture.ChannelOrder.DS && format.type == tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV);
     82    };
     83 
     84    /**
     85     * @param {tcuTexture.PixelBufferAccess} access
     86     */
     87    es3fTextureShadowTests.clampFloatingPointTexture = function(access) {
     88        DE_ASSERT(es3fTextureShadowTests.isFloatingPointDepthFormat(access.getFormat()));
     89        for (var z = 0; z < access.getDepth(); ++z)
     90            for (var y = 0; y < access.getHeight(); ++y)
     91                for (var x = 0; x < access.getWidth(); ++x)
     92                    access.setPixDepth(deMath.clamp(access.getPixDepth(x, y, z), 0.0, 1.0), x, y, z);
     93    };
     94 
     95    /**
     96     * @param {tcuTexture.Texture2D|tcuTexture.Texture2DArray} target
     97     */
     98    es3fTextureShadowTests.clampFloatingPointTexture2D = function(target) {
     99        for (var level = 0; level < target.getNumLevels(); ++level)
    100            if (!target.isLevelEmpty(level))
    101                es3fTextureShadowTests.clampFloatingPointTexture(target.getLevel(level));
    102    };
    103 
    104    /**
    105     * @param {tcuTexture.TextureCube} target
    106     */
    107    es3fTextureShadowTests.clampFloatingPointTextureCube = function(target) {
    108        for (var level = 0; level < target.getNumLevels(); ++level)
    109            for (var face = tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X; face < Object.keys(tcuTexture.CubeFace).length; face++)
    110                es3fTextureShadowTests.clampFloatingPointTexture(target.getLevelFace(level, face));
    111    };
    112 
    113    /**
    114     * @param {?} textureType
    115     * @param {tcuTexture.ConstPixelBufferAccess} result
    116     * @param {tcuTexture.Texture2D|tcuTexture.Texture2DArray|tcuTexture.TextureCube} src
    117     * @param {Array<number>} texCoord
    118     * @param {glsTextureTestUtil.ReferenceParams} sampleParams
    119     * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
    120     * @param {tcuTexLookupVerifier.LodPrecision} lodPrecision
    121     * @param {tcuPixelFormat.PixelFormat} pixelFormat
    122     */
    123    es3fTextureShadowTests.verifyTexCompareResult = function(textureType, result, src, texCoord, sampleParams, comparePrec, lodPrecision, pixelFormat) {
    124        var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
    125        var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
    126        var nonShadowThreshold = deMath.swizzle(tcuTexLookupVerifier.computeFixedPointThreshold(deMath.subtract(glsTextureTestUtil.getBitsVec(pixelFormat), [1, 1, 1, 1])), [1, 2, 3]);
    127        var numFailedPixels;
    128 
    129        if (es3fTextureShadowTests.isFloatingPointDepthFormat(src.getFormat())) {
    130            var clampedSource = /*deUtil.clone(*/src/*)*/;
    131 
    132            if (textureType == tcuTexture.Texture2D) {
    133                es3fTextureShadowTests.clampFloatingPointTexture2D(/** @type {tcuTexture.Texture2D} */(clampedSource));
    134                glsTextureTestUtil.sampleTexture2D(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DView} */ (clampedSource.getView()), texCoord, sampleParams);
    135                // sample clamped values
    136                numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2D(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DView} */ (clampedSource.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
    137            } else if (textureType == tcuTexture.Texture2DArray) {
    138                es3fTextureShadowTests.clampFloatingPointTexture2D(/** @type {tcuTexture.Texture2DArray} */(clampedSource));
    139                glsTextureTestUtil.sampleTexture2DArray(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DArrayView} */ (clampedSource.getView()), texCoord, sampleParams);
    140                // sample clamped values
    141                numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2DArray(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DArrayView} */ (clampedSource.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
    142            } else if (textureType == tcuTexture.TextureCube) {
    143                es3fTextureShadowTests.clampFloatingPointTextureCube(/** @type {tcuTexture.TextureCube} */(clampedSource));
    144                glsTextureTestUtil.sampleTextureCube(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.TextureCubeView} */ (clampedSource.getView()), texCoord, sampleParams);
    145                // sample clamped values
    146                numFailedPixels = glsTextureTestUtil.computeTextureCompareDiffCube(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.TextureCubeView} */ (clampedSource.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
    147            } else
    148                throw new Error('Invalid texture type');
    149 
    150        } else {
    151            if (textureType == tcuTexture.Texture2D) {
    152                glsTextureTestUtil.sampleTexture2D(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DView} */ (src.getView()), texCoord, sampleParams);
    153                // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
    154                numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2D(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DView} */ (src.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
    155            } else if (textureType == tcuTexture.Texture2DArray) {
    156                glsTextureTestUtil.sampleTexture2DArray(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.Texture2DArrayView} */ (src.getView()), texCoord, sampleParams);
    157                // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
    158                numFailedPixels = glsTextureTestUtil.computeTextureCompareDiff2DArray(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.Texture2DArrayView} */ (src.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
    159            } else if (textureType == tcuTexture.TextureCube) {
    160                glsTextureTestUtil.sampleTextureCube(new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat), /** @type {tcuTexture.TextureCubeView} */ (src.getView()), texCoord, sampleParams);
    161                // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
    162                numFailedPixels = glsTextureTestUtil.computeTextureCompareDiffCube(result, reference.getAccess(), errorMask.getAccess(), /** @type {tcuTexture.TextureCubeView} */ (src.getView()), texCoord, sampleParams, comparePrec, lodPrecision, nonShadowThreshold);
    163            } else
    164                throw new Error('Invalid texture type');
    165        }
    166 
    167        if (numFailedPixels > 0)
    168            bufferedLogToConsole('ERROR: Result verification failed, got ' + numFailedPixels + ' invalid pixels!');
    169 
    170        if (numFailedPixels > 0)
    171            tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
    172        else
    173            tcuLogImage.logImageWithInfo(result, 'Result');
    174 
    175        return numFailedPixels == 0;
    176 
    177    };
    178 
    179    /**
    180     * @constructor
    181     * @param {string} name
    182     * @param {number} format
    183     * @struct
    184     */
    185    es3fTextureShadowTests.Format = function(name, format) {
    186        /** @type {string} */ this.name = name;
    187        /** @type {number} */ this.format = format;
    188    };
    189 
    190    /**
    191     * @constructor
    192     * @param {string} name
    193     * @param {number} minFilter
    194     * @param {number} magFilter
    195     * @struct
    196     */
    197    es3fTextureShadowTests.Filter = function(name, minFilter, magFilter) {
    198        /** @type {string} */ this.name = name;
    199        /** @type {number} */ this.minFilter = minFilter;
    200        /** @type {number} */ this.magFilter = magFilter;
    201    };
    202 
    203    /**
    204     * @constructor
    205     * @param {string} name
    206     * @param {number} func
    207     * @struct
    208     */
    209    es3fTextureShadowTests.CompareFunc = function(name, func) {
    210        /** @type {string} */ this.name = name;
    211        /** @type {number} */ this.func = func;
    212    };
    213 
    214    /**
    215     * @constructor
    216     * @param {number} texNdx
    217     * @param {number} ref
    218     * @param {number} lodX
    219     * @param {number} lodY
    220     * @param {number} oX
    221     * @param {number} oY
    222     * @struct
    223     */
    224    es3fTextureShadowTests.TestCase = function(texNdx, ref, lodX, lodY, oX, oY) {
    225        /** @type {number} */ this.texNdx = texNdx;
    226        /** @type {number} */ this.ref = ref;
    227        /** @type {number} */ this.lodX = lodX;
    228        /** @type {number} */ this.lodY = lodY;
    229        /** @type {number} */ this.oX = oX
    230        /** @type {number} */ this.oY = oY;
    231    };
    232 
    233    /**
    234     * @constructor
    235     * @param {?gluTexture.Texture2D|?gluTexture.TextureCube|?gluTexture.Texture2DArray} tex
    236     * @param {number} ref
    237     * @param {Array<number>} minCoord
    238     * @param {Array<number>} maxCoord
    239     * @struct
    240     */
    241    es3fTextureShadowTests.FilterCase = function(tex, ref, minCoord, maxCoord) {
    242        /** @type {?gluTexture.Texture2D|?gluTexture.TextureCube|?gluTexture.Texture2DArray} */ this.texture = tex;
    243        /** @type {Array<number>} */ this.minCoord = minCoord;
    244        /** @type {Array<number>} */ this.maxCoord = maxCoord;
    245        /** @type {number} */ this.ref = ref;
    246    };
    247 
    248    /**
    249     * @constructor
    250     * @param {string} name
    251     * @param {string} desc
    252     * @param {number} minFilter
    253     * @param {number} magFilter
    254     * @param {number} wrapS
    255     * @param {number} wrapT
    256     * @param {number} format
    257     * @param {number} width
    258     * @param {number} height
    259     * @param {number} compareFunc
    260     * @extends {tcuTestCase.DeqpTest}
    261     */
    262    es3fTextureShadowTests.Texture2DShadowCase = function(name, desc, minFilter, magFilter, wrapS, wrapT, format, width, height, compareFunc) {
    263        tcuTestCase.DeqpTest.call(this, name, desc);
    264        this.m_minFilter = minFilter;
    265        this.m_magFilter = magFilter;
    266        this.m_wrapS = wrapS;
    267        this.m_wrapT = wrapT;
    268        this.m_format = format;
    269        this.m_width = width;
    270        this.m_height = height;
    271        this.m_compareFunc = compareFunc;
    272        this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureShadowTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
    273        this.m_caseNdx = 0;
    274        this.m_cases = [];
    275    };
    276 
    277    es3fTextureShadowTests.Texture2DShadowCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    278    es3fTextureShadowTests.Texture2DShadowCase.prototype.constructor = es3fTextureShadowTests.Texture2DShadowCase;
    279 
    280    es3fTextureShadowTests.Texture2DShadowCase.prototype.init = function() {
    281 
    282        // Create 2 textures.
    283        this.m_textures = [];
    284        this.m_textures[0] = gluTexture.texture2DFromInternalFormat(gl, this.m_format, this.m_width, this.m_height);
    285        this.m_textures[1] = gluTexture.texture2DFromInternalFormat(gl, this.m_format, this.m_width, this.m_height);
    286 
    287        var numLevels = this.m_textures[0].getRefTexture().getNumLevels();
    288 
    289        for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
    290            this.m_textures[0].getRefTexture().allocLevel(levelNdx);
    291            tcuTextureUtil.fillWithComponentGradients(this.m_textures[0].getRefTexture().getLevel(levelNdx), [-0.5, -0.5, -0.5, 2.0], [1, 1, 1, 0]);
    292        }
    293 
    294        for (levelNdx = 0; levelNdx < numLevels; levelNdx++) {
    295            var step = 0x00ffffff / numLevels;
    296            var rgb = step * levelNdx;
    297            var colorA = 0xff000000 | rgb;
    298            var colorB = 0xff000000 | ~rgb;
    299 
    300            this.m_textures[1].getRefTexture().allocLevel(levelNdx);
    301            tcuTextureUtil.fillWithGrid(this.m_textures[1].getRefTexture().getLevel(levelNdx), 4, tcuRGBA.newRGBAFromValue(colorA).toVec(), tcuRGBA.newRGBAFromValue(colorB).toVec());
    302        }
    303 
    304        for (var i = 0; i < this.m_textures.length; i++)
    305            this.m_textures[i].upload();
    306 
    307        var refInRangeUpper = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 1.0 : 0.5;
    308        var refInRangeLower = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 0.0 : 0.5;
    309 
    310        var refOutOfBoundsUpper = 1.1;
    311        var refOutOfBoundsLower = -0.1;
    312 
    313        numLevels = this.m_textures[0].getRefTexture().getNumLevels();
    314 
    315        var cases = [];
    316        cases.push(new es3fTextureShadowTests.TestCase(0, refInRangeUpper, 1.6, 2.9, -1.0, -2.7));
    317        cases.push(new es3fTextureShadowTests.TestCase(0, refInRangeLower, -2.0, -1.35, -0.2, 0.7));
    318        cases.push(new es3fTextureShadowTests.TestCase(1, refInRangeUpper, 0.14, 0.275, -1.5, -1.1));
    319        cases.push(new es3fTextureShadowTests.TestCase(1, refInRangeLower, -0.92, -2.64, 0.4, -0.1));
    320        cases.push(new es3fTextureShadowTests.TestCase(1, refOutOfBoundsUpper, -0.39, -0.52, 0.65, 0.87));
    321        cases.push(new es3fTextureShadowTests.TestCase(1, refOutOfBoundsLower, -1.55, 0.65, 0.35, 0.91));
    322 
    323        var viewportW = Math.min(VIEWPORT_WIDTH, gl.canvas.width);
    324        var viewportH = Math.min(VIEWPORT_HEIGHT, gl.canvas.height);
    325 
    326        for (var caseNdx = 0; caseNdx < cases.length; caseNdx++) {
    327            var texNdx = deMath.clamp(cases[caseNdx].texNdx, 0, this.m_textures.length - 1);
    328            var ref = cases[caseNdx].ref;
    329            var lodX = cases[caseNdx].lodX;
    330            var lodY = cases[caseNdx].lodY;
    331            var oX = cases[caseNdx].oX;
    332            var oY = cases[caseNdx].oY;
    333            var sX = Math.exp(lodX * Math.log(2)) * viewportW / this.m_textures[texNdx].getRefTexture().getWidth();
    334            var sY = Math.exp(lodY * Math.log(2)) * viewportH / this.m_textures[texNdx].getRefTexture().getHeight();
    335 
    336            this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_textures[texNdx], ref, [oX, oY], [oX + sX, oY + sY]));
    337        }
    338 
    339        this.m_caseNdx = 0;
    340    };
    341 
    342    es3fTextureShadowTests.Texture2DShadowCase.prototype.iterate = function() {
    343 
    344        var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
    345        var curCase = this.m_cases[this.m_caseNdx];
    346        var sampleParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D);
    347        var rendered = new tcuSurface.Surface(viewport.width, viewport.height);
    348        var texCoord = [];
    349 
    350        if (viewport.width < MIN_VIEWPORT_WIDTH || viewport.height < MIN_VIEWPORT_HEIGHT)
    351            throw new Error('Too small render target');
    352 
    353        // Setup params for reference.
    354        sampleParams.sampler = gluTextureUtil.mapGLSampler(this.m_wrapS, this.m_wrapT, gl.CLAMP_TO_EDGE, this.m_minFilter, this.m_magFilter);
    355        sampleParams.sampler.compare = gluTextureUtil.mapGLCompareFunc(this.m_compareFunc);
    356        sampleParams.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW;
    357        sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
    358        sampleParams.ref = curCase.ref;
    359 
    360        bufferedLogToConsole('Compare reference value = ' + sampleParams.ref);
    361 
    362        // Compute texture coordinates.
    363        bufferedLogToConsole('Texture coordinates: ' + curCase.minCoord + ' -> ' + curCase.maxCoord);
    364 
    365        texCoord = glsTextureTestUtil.computeQuadTexCoord2D(curCase.minCoord, curCase.maxCoord);
    366 
    367        gl.bindTexture(gl.TEXTURE_2D, curCase.texture.getGLTexture());
    368        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_minFilter);
    369        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_magFilter);
    370        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.m_wrapS);
    371        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.m_wrapT);
    372        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
    373        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, this.m_compareFunc);
    374 
    375        gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
    376        this.m_renderer.renderQuad(0, texCoord, sampleParams);
    377        rendered.readViewport(gl, viewport);
    378 
    379 
    380        var pixelFormat = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
    381        var lodPrecision = new tcuTexLookupVerifier.LodPrecision(18, 6);
    382        var texComparePrecision = new tcuTexCompareVerifier.TexComparePrecision([20, 20, 0], [7, 7, 0], 5, 16, pixelFormat.redBits - 1);
    383 
    384        var isHighQuality = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2D, rendered.getAccess(), curCase.texture.getRefTexture(),
    385                                                      texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
    386 
    387        if (!isHighQuality) {
    388            bufferedLogToConsole('Warning: Verification assuming high-quality PCF filtering failed.');
    389 
    390            lodPrecision.lodBits = 4;
    391            texComparePrecision.uvwBits = [4, 4, 0];
    392            texComparePrecision.pcfBits = 0;
    393 
    394            var isOk = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2D, rendered.getAccess(), curCase.texture.getRefTexture(),
    395                                                     texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
    396 
    397            if (!isOk) {
    398                bufferedLogToConsole('ERROR: Verification against low precision requirements failed, failing test case.');
    399                testFailedOptions('Image verification failed', false);
    400            } else
    401                testPassedOptions('Low-quality result', true);
    402        } else
    403            testPassedOptions('High-quality result', true);
    404 
    405        this.m_caseNdx += 1;
    406        return this.m_caseNdx < this.m_cases.length ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
    407    };
    408 
    409    /**
    410     * @constructor
    411     * @param {string} name
    412     * @param {string} desc
    413     * @param {number} minFilter
    414     * @param {number} magFilter
    415     * @param {number} wrapS
    416     * @param {number} wrapT
    417     * @param {number} format
    418     * @param {number} size
    419     * @param {number} compareFunc
    420     * @extends {tcuTestCase.DeqpTest}
    421     */
    422    es3fTextureShadowTests.TextureCubeShadowCase = function(name, desc, minFilter, magFilter, wrapS, wrapT, format, size, compareFunc) {
    423        tcuTestCase.DeqpTest.call(this, name, desc);
    424        this.m_minFilter = minFilter;
    425        this.m_magFilter = magFilter;
    426        this.m_wrapS = wrapS;
    427        this.m_wrapT = wrapT;
    428        this.m_format = format;
    429        this.m_size = size;
    430        this.m_compareFunc = compareFunc;
    431        this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureShadowTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
    432        this.m_caseNdx = 0;
    433        this.m_cases = [];
    434    };
    435 
    436    es3fTextureShadowTests.TextureCubeShadowCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    437    es3fTextureShadowTests.TextureCubeShadowCase.prototype.constructor = es3fTextureShadowTests.TextureCubeShadowCase;
    438 
    439    es3fTextureShadowTests.TextureCubeShadowCase.prototype.init = function() {
    440        DE_ASSERT(!this.m_gradientTex && !this.m_gridTex);
    441 
    442        var numLevels = Math.floor(Math.log2(this.m_size)) + 1;
    443        /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
    444        /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
    445        /** @type {Array<number>} */ var cBias = fmtInfo.valueMin;
    446        /** @type {Array<number>} */ var cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
    447 
    448        // Create textures.
    449        this.m_gradientTex = gluTexture.cubeFromInternalFormat(gl, this.m_format, this.m_size);
    450        this.m_gridTex = gluTexture.cubeFromInternalFormat(gl, this.m_format, this.m_size);
    451 
    452        // Fill first with gradient texture.
    453        var gradients = [[[-1.0, -1.0, -1.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // negative x
    454            [[0.0, -1.0, -1.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // positive x
    455            [[-1.0, 0.0, -1.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // negative y
    456            [[-1.0, -1.0, 0.0, 2.0], [1.0, 1.0, 1.0, 0.0]], // positive y
    457            [[-1.0, -1.0, -1.0, 0.0], [1.0, 1.0, 1.0, 1.0]], // negative z
    458            [[0.0, 0.0, 0.0, 2.0], [1.0, 1.0, 1.0, 0.0]]]; // positive z
    459 
    460        for (var face in tcuTexture.CubeFace) {
    461            for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
    462                this.m_gradientTex.getRefTexture().allocLevel(tcuTexture.CubeFace[face], levelNdx);
    463                tcuTextureUtil.fillWithComponentGradients(this.m_gradientTex.getRefTexture().getLevelFace(levelNdx, tcuTexture.CubeFace[face]), deMath.add(deMath.multiply(gradients[tcuTexture.CubeFace[face]][0], cScale), cBias), deMath.add(deMath.multiply(gradients[tcuTexture.CubeFace[face]][1], cScale), cBias));
    464            }
    465        }
    466 
    467        // Fill second with grid texture.
    468        for (var face in tcuTexture.CubeFace) {
    469            for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
    470                var step = 0x00ffffff / (numLevels * Object.keys(tcuTexture.CubeFace).length);
    471                var rgb = step * levelNdx * face;
    472                var colorA = 0xff000000 | rgb;
    473                var colorB = 0xff000000 | ~rgb;
    474 
    475                this.m_gridTex.getRefTexture().allocLevel(tcuTexture.CubeFace[face], levelNdx);
    476                tcuTextureUtil.fillWithGrid(this.m_gridTex.getRefTexture().getLevelFace(levelNdx, tcuTexture.CubeFace[face]), 4, deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorA).toVec(), cScale), cBias), deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorB).toVec(), cScale), cBias));
    477            }
    478        }
    479 
    480        // Upload.
    481        this.m_gradientTex.upload();
    482        this.m_gridTex.upload();
    483 
    484        var refInRangeUpper = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 1.0 : 0.5;
    485        var refInRangeLower = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 0.0 : 0.5;
    486        var refOutOfBoundsUpper = 1.1;
    487        var refOutOfBoundsLower = -0.1;
    488        var singleSample = new rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess().getNumSamples() == 0;
    489        //var singleSample = this.m_context.getRenderTarget().getNumSamples() == 0;
    490 
    491        if (singleSample)
    492            this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gradientTex, refInRangeUpper, [-1.25, -1.2], [1.2, 1.25])); // minification
    493        else
    494            this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gradientTex, refInRangeUpper, [-1.19, -1.3], [1.1, 1.35])); // minification - w/ tuned coordinates to avoid hitting triangle edges
    495 
    496        this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gradientTex, refInRangeLower, [0.8, 0.8], [1.25, 1.20])); // magnification
    497        this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refInRangeUpper, [-1.19, -1.3], [1.1, 1.35])); // minification
    498        this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refInRangeLower, [-1.2, -1.1], [-0.8, -0.8])); // magnification
    499        this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refOutOfBoundsUpper, [-0.61, -0.1], [0.9, 1.18])); // reference value clamp, upper
    500 
    501        if (singleSample)
    502            this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refOutOfBoundsLower, [-0.75, 1.0], [0.05, 0.75])); // reference value clamp, lower
    503        else
    504            this.m_cases.push(new es3fTextureShadowTests.FilterCase(this.m_gridTex, refOutOfBoundsLower, [-0.75, 1.0], [0.25, 0.75])); // reference value clamp, lower
    505 
    506        this.m_caseNdx = 0;
    507    };
    508 
    509    es3fTextureShadowTests.TextureCubeShadowCase.prototype.iterate = function() {
    510        var viewportSize = 28;
    511        var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), viewportSize, viewportSize, deString.deStringHash(this.fullName()) ^ deMath.deMathHash(this.m_caseNdx));
    512        var curCase = this.m_cases[this.m_caseNdx];
    513        var sampleParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_CUBE);
    514 
    515        if (viewport.width < viewportSize || viewport.height < viewportSize)
    516            throw new Error('Too small render target');
    517 
    518        // Setup texture
    519        gl.bindTexture(gl.TEXTURE_CUBE_MAP, curCase.texture.getGLTexture());
    520        gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, this.m_minFilter);
    521        gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, this.m_magFilter);
    522        gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this.m_wrapS);
    523        gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this.m_wrapT);
    524        gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
    525        gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, this.m_compareFunc);
    526 
    527        // Other state
    528        gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
    529 
    530        // Params for reference computation.
    531        sampleParams.sampler = gluTextureUtil.mapGLSampler(gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, this.m_minFilter, this.m_magFilter);
    532        sampleParams.sampler.seamlessCubeMap = true;
    533        sampleParams.sampler.compare = gluTextureUtil.mapGLCompareFunc(this.m_compareFunc);
    534        sampleParams.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW;
    535        sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
    536        sampleParams.ref = curCase.ref;
    537 
    538        bufferedLogToConsole(
    539            'Compare reference value = ' + sampleParams.ref + '\n' +
    540            'Coordinates: ' + curCase.minCoord + ' -> ' + curCase.maxCoord);
    541 
    542        for (var faceNdx in tcuTexture.CubeFace) {
    543            var face = tcuTexture.CubeFace[faceNdx];
    544            var result = new tcuSurface.Surface(viewport.width, viewport.height);
    545            var texCoord = [];
    546 
    547            texCoord = glsTextureTestUtil.computeQuadTexCoordCubeFace(face, curCase.minCoord, curCase.maxCoord);
    548 
    549            this.m_renderer.renderQuad(0, texCoord, sampleParams);
    550 
    551            result.readViewport(gl, viewport);
    552 
    553            var pixelFormat = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
    554            /** @type {tcuTexLookupVerifier.LodPrecision} */ var lodPrecision = new tcuTexLookupVerifier.LodPrecision(10, 5);
    555            /** @type {tcuTexCompareVerifier.TexComparePrecision} */ var texComparePrecision = new tcuTexCompareVerifier.TexComparePrecision(
    556                [10, 10, 10],
    557                [6, 6, 0],
    558                5,
    559                16,
    560                pixelFormat.redBits - 1
    561            );
    562 
    563            var isHighQuality = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.TextureCube, result.getAccess(), curCase.texture.getRefTexture(),
    564                                                     texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
    565 
    566            if (!isHighQuality) {
    567                bufferedLogToConsole('Warning: Verification assuming high-quality PCF filtering failed.');
    568 
    569                lodPrecision.lodBits = 4;
    570                texComparePrecision.uvwBits = [4, 4, 0];
    571                texComparePrecision.pcfBits = 0;
    572 
    573                var isOk = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.TextureCube, result.getAccess(), curCase.texture.getRefTexture(),
    574                                                                                                  texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
    575                if (!isOk) {
    576                    bufferedLogToConsole('ERROR: Verification against low precision requirements failed, failing test case.');
    577                    testFailedOptions('Image verification failed', false);
    578                } else
    579                    testPassedOptions('Low-quality result', true);
    580            }
    581            else
    582                testPassedOptions('High-quality result', true);
    583        }
    584 
    585        this.m_caseNdx += 1;
    586        return this.m_caseNdx < this.m_cases.length ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
    587    };
    588 
    589    /**
    590     * Testure2DArrayShadowCase
    591     * @constructor
    592     * @extends {tcuTestCase.DeqpTest}
    593     * @param {string} name
    594     * @param {string} desc
    595     * @param {number} minFilter
    596     * @param {number} magFilter
    597     * @param {number} wrapS
    598     * @param {number} wrapT
    599     * @param {number} format
    600     * @param {number} width
    601     * @param {number} height
    602     * @param {number} numLayers
    603     * @param {number} compareFunc
    604     */
    605    es3fTextureShadowTests.Texture2DArrayShadowCase = function(name, desc, minFilter, magFilter, wrapS, wrapT, format, width, height, numLayers, compareFunc) {
    606        tcuTestCase.DeqpTest.call(this, name, desc);
    607        /** @type {number} */ this.m_minFilter = minFilter;
    608        /** @type {number} */ this.m_magFilter = magFilter;
    609        /** @type {number} */ this.m_wrapS = wrapS;
    610        /** @type {number} */ this.m_wrapT = wrapT;
    611        /** @type {number} */ this.m_format = format;
    612        /** @type {number} */ this.m_width = width;
    613        /** @type {number} */ this.m_height = height;
    614        /** @type {number} */ this.m_numLayers = numLayers;
    615        /** @type {number} */ this.m_compareFunc = compareFunc;
    616        /** @type {?gluTexture.Texture2DArray} */ this.m_gradientTex = null;
    617        /** @type {?gluTexture.Texture2DArray} */ this.m_gridTex = null;
    618        /** @type {glsTextureTestUtil.TextureRenderer} */ this.m_renderer = new glsTextureTestUtil.TextureRenderer(es3fTextureShadowTests.version, gluShaderUtil.precision.PRECISION_HIGHP);
    619        /** @type {Array<es3fTextureShadowTests.FilterCase>} */ this.m_cases = [];
    620        /** @type {number} */ this.m_caseNdx = 0;
    621    };
    622 
    623    es3fTextureShadowTests.Texture2DArrayShadowCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    624    es3fTextureShadowTests.Texture2DArrayShadowCase.prototype.constructor = es3fTextureShadowTests.Texture2DArrayShadowCase;
    625 
    626    /**
    627     * init
    628     */
    629    es3fTextureShadowTests.Texture2DArrayShadowCase.prototype.init = function() {
    630        /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_format);
    631        /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
    632        /** @type {Array<number>}*/ var cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
    633        /** @type {Array<number>}*/ var cBias = fmtInfo.valueMin;
    634        /** @type {number}*/ var numLevels = deMath.logToFloor(Math.max(this.m_width, this.m_height)) + 1;
    635 
    636        // Create textures.
    637        this.m_gradientTex = gluTexture.texture2DArrayFromInternalFormat(gl, this.m_format, this.m_width, this.m_height, this.m_numLayers);
    638        this.m_gridTex = gluTexture.texture2DArrayFromInternalFormat(gl, this.m_format, this.m_width, this.m_height, this.m_numLayers);
    639 
    640        // Fill first gradient texture.
    641        for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
    642            /** @type {Array<number>}*/ var gMin = deMath.add(deMath.multiply([-0.5, -0.5, -0.5, 2.0], cScale), cBias);
    643            /** @type {Array<number>}*/ var gMax = deMath.add(deMath.multiply([1.0, 1.0, 1.0, 0.0], cScale), cBias);
    644 
    645            this.m_gradientTex.getRefTexture().allocLevel(levelNdx);
    646            tcuTextureUtil.fillWithComponentGradients(
    647                /** @type {tcuTexture.PixelBufferAccess} */ (this.m_gradientTex.getRefTexture().getLevel(levelNdx)), gMin, gMax);
    648        }
    649 
    650        // Fill second with grid texture.
    651        for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) {
    652            /** @type {number}*/ var step = Math.floor(0x00ffffff / numLevels);
    653            /** @type {number}*/ var rgb = step * levelNdx;
    654            /** @type {number}*/ var colorA = deMath.binaryOp(0xff000000, rgb, deMath.BinaryOp.OR);
    655            /** @type {number}*/ var colorB = deMath.binaryOp(0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR);
    656 
    657            this.m_gridTex.getRefTexture().allocLevel(levelNdx);
    658            tcuTextureUtil.fillWithGrid(
    659                /** @type {tcuTexture.PixelBufferAccess} */ (this.m_gridTex.getRefTexture().getLevel(levelNdx)), 4,
    660                deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorA).toVec(), cScale), cBias),
    661                deMath.add(deMath.multiply(tcuRGBA.newRGBAFromValue(colorB).toVec(), cScale), cBias)
    662            );
    663        }
    664 
    665        // Upload.
    666        this.m_gradientTex.upload();
    667        this.m_gridTex.upload();
    668 
    669        // Compute cases.
    670        /** @type {number} */ var refInRangeUpper = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 1.0 : 0.5;
    671        /** @type {number} */ var refInRangeLower = (this.m_compareFunc == gl.EQUAL || this.m_compareFunc == gl.NOTEQUAL) ? 0.0 : 0.5;
    672        /** @type {number} */ var refOutOfBoundsUpper = 1.1; // !< lookup function should clamp values to [0, 1] range
    673        /** @type {number} */ var refOutOfBoundsLower = -0.1;
    674 
    675        /** @type {Array<{texNdx: number, ref: number, lodX: number, lodY: number, oX: number, oY: number}>} */
    676        var cases = [{ texNdx: 0, ref: refInRangeUpper, lodX: 1.6, lodY: 2.9, oX: -1.0, oY: -2.7 },{ texNdx: 0, ref: refInRangeLower, lodX: -2.0, lodY: -1.35, oX: -0.2, oY: 0.7 },{ texNdx: 1, ref: refInRangeUpper, lodX: 0.14, lodY: 0.275, oX: -1.5, oY: -1.1 },{ texNdx: 1, ref: refInRangeLower, lodX: -0.92, lodY: -2.64, oX: 0.4, oY: -0.1 },{ texNdx: 1, ref: refOutOfBoundsUpper, lodX: -0.49, lodY: -0.22, oX: 0.45, oY: 0.97 },{ texNdx: 1, ref: refOutOfBoundsLower, lodX: -0.85, lodY: 0.75, oX: 0.25, oY: 0.61 }
    677        ];
    678 
    679        var viewportW = Math.min(VIEWPORT_WIDTH, gl.canvas.width);
    680        var viewportH = Math.min(VIEWPORT_HEIGHT, gl.canvas.height);
    681 
    682        /** @type {number} */ var minLayer = -0.5;
    683        /** @type {number} */ var maxLayer = this.m_numLayers;
    684 
    685        for (var caseNdx = 0; caseNdx < cases.length; caseNdx++) {
    686            var tex = cases[caseNdx].texNdx > 0 ? this.m_gridTex : this.m_gradientTex;
    687            /** @type {number} */ var ref = cases[caseNdx].ref;
    688            /** @type {number} */ var lodX = cases[caseNdx].lodX;
    689            /** @type {number} */ var lodY = cases[caseNdx].lodY;
    690            /** @type {number} */ var oX = cases[caseNdx].oX;
    691            /** @type {number} */ var oY = cases[caseNdx].oY;
    692            /** @type {number} */ var sX = Math.exp(lodX * Math.LN2) * viewportW / tex.getRefTexture().getWidth();
    693            /** @type {number} */ var sY = Math.exp(lodY * Math.LN2) * viewportH / tex.getRefTexture().getHeight();
    694 
    695            this.m_cases.push(new es3fTextureShadowTests.FilterCase(tex, ref, [oX, oY, minLayer], [oX + sX, oY + sY, maxLayer]));
    696        }
    697 
    698        this.m_caseNdx = 0;
    699    };
    700 
    701    /**
    702     * @return {tcuTestCase.IterateResult}
    703     */
    704    es3fTextureShadowTests.Texture2DArrayShadowCase.prototype.iterate = function() {
    705        var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, deString.deStringHash(this.fullName()) ^ deMath.deMathHash(this.m_caseNdx));
    706        var curCase = this.m_cases[this.m_caseNdx];
    707        var sampleParams = new glsTextureTestUtil.ReferenceParams(glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY);
    708        var rendered = new tcuSurface.Surface(viewport.width, viewport.height);
    709        var texCoord = [];
    710 
    711        texCoord = [curCase.minCoord[0], curCase.minCoord[1], curCase.minCoord[2],
    712            curCase.minCoord[0], curCase.maxCoord[1], (curCase.minCoord[2] + curCase.maxCoord[2]) / 2.0,
    713            curCase.maxCoord[0], curCase.minCoord[1], (curCase.minCoord[2] + curCase.maxCoord[2]) / 2.0,
    714            curCase.maxCoord[0], curCase.maxCoord[1], curCase.maxCoord[2]];
    715 
    716        if (viewport.width < MIN_VIEWPORT_WIDTH || viewport.height < MIN_VIEWPORT_HEIGHT)
    717            throw new Error('Too small render target');
    718 
    719        sampleParams.sampler = gluTextureUtil.mapGLSamplerWrapST(this.m_wrapS, this.m_wrapT, this.m_minFilter, this.m_magFilter);
    720        sampleParams.sampler.compare = gluTextureUtil.mapGLCompareFunc(this.m_compareFunc);
    721        sampleParams.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW;
    722        sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT;
    723        sampleParams.ref = curCase.ref;
    724 
    725        bufferedLogToConsole(
    726            'Compare reference value = ' + sampleParams.ref + '\n' +
    727            'Texture Coordinates: ' + curCase.minCoord + ' -> ' + curCase.maxCoord
    728        );
    729 
    730        gl.bindTexture(gl.TEXTURE_2D_ARRAY, curCase.texture.getGLTexture());
    731        gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, this.m_minFilter);
    732        gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, this.m_magFilter);
    733        gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, this.m_wrapS);
    734        gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, this.m_wrapT);
    735        gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
    736        gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_COMPARE_FUNC, this.m_compareFunc);
    737 
    738        gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
    739        this.m_renderer.renderQuad(0, texCoord, sampleParams);
    740        rendered.readViewport(gl, viewport);
    741 
    742        var pixelFormat = new tcuPixelFormat.PixelFormat(8, 8, 8, 8);
    743        /** @type {tcuTexLookupVerifier.LodPrecision} */ var lodPrecision = new tcuTexLookupVerifier.LodPrecision(18, 6);
    744        /** @type {tcuTexCompareVerifier.TexComparePrecision} */ var texComparePrecision = new tcuTexCompareVerifier.TexComparePrecision(
    745            [20, 20, 20],
    746            [7, 7, 7],
    747            5,
    748            16,
    749            pixelFormat.redBits - 1
    750        );
    751 
    752        var isHighQuality = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2DArray, rendered.getAccess(), curCase.texture.getRefTexture(),
    753                                                          texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
    754 
    755        if (!isHighQuality) {
    756            bufferedLogToConsole('Warning: Verification assuming high-quality PCF filtering failed');
    757 
    758            lodPrecision.lodBits = 4;
    759            texComparePrecision.uvwBits = [4, 4, 4];
    760            texComparePrecision.pcfBits = 0;
    761 
    762            var isOk = es3fTextureShadowTests.verifyTexCompareResult(tcuTexture.Texture2DArray, rendered.getAccess(), curCase.texture.getRefTexture(),
    763                                                                                              texCoord, sampleParams, texComparePrecision, lodPrecision, pixelFormat);
    764 
    765            if (!isOk) {
    766                bufferedLogToConsole('ERROR: Verification against low precision requirements failed, failing test case.');
    767                testFailedOptions('Image verification failed', false);
    768            } else
    769                testPassedOptions('Low-quality result', true);
    770        } else
    771            testPassedOptions('High-quality result', true);
    772 
    773        this.m_caseNdx += 1;
    774        return this.m_caseNdx < this.m_cases.length ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
    775    };
    776 
    777    es3fTextureShadowTests.init = function() {
    778        /** @type {Array<es3fTextureShadowTests.Format>} */ var formats = [];
    779        formats.push(new es3fTextureShadowTests.Format('depth_component16', gl.DEPTH_COMPONENT16));
    780        formats.push(new es3fTextureShadowTests.Format('depth_component32f', gl.DEPTH_COMPONENT32F));
    781        formats.push(new es3fTextureShadowTests.Format('depth24_stencil8', gl.DEPTH24_STENCIL8));
    782 
    783        /** @type {Array<es3fTextureShadowTests.Filter>} */ var filters = [];
    784        filters.push(new es3fTextureShadowTests.Filter('nearest', gl.NEAREST, gl.NEAREST));
    785        filters.push(new es3fTextureShadowTests.Filter('linear', gl.LINEAR, gl.LINEAR));
    786        filters.push(new es3fTextureShadowTests.Filter('nearest_mipmap_nearest', gl.NEAREST_MIPMAP_NEAREST, gl.LINEAR));
    787        filters.push(new es3fTextureShadowTests.Filter('linear_mipmap_nearest', gl.LINEAR_MIPMAP_NEAREST, gl.LINEAR));
    788        filters.push(new es3fTextureShadowTests.Filter('nearest_mipmap_linear', gl.NEAREST_MIPMAP_LINEAR, gl.LINEAR));
    789        filters.push(new es3fTextureShadowTests.Filter('linear_mipmap_linear', gl.LINEAR_MIPMAP_LINEAR, gl.LINEAR));
    790 
    791        /** @type {Array<es3fTextureShadowTests.CompareFunc>} */ var compareFuncs = [];
    792        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('less_or_equal', gl.LEQUAL));
    793        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('greater_or_equal', gl.GEQUAL));
    794        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('less', gl.LESS));
    795        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('greater', gl.GREATER));
    796        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('equal', gl.EQUAL));
    797        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('not_equal', gl.NOTEQUAL));
    798        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('always', gl.ALWAYS));
    799        compareFuncs.push(new es3fTextureShadowTests.CompareFunc('never', gl.NEVER));
    800 
    801        var state = tcuTestCase.runner;
    802        /** @type {tcuTestCase.DeqpTest} */ var testGroup = state.testCases;
    803 
    804        for (var filterNdx = 0; filterNdx < filters.length; filterNdx++) {
    805            for (var compareNdx = 0; compareNdx < compareFuncs.length; compareNdx++) {
    806                var filterGroup = tcuTestCase.newTest(
    807                    '2d.' + filters[filterNdx].name, '2D texture shadow lookup tests');
    808                testGroup.addChild(filterGroup);
    809 
    810                for (var formatNdx = 0; formatNdx < formats.length; formatNdx++) {
    811                    /** @type {number} */ var minFilter = filters[filterNdx].minFilter;
    812                    /** @type {number} */ var magFilter = filters[filterNdx].magFilter;
    813                    /** @type {number} */ var format = formats[formatNdx].format;
    814                    /** @type {number} */ var compareFunc = compareFuncs[compareNdx].func;
    815                    /** @type {number} */ var wrapS = gl.REPEAT;
    816                    /** @type {number} */ var wrapT = gl.REPEAT;
    817                    /** @type {number} */ var width = 32;
    818                    /** @type {number} */ var height = 64;
    819                    /** @type {string} */ var name = compareFuncs[compareNdx].name + '_' + formats[formatNdx].name;
    820 
    821                    filterGroup.addChild(new es3fTextureShadowTests.Texture2DShadowCase(name, '', minFilter, magFilter, wrapS, wrapT, format, width, height, compareFunc));
    822                }
    823            }
    824        }
    825 
    826        for (filterNdx = 0; filterNdx < filters.length; filterNdx++) {
    827            for (compareNdx = 0; compareNdx < compareFuncs.length; compareNdx++) {
    828                filterGroup = tcuTestCase.newTest(
    829                    'cube.' + filters[filterNdx].name, 'Cube map texture shadow lookup tests');
    830                testGroup.addChild(filterGroup);
    831 
    832                for (formatNdx = 0; formatNdx < formats.length; formatNdx++) {
    833                    minFilter = filters[filterNdx].minFilter;
    834                    magFilter = filters[filterNdx].magFilter;
    835                    format = formats[formatNdx].format;
    836                    compareFunc = compareFuncs[compareNdx].func;
    837                    wrapS = gl.REPEAT;
    838                    wrapT = gl.REPEAT;
    839                    var size = 32;
    840                    name = compareFuncs[compareNdx].name + '_' + formats[formatNdx].name;
    841 
    842                    filterGroup.addChild(new es3fTextureShadowTests.TextureCubeShadowCase(name, '', minFilter, magFilter, wrapS, wrapT, format, size, compareFunc));
    843                }
    844            }
    845        }
    846 
    847        for (var filterNdx = 0; filterNdx < filters.length; filterNdx++) {
    848            for (var compareNdx = 0; compareNdx < compareFuncs.length; compareNdx++) {
    849                filterGroup = tcuTestCase.newTest(
    850                    '2d_array.' + filters[filterNdx].name, '2D texture array shadow lookup tests');
    851                testGroup.addChild(filterGroup);
    852 
    853                for (var formatNdx = 0; formatNdx < formats.length; formatNdx++) {
    854                    minFilter = filters[filterNdx].minFilter;
    855                    magFilter = filters[filterNdx].magFilter;
    856                    format = formats[formatNdx].format;
    857                    compareFunc = compareFuncs[compareNdx].func;
    858                    wrapS = gl.REPEAT;
    859                    wrapT = gl.REPEAT;
    860                    width = 32;
    861                    height = 64;
    862                    var numLayers = 8;
    863                    name = compareFuncs[compareNdx].name + '_' + formats[formatNdx].name;
    864 
    865                    filterGroup.addChild(new es3fTextureShadowTests.Texture2DArrayShadowCase(name, '', minFilter, magFilter, wrapS, wrapT, format, width, height, numLayers, compareFunc));
    866                }
    867            }
    868        }
    869    };
    870 
    871    es3fTextureShadowTests.run = function(context, range) {
    872        gl = context;
    873        //Set up Test Root parameters
    874        var testName = 'texture_shadow';
    875        var testDescription = 'Texture Shadow Test';
    876        var state = tcuTestCase.runner;
    877 
    878        state.testName = testName;
    879        state.testCases = tcuTestCase.newTest(testName, testDescription, null);
    880 
    881        //Set up name and description of this test series.
    882        setCurrentTestName(testName);
    883        description(testDescription);
    884 
    885        try {
    886            //Create test cases
    887            es3fTextureShadowTests.init();
    888            if (range)
    889                state.setRange(range);
    890            //Run test cases
    891            tcuTestCase.runTestCases();
    892        }
    893        catch (err) {
    894            bufferedLogToConsole(err);
    895            tcuTestCase.runner.terminate();
    896        }
    897    };
    898 });