diff options
Diffstat (limited to '')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js | 2282 |
1 files changed, 2282 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js new file mode 100644 index 0000000000..45ff09a11c --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js @@ -0,0 +1,2282 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program OpenGL ES Utilities + * ------------------------------------------------ + * + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +'use strict'; +goog.provide('functional.gles3.es3fTextureFilteringTests'); +goog.require('framework.common.tcuImageCompare'); +goog.require('framework.common.tcuLogImage'); +goog.require('framework.common.tcuPixelFormat'); +goog.require('framework.common.tcuRGBA'); +goog.require('framework.common.tcuSurface'); +goog.require('framework.common.tcuTestCase'); +goog.require('framework.common.tcuTexLookupVerifier'); +goog.require('framework.common.tcuTexture'); +goog.require('framework.common.tcuTextureUtil'); +goog.require('framework.delibs.debase.deMath'); +goog.require('framework.delibs.debase.deRandom'); +goog.require('framework.delibs.debase.deString'); +goog.require('framework.opengl.gluShaderUtil'); +goog.require('framework.opengl.gluTexture'); +goog.require('framework.opengl.gluTextureUtil'); +goog.require('functional.gles3.es3fFboTestUtil'); +goog.require('modules.shared.glsTextureTestUtil'); + +goog.scope(function() { + + var es3fTextureFilteringTests = functional.gles3.es3fTextureFilteringTests; + var es3fFboTestUtil = functional.gles3.es3fFboTestUtil; + var gluShaderUtil = framework.opengl.gluShaderUtil; + var gluTextureUtil = framework.opengl.gluTextureUtil; + var tcuImageCompare = framework.common.tcuImageCompare; + var tcuLogImage = framework.common.tcuLogImage; + var tcuPixelFormat = framework.common.tcuPixelFormat; + var tcuRGBA = framework.common.tcuRGBA; + var tcuTestCase = framework.common.tcuTestCase; + var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier; + var tcuSurface = framework.common.tcuSurface; + var tcuTexture = framework.common.tcuTexture; + var tcuTextureUtil = framework.common.tcuTextureUtil; + var deMath = framework.delibs.debase.deMath; + var deString = framework.delibs.debase.deString; + var deRandom = framework.delibs.debase.deRandom; + var gluTexture = framework.opengl.gluTexture; + var glsTextureTestUtil = modules.shared.glsTextureTestUtil; + + /** @type {WebGL2RenderingContext} */ var gl; + + es3fTextureFilteringTests.version = + gluShaderUtil.getGLSLVersionString(gluShaderUtil.GLSLVersion.V300_ES); + + let canvasWH = 256; + let viewportWH = 64; + + if (tcuTestCase.isQuickMode()) { + canvasWH = 64; + viewportWH = 32; + } + + const TEX2D_VIEWPORT_WIDTH = viewportWH; + const TEX2D_VIEWPORT_HEIGHT = viewportWH; + const TEX2D_MIN_VIEWPORT_WIDTH = viewportWH; + const TEX2D_MIN_VIEWPORT_HEIGHT = viewportWH; + + const TEX3D_VIEWPORT_WIDTH = viewportWH; + const TEX3D_VIEWPORT_HEIGHT = viewportWH; + const TEX3D_MIN_VIEWPORT_WIDTH = viewportWH; + const TEX3D_MIN_VIEWPORT_HEIGHT = viewportWH; + + /** + * @constructor + * @extends {tcuTestCase.DeqpTest} + */ + es3fTextureFilteringTests.TextureFilteringTests = function() { + tcuTestCase.DeqpTest.call(this, 'filtering', 'Texture Filtering Tests'); + }; + + es3fTextureFilteringTests.TextureFilteringTests.prototype = + Object.create(tcuTestCase.DeqpTest.prototype); + + es3fTextureFilteringTests.TextureFilteringTests.prototype.constructor = + es3fTextureFilteringTests.TextureFilteringTests; + + /** + * @constructor + * @extends {tcuTestCase.DeqpTest} + * @param {string} name + * @param {string} desc + * @param {number} minFilter + * @param {number} magFilter + * @param {number} wrapS + * @param {number} wrapT + * @param {number} internalFormat + * @param {number} width + * @param {number} height + */ + es3fTextureFilteringTests.Texture2DFilteringCase = function( + name, desc, minFilter, magFilter, wrapS, wrapT, + internalFormat, width, height + ) { + tcuTestCase.DeqpTest.call(this, name, desc); + this.m_minFilter = minFilter; + this.m_magFilter = magFilter; + this.m_wrapS = wrapS; + this.m_wrapT = wrapT; + this.m_internalFormat = internalFormat; + this.m_width = width; + this.m_height = height; + /** @type {glsTextureTestUtil.TextureRenderer} */ + this.m_renderer = new glsTextureTestUtil.TextureRenderer( + es3fTextureFilteringTests.version, + gluShaderUtil.precision.PRECISION_HIGHP + ); + this.m_caseNdx = 0; + /** @type {Array<gluTexture.Texture2D>} */ this.m_textures = []; + this.m_cases = []; + }; + + es3fTextureFilteringTests.Texture2DFilteringCase.prototype = + Object.create(tcuTestCase.DeqpTest.prototype); + es3fTextureFilteringTests.Texture2DFilteringCase.prototype.constructor = + es3fTextureFilteringTests.Texture2DFilteringCase; + + /** + * @constructor + * @param {gluTexture.Texture2D} tex_ + * @param {Array<number>} minCoord_ + * @param {Array<number>} maxCoord_ + */ + es3fTextureFilteringTests.Texture2DFilteringCase.FilterCase = function( + tex_, minCoord_, maxCoord_ + ) { + this.texture = tex_; + this.minCoord = minCoord_; + this.maxCoord = maxCoord_; + }; + + /** @typedef {{texNdx: number, lodX: number, + * lodY: number, oX: number, oY: number}} */ + es3fTextureFilteringTests.Cases; + + /** + * init + */ + es3fTextureFilteringTests.Texture2DFilteringCase.prototype.init = + function() { + try { + // Create 2 textures. + for (var ndx = 0; ndx < 2; ndx++) + this.m_textures.push( + gluTexture.texture2DFromInternalFormat( + gl, this.m_internalFormat, + this.m_width, this.m_height + ) + ); + + var mipmaps = true; + var numLevels = mipmaps ? deMath.logToFloor( + Math.max(this.m_width, this.m_height) + ) + 1 : 1; + + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo( + this.m_textures[0].getRefTexture().getFormat() + ); + /** @type {Array<number>} */ var cBias = fmtInfo.valueMin; + /** @type {Array<number>} */ + var cScale = deMath.subtract( + fmtInfo.valueMax, fmtInfo.valueMin + ); + + // Fill first gradient texture. + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + /** @type {Array<number>} */ var gMin = deMath.add( + deMath.multiply([0.0, 0.0, 0.0, 1.0], cScale), cBias + ); + /** @type {Array<number>} */ var gMax = deMath.add( + deMath.multiply([1.0, 1.0, 1.0, 0.0], cScale), cBias + ); + + this.m_textures[0].getRefTexture().allocLevel(levelNdx); + tcuTextureUtil.fillWithComponentGradients( + this.m_textures[0].getRefTexture().getLevel(levelNdx), + gMin, gMax + ); + } + + // Fill second with grid texture. + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + /** @type {number} */ var step = 0x00ffffff / numLevels; + /** @type {number} */ var rgb = step * levelNdx; + /** @type {number} */ var colorA = deMath.binaryOp( + 0xff000000, rgb, deMath.BinaryOp.OR + ); + /** @type {number} */ var colorB = deMath.binaryOp( + 0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR + ); + + this.m_textures[1].getRefTexture().allocLevel(levelNdx); + tcuTextureUtil.fillWithGrid( + this.m_textures[1].getRefTexture().getLevel(levelNdx), + 4, + deMath.add(deMath.multiply( + tcuRGBA.newRGBAFromValue(colorA).toVec(), cScale), + cBias + ), + deMath.add(deMath.multiply( + tcuRGBA.newRGBAFromValue(colorB).toVec(), cScale), + cBias + ) + ); + } + + // Upload. + for (var i = 0; i < this.m_textures.length; i++) + this.m_textures[i].upload(); + + // Compute cases. + + /** @type {Array<es3fTextureFilteringTests.Cases>} */ + var cases = [{ + texNdx: 0, lodX: 1.6, lodY: 2.9, oX: -1.0, oY: -2.7 + }, { + texNdx: 0, lodX: -2.0, lodY: -1.35, oX: -0.2, oY: 0.7 + }, { + texNdx: 1, lodX: 0.14, lodY: 0.275, oX: -1.5, oY: -1.1 + }, { + texNdx: 1, lodX: -0.92, lodY: -2.64, oX: 0.4, oY: -0.1 + } + ]; + + var viewportW = Math.min( + TEX2D_VIEWPORT_WIDTH, gl.canvas.width + ); + var viewportH = Math.min( + TEX2D_VIEWPORT_HEIGHT, gl.canvas.height + ); + + for (var caseNdx = 0; caseNdx < cases.length; caseNdx++) { + /** @type {number} */ var texNdx = deMath.clamp( + cases[caseNdx].texNdx, 0, this.m_textures.length - 1 + ); + /** @type {number} */ var lodX = cases[caseNdx].lodX; + /** @type {number} */ var lodY = cases[caseNdx].lodY; + /** @type {number} */ var oX = cases[caseNdx].oX; + /** @type {number} */ var oY = cases[caseNdx].oY; + /** @type {number} */ var sX = Math.exp(lodX * Math.log(2)) * viewportW / + this.m_textures[texNdx].getRefTexture().getWidth(); + /** @type {number} */ var sY = Math.exp(lodY * Math.log(2)) * viewportH / + this.m_textures[texNdx].getRefTexture().getHeight(); + + this.m_cases.push( + new + es3fTextureFilteringTests.Texture2DFilteringCase.FilterCase( + this.m_textures[texNdx], [oX, oY], [oX + sX, oY + sY] + ) + ); + } + + this.m_caseNdx = 0; + } + catch (e) { + // Clean up to save memory. + this.deinit(); + throw e; + } + }; + + /** + * deinit + */ + es3fTextureFilteringTests.Texture2DFilteringCase.prototype.deinit = + function() { + while (this.m_textures.length > 0) { + gl.deleteTexture(this.m_textures[0].getGLTexture()); + this.m_textures.splice(0, 1); + } + }; + + /** + * @return {tcuTestCase.IterateResult} + */ + es3fTextureFilteringTests.Texture2DFilteringCase.prototype.iterate = + function() { + /** @type {glsTextureTestUtil.RandomViewport} */ + var viewport = new glsTextureTestUtil.RandomViewport( + gl.canvas, TEX2D_VIEWPORT_WIDTH, + TEX2D_VIEWPORT_HEIGHT, deMath.binaryOp( + deString.deStringHash(this.fullName()), + deMath.deMathHash(this.m_caseNdx), + deMath.BinaryOp.XOR + ) + ); + /** @type {tcuTexture.TextureFormat} */ + var texFmt = this.m_textures[0].getRefTexture().getFormat(); + + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt); + var curCase = this.m_cases[this.m_caseNdx]; + bufferedLogToConsole('Test ' + this.m_caseNdx); + var refParams = new glsTextureTestUtil.ReferenceParams( + glsTextureTestUtil.textureType.TEXTURETYPE_2D + ); + var rendered = new tcuSurface.Surface(viewport.width, viewport.height); + var texCoord = [0, 0]; + + if (viewport.width < TEX2D_MIN_VIEWPORT_WIDTH || + viewport.height < TEX2D_MIN_VIEWPORT_HEIGHT) + throw new Error('Too small render target'); + + // Setup params for reference. + refParams.sampler = gluTextureUtil.mapGLSamplerWrapST( + this.m_wrapS, this.m_wrapT, this.m_minFilter, this.m_magFilter + ); + refParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt); + refParams.lodMode = glsTextureTestUtil.lodMode.EXACT; + refParams.colorBias = fmtInfo.lookupBias; + refParams.colorScale = fmtInfo.lookupScale; + + // Compute texture coordinates. + bufferedLogToConsole( + 'Texture coordinates: ' + curCase.minCoord + + ' -> ' + curCase.maxCoord + ); + texCoord = glsTextureTestUtil.computeQuadTexCoord2D( + curCase.minCoord, curCase.maxCoord + ); + + gl.bindTexture(gl.TEXTURE_2D, curCase.texture.getGLTexture()); + gl.texParameteri( + gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_minFilter + ); + gl.texParameteri( + gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_magFilter + ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.m_wrapS); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.m_wrapT); + + gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); + + this.m_renderer.renderQuad(0, texCoord, refParams); + rendered.readViewport( + gl, [viewport.x, viewport.y, viewport.width, viewport.height] + ); + + /** @type {boolean} */ var isNearestOnly = + this.m_minFilter == gl.NEAREST && this.m_magFilter == gl.NEAREST; + /** @type {tcuPixelFormat.PixelFormat} */ + var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl); + + //(iVec4) + var colorBits = deMath.max( + deMath.addScalar( + glsTextureTestUtil.getBitsVec(pixelFormat), + // 1 inaccurate bit if nearest only, 2 otherwise + -1 * (isNearestOnly ? 1 : 2) + ), + [0, 0, 0, 0] + ); + + /** @type {tcuTexLookupVerifier.LodPrecision} */ + var lodPrecision = new tcuTexLookupVerifier.LodPrecision(); + /** @type {tcuTexLookupVerifier.LookupPrecision} */ + var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision(); + + lodPrecision.derivateBits = 18; + lodPrecision.lodBits = 6; + lookupPrecision.colorThreshold = deMath.divide( + tcuTexLookupVerifier.computeFixedPointThreshold(colorBits), + refParams.colorScale + ); + lookupPrecision.coordBits = [20, 20, 0]; + lookupPrecision.uvwBits = [7, 7, 0]; + lookupPrecision.colorMask = + glsTextureTestUtil.getCompareMask(pixelFormat); + + var isHighQuality = glsTextureTestUtil.verifyTexture2DResult( + rendered.getAccess(), curCase.texture.getRefTexture(), + texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat + ); + + if (!isHighQuality) { + // Evaluate against lower precision requirements. + lodPrecision.lodBits = 4; + lookupPrecision.uvwBits = [4, 4, 0]; + + bufferedLogToConsole('Warning: Verification against high ' + + 'precision requirements failed, trying with lower ' + + 'requirements.' + ); + + var isOk = glsTextureTestUtil.verifyTexture2DResult( + rendered.getAccess(), curCase.texture.getRefTexture(), + texCoord, refParams, lookupPrecision, lodPrecision, + pixelFormat + ); + + if (!isOk) { + bufferedLogToConsole( + 'ERROR: Verification against low ' + + 'precision requirements failed, failing test case.' + ); + testFailedOptions('Image verification failed', false); + //In JS version, one mistake and you're out + return tcuTestCase.IterateResult.STOP; + } else + checkMessage( + false, + 'Low-quality filtering result in iteration no. ' + + this.m_caseNdx + ); + } + + this.m_caseNdx += 1; + if (this.m_caseNdx < this.m_cases.length) + return tcuTestCase.IterateResult.CONTINUE; + + testPassed('Verified'); + return tcuTestCase.IterateResult.STOP; + }; + + /** + * @constructor + * @extends {tcuTestCase.DeqpTest} + * @param {string} name + * @param {string} desc + * @param {number} minFilter + * @param {number} magFilter + * @param {number} wrapS + * @param {number} wrapT + * @param {boolean} onlySampleFaceInterior + * @param {number} internalFormat + * @param {number} width + * @param {number} height + */ + es3fTextureFilteringTests.TextureCubeFilteringCase = function( + name, desc, minFilter, magFilter, wrapS, wrapT, onlySampleFaceInterior, + internalFormat, width, height + ) { + tcuTestCase.DeqpTest.call(this, name, desc); + this.m_minFilter = minFilter; + this.m_magFilter = magFilter; + this.m_wrapS = wrapS; + this.m_wrapT = wrapT; + /** @type {boolean}*/ + this.m_onlySampleFaceInterior = onlySampleFaceInterior; + this.m_internalFormat = internalFormat; + this.m_width = width; + this.m_height = height; + /** @type {glsTextureTestUtil.TextureRenderer} */ + this.m_renderer = new glsTextureTestUtil.TextureRenderer( + es3fTextureFilteringTests.version, + gluShaderUtil.precision.PRECISION_HIGHP + ); + this.m_caseNdx = 0; + /** @type {Array<gluTexture.TextureCube>} */ this.m_textures = []; + /** @type {Array<es3fTextureFilteringTests. + * TextureCubeFilteringCase.FilterCase>} + */ + this.m_cases = []; + }; + + /** + * @constructor + * @param {gluTexture.TextureCube} tex_ + * @param {Array<number>} bottomLeft_ + * @param {Array<number>} topRight_ + */ + es3fTextureFilteringTests.TextureCubeFilteringCase.FilterCase = function( + tex_, bottomLeft_, topRight_ + ) { + this.texture = tex_; + this.bottomLeft = bottomLeft_; + this.topRight = topRight_; + }; + + es3fTextureFilteringTests.TextureCubeFilteringCase.prototype = + Object.create(tcuTestCase.DeqpTest.prototype); + + es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.constructor = + es3fTextureFilteringTests.TextureCubeFilteringCase; + + /** + * init + */ + es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.init = + function() { + try { + assertMsgOptions( + this.m_width == this.m_height, 'Texture has to be squared', + false, true + ); + for (var ndx = 0; ndx < 2; ndx++) + this.m_textures.push(gluTexture.cubeFromInternalFormat( + gl, this.m_internalFormat, this.m_width + )); + + var numLevels = deMath.logToFloor( + Math.max(this.m_width, this.m_height) + ) + 1; + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo( + this.m_textures[0].getRefTexture().getFormat() + ); + /** @type {Array<number>} */ + var cBias = fmtInfo.valueMin; + /** @type {Array<number>} */ + var cScale = deMath.subtract( + fmtInfo.valueMax, fmtInfo.valueMin + ); + + // Fill first with gradient texture. + /** @type {Array<Array<Array<number>>>} + * (array of 4 component vectors) + */ + var gradients = [ + [ // negative x + [0.0, 0.0, 0.0, 1.0], [1.0, 1.0, 1.0, 0.0] + ], [ // positive x + [0.5, 0.0, 0.0, 1.0], [1.0, 1.0, 1.0, 0.0] + ], [ // negative y + [0.0, 0.5, 0.0, 1.0], [1.0, 1.0, 1.0, 0.0] + ], [ // positive y + [0.0, 0.0, 0.5, 1.0], [1.0, 1.0, 1.0, 0.0] + ], [ // negative z + [0.0, 0.0, 0.0, 0.5], [1.0, 1.0, 1.0, 1.0] + ], [ // positive z + [0.5, 0.5, 0.5, 1.0], [1.0, 1.0, 1.0, 0.0] + ] + ]; + for (var face = 0; + face < Object.keys(tcuTexture.CubeFace).length; + face++) { + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + this.m_textures[0].getRefTexture().allocLevel( + face, levelNdx + ); + tcuTextureUtil.fillWithComponentGradients( + this.m_textures[0].getRefTexture().getLevelFace( + levelNdx, face + ), + deMath.add(deMath.multiply( + gradients[face][0], cScale + ), cBias), + deMath.add(deMath.multiply( + gradients[face][1], cScale + ), cBias) + ); + } + } + + // Fill second with grid texture. + for (var face = 0; + face < Object.keys(tcuTexture.CubeFace).length; + face++) { + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + var step = 0x00ffffff / ( + numLevels * Object.keys(tcuTexture.CubeFace).length + ); + var rgb = step * levelNdx * face; + /** @type {number} */ var colorA = deMath.binaryOp( + 0xff000000, rgb, deMath.BinaryOp.OR + ); + /** @type {number} */ var colorB = deMath.binaryOp( + 0xff000000, deMath.binaryNot(rgb), + deMath.BinaryOp.OR + ); + + this.m_textures[1].getRefTexture().allocLevel( + face, levelNdx + ); + tcuTextureUtil.fillWithGrid( + this.m_textures[1].getRefTexture().getLevelFace( + levelNdx, face + ), 4, deMath.add( + deMath.multiply( + tcuRGBA.newRGBAFromValue(colorA).toVec(), + cScale + ), cBias + ), deMath.add( + deMath.multiply( + tcuRGBA.newRGBAFromValue(colorB).toVec(), + cScale + ), cBias + ) + ); + } + } + + // Upload. + for (var i = 0; i < this.m_textures.length; i++) + this.m_textures[i].upload(); + + // Compute cases + /** @type {gluTexture.TextureCube} */ + var tex0 = this.m_textures[0]; + /** @type {gluTexture.TextureCube} */ + var tex1 = this.m_textures.length > 1 ? this.m_textures[1] : tex0; + + if (this.m_onlySampleFaceInterior) { + // minification + this.m_cases.push(new es3fTextureFilteringTests. + TextureCubeFilteringCase.FilterCase( + tex0, [-0.8, -0.8], [0.8, 0.8] + )); + // magnification + this.m_cases.push(new es3fTextureFilteringTests. + TextureCubeFilteringCase.FilterCase( + tex0, [0.5, 0.65], [0.8, 0.8] + )); + // minification + this.m_cases.push(new es3fTextureFilteringTests. + TextureCubeFilteringCase.FilterCase( + tex1, [-0.8, -0.8], [0.8, 0.8] + )); + // magnification + this.m_cases.push(new es3fTextureFilteringTests. + TextureCubeFilteringCase.FilterCase( + tex1, [0.2, 0.2], [0.6, 0.5] + )); + } else { + // minification + if (gl.getParameter(gl.SAMPLES) == 0) + this.m_cases.push( + new es3fTextureFilteringTests.TextureCubeFilteringCase. + FilterCase( + tex0, [-1.25, -1.2], [1.2, 1.25] + ) + ); + // minification - w/ tweak to avoid hitting triangle + // edges with face switchpoint. + else + this.m_cases.push( + new es3fTextureFilteringTests.TextureCubeFilteringCase. + FilterCase( + tex0, [-1.19, -1.3], [1.1, 1.35] + ) + ); + + // magnification + this.m_cases.push( + new es3fTextureFilteringTests.TextureCubeFilteringCase. + FilterCase( + tex0, [0.8, 0.8], [1.25, 1.20] + ) + ); + // minification + this.m_cases.push( + new es3fTextureFilteringTests.TextureCubeFilteringCase. + FilterCase( + tex1, [-1.19, -1.3], [1.1, 1.35] + ) + ); + // magnification + this.m_cases.push( + new es3fTextureFilteringTests.TextureCubeFilteringCase. + FilterCase( + tex1, [-1.2, -1.1], [-0.8, -0.8] + ) + ); + } + + this.m_caseNdx = 0; + } + catch (e) { + // Clean up to save memory. + this.deinit(); + throw e; + } + }; + + /** + * deinit + */ + es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.deinit = + function() { + while (this.m_textures.length > 0) { + gl.deleteTexture(this.m_textures[0].getGLTexture()); + this.m_textures.splice(0, 1); + } + }; + + /** + * @param {tcuTexture.CubeFace} face + * @return {string} + */ + es3fTextureFilteringTests.getFaceDesc = function(face) { + switch (face) { + case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: return '-X'; + case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: return '+X'; + case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: return '-Y'; + case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: return '+Y'; + case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: return '-Z'; + case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: return '+Z'; + default: + throw new Error('Invalid cube face specified'); + } + }; + + /** + * @return {tcuTestCase.IterateResult} + */ + es3fTextureFilteringTests.TextureCubeFilteringCase.prototype.iterate = + function() { + var viewportSize = 28; + /** @type {glsTextureTestUtil.RandomViewport} */ + var viewport = new glsTextureTestUtil.RandomViewport( + gl.canvas, viewportSize, + viewportSize, deMath.binaryOp( + deString.deStringHash(this.fullName()), + deMath.deMathHash(this.m_caseNdx), + deMath.BinaryOp.XOR + ) + ); + bufferedLogToConsole('Test' + this.m_caseNdx); + /** @type {es3fTextureFilteringTests. + * TextureCubeFilteringCase.FilterCase} + */ + var curCase = this.m_cases[this.m_caseNdx]; + /** @type {tcuTexture.TextureFormat} */ + var texFmt = curCase.texture.getRefTexture().getFormat(); + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt); + /** @type {glsTextureTestUtil.ReferenceParams} */ + var sampleParams = new glsTextureTestUtil.ReferenceParams( + glsTextureTestUtil.textureType.TEXTURETYPE_CUBE + ); + + if (viewport.width < viewportSize || viewport.height < viewportSize) + throw new Error('Too small render target'); + + // Setup texture + gl.bindTexture(gl.TEXTURE_CUBE_MAP, curCase.texture.getGLTexture()); + gl.texParameteri( + gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, this.m_minFilter + ); + gl.texParameteri( + gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, this.m_magFilter + ); + gl.texParameteri( + gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this.m_wrapS + ); + gl.texParameteri( + gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this.m_wrapT + ); + + // Other state + gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); + + // Params for reference computation. + sampleParams.sampler = gluTextureUtil.mapGLSamplerWrapST( + gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, + this.m_minFilter, this.m_magFilter + ); + sampleParams.sampler.seamlessCubeMap = true; + sampleParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt); + sampleParams.colorBias = fmtInfo.lookupBias; + sampleParams.colorScale = fmtInfo.lookupScale; + sampleParams.lodMode = glsTextureTestUtil.lodMode.EXACT; + + bufferedLogToConsole( + 'Coordinates: ' + curCase.bottomLeft + ' -> ' + curCase.topRight + ); + + for (var faceNdx = 0; + faceNdx < Object.keys(tcuTexture.CubeFace).length; + faceNdx++) { + var face = /** @type {tcuTexture.CubeFace} */ (faceNdx); + /** @type {tcuSurface.Surface} */ + var result = new tcuSurface.Surface( + viewport.width, viewport.height + ); + /** @type {Array<number>} */ var texCoord; + + texCoord = glsTextureTestUtil.computeQuadTexCoordCubeFace( + face, curCase.bottomLeft, curCase.topRight + ); + + bufferedLogToConsole( + 'Face ' + es3fTextureFilteringTests.getFaceDesc(face) + ); + + // \todo Log texture coordinates. + + this.m_renderer.renderQuad(0, texCoord, sampleParams); + + result.readViewport( + gl, [viewport.x, viewport.y, viewport.width, viewport.height] + ); + + /** @type {boolean} */ + var isNearestOnly = this.m_minFilter == gl.NEAREST && + this.m_magFilter == gl.NEAREST; + /** @type {tcuPixelFormat.PixelFormat} */ + var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl); + + //(iVec4) + var colorBits = deMath.max( + deMath.addScalar( + glsTextureTestUtil.getBitsVec(pixelFormat), + // 1 inaccurate bit if nearest only, 2 otherwise + -1 * (isNearestOnly ? 1 : 2) + ), + [0, 0, 0, 0] + ); + /** @type {tcuTexLookupVerifier.LodPrecision} */ + var lodPrecision = new tcuTexLookupVerifier.LodPrecision(); + /** @type {tcuTexLookupVerifier.LookupPrecision} */ + var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision(); + + lodPrecision.derivateBits = 10; + lodPrecision.lodBits = 5; + lookupPrecision.colorThreshold = deMath.divide( + tcuTexLookupVerifier.computeFixedPointThreshold(colorBits), + sampleParams.colorScale + ); + lookupPrecision.coordBits = [10, 10, 10]; + lookupPrecision.uvwBits = [6, 6, 0]; + lookupPrecision.colorMask = + glsTextureTestUtil.getCompareMask(pixelFormat); + + var isHighQuality = glsTextureTestUtil.verifyTextureCubeResult( + result.getAccess(), curCase.texture.getRefTexture(), + texCoord, sampleParams, lookupPrecision, lodPrecision, + pixelFormat + ); + + + if (!isHighQuality) { + // Evaluate against lower precision requirements. + lodPrecision.lodBits = 2; + lookupPrecision.uvwBits = [3, 3, 0]; + + bufferedLogToConsole('Warning: Verification against high ' + + 'precision requirements failed, trying with lower ' + + 'requirements.'); + + var isOk = glsTextureTestUtil.verifyTextureCubeResult( + result.getAccess(), curCase.texture.getRefTexture(), + texCoord, sampleParams, lookupPrecision, lodPrecision, + pixelFormat + ); + + if (!isOk) { + bufferedLogToConsole('ERROR: Verification against low' + + 'precision requirements failed, failing test case.'); + testFailedOptions('Image verification failed', false); + //In JS version, one mistake and you're out + return tcuTestCase.IterateResult.STOP; + } else + checkMessage( + false, + 'Low-quality filtering result in iteration no. ' + + this.m_caseNdx + ); + } + } + + this.m_caseNdx += 1; + if (this.m_caseNdx < this.m_cases.length) + return tcuTestCase.IterateResult.CONTINUE; + + testPassed('Verified'); + return tcuTestCase.IterateResult.STOP; + }; + + // 2D array filtering + + /** + * @constructor + * @extends {tcuTestCase.DeqpTest} + * @param {string} name + * @param {string} desc + * @param {number} minFilter + * @param {number} magFilter + * @param {number} wrapS + * @param {number} wrapT + * @param {number} internalFormat + * @param {number} width + * @param {number} height + * @param {number} numLayers + */ + es3fTextureFilteringTests.Texture2DArrayFilteringCase = function( + name, desc, minFilter, magFilter, wrapS, wrapT, + internalFormat, width, height, numLayers + ) { + tcuTestCase.DeqpTest.call(this, name, desc); + this.m_minFilter = minFilter; + this.m_magFilter = magFilter; + this.m_wrapS = wrapS; + this.m_wrapT = wrapT; + this.m_internalFormat = internalFormat; + this.m_width = width; + this.m_height = height; + this.m_numLayers = numLayers; + this.m_gradientTex = null; + this.m_gridTex = null; + /** @type {glsTextureTestUtil.TextureRenderer} */ + this.m_renderer = new glsTextureTestUtil.TextureRenderer( + es3fTextureFilteringTests.version, + gluShaderUtil.precision.PRECISION_HIGHP + ); + this.m_textures = []; + this.m_caseNdx = 0; + this.m_cases = []; + }; + + es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype = + Object.create(tcuTestCase.DeqpTest.prototype); + + es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype. + constructor = es3fTextureFilteringTests.Texture2DArrayFilteringCase; + + /** + * @constructor + * @param {gluTexture.Texture2DArray} tex_ + * @param {Array<number>} lod_ + * @param {Array<number>} offset_ + * @param {Array<number>} layerRange_ + */ + es3fTextureFilteringTests.Texture2DArrayFilteringCase.FilterCase = + function( + tex_, lod_, offset_, layerRange_ + ) { + this.texture = tex_; + this.lod = lod_; + this.offset = offset_; + this.layerRange = layerRange_; + }; + + /* + * init + */ + es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype.init = + function() { + try { + /** @type {tcuTexture.TextureFormat} */ + var texFmt = gluTextureUtil.mapGLInternalFormat( + this.m_internalFormat + ); + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt); + var cScale = deMath.subtract( + fmtInfo.valueMax, fmtInfo.valueMin + ); + var cBias = fmtInfo.valueMin; + var numLevels = deMath.logToFloor( + Math.max(this.m_width, this.m_height) + ) + 1; + + // Create textures. + this.m_gradientTex = gluTexture.texture2DArrayFromInternalFormat( + gl, + this.m_internalFormat, this.m_width, + this.m_height, this.m_numLayers + ); + + this.m_gridTex = gluTexture.texture2DArrayFromInternalFormat( + gl, + this.m_internalFormat, this.m_width, + this.m_height, this.m_numLayers + ); + + var levelSwz = [ + [0, 1, 2, 3], + [2, 1, 3, 0], + [3, 0, 1, 2], + [1, 3, 2, 0] + ]; + + // Fill first gradient texture + // (gradient direction varies between layers). + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + this.m_gradientTex.getRefTexture().allocLevel(levelNdx); + + var levelBuf = + this.m_gradientTex.getRefTexture().getLevel(levelNdx); + + for (var layerNdx = 0; + layerNdx < this.m_numLayers; + layerNdx++) { + var swz = levelSwz[layerNdx % levelSwz.length]; + var gMin = deMath.add(deMath.multiply(deMath.swizzle( + [0.0, 0.0, 0.0, 1.0], [swz[0], swz[1], swz[2], swz[3]] + ), cScale), cBias); + var gMax = deMath.add(deMath.multiply(deMath.swizzle( + [1.0, 1.0, 1.0, 0.0], [swz[0], swz[1], swz[2], swz[3]] + ), cScale), cBias); + + tcuTextureUtil.fillWithComponentGradients2D( + tcuTextureUtil.getSubregion( + levelBuf, 0, 0, layerNdx, levelBuf.getWidth(), + levelBuf.getHeight(), 1 + ), gMin, gMax + ); + } + } + + // Fill second with grid texture (each layer has unique colors). + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + this.m_gridTex.getRefTexture().allocLevel(levelNdx); + + /** @type {tcuTexture.PixelBufferAccess} */ var levelBuf = + this.m_gridTex.getRefTexture().getLevel(levelNdx); + + for ( + var layerNdx = 0; + layerNdx < this.m_numLayers; + layerNdx++) { + var step = 0x00ffffff / (numLevels * this.m_numLayers - 1); + var rgb = step * (levelNdx + layerNdx * numLevels); + /** @type {number} */ var colorA = deMath.binaryOp( + 0xff000000, rgb, deMath.BinaryOp.OR + ); + /** @type {number} */ var colorB = deMath.binaryOp( + 0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR + ); + + tcuTextureUtil.fillWithGrid( + tcuTextureUtil.getSubregion( + levelBuf, 0, 0, layerNdx, levelBuf.getWidth(), + levelBuf.getHeight(), 1 + ), 4, + deMath.add( + deMath.multiply( + tcuRGBA.newRGBAFromValue(colorA).toVec(), + cScale + ), cBias + ), + deMath.add( + deMath.multiply( + tcuRGBA.newRGBAFromValue(colorB).toVec(), + cScale + ), cBias + ) + ); + } + } + + // Upload. + this.m_gradientTex.upload(); + this.m_gridTex.upload(); + + // Test cases + this.m_cases.push( + new es3fTextureFilteringTests. + Texture2DArrayFilteringCase.FilterCase( + this.m_gradientTex, [1.5, 2.8], [-1.0, -2.7], + [-0.5, this.m_numLayers + 0.5] + ) + ); + this.m_cases.push( + new es3fTextureFilteringTests. + Texture2DArrayFilteringCase.FilterCase( + this.m_gridTex, [0.2, 0.175], [-2.0, -3.7], + [-0.5, this.m_numLayers + 0.5] + ) + ); + this.m_cases.push( + new es3fTextureFilteringTests. + Texture2DArrayFilteringCase.FilterCase( + this.m_gridTex, [-0.8, -2.3], [0.2, -0.1], + [this.m_numLayers + 0.5, -0.5] + ) + ); + + // Level rounding - only in single-sample configs as + // multisample configs may produce smooth transition at the middle. + if (gl.getParameter(gl.SAMPLES) == 0) + this.m_cases.push( + new es3fTextureFilteringTests. + Texture2DArrayFilteringCase.FilterCase( + this.m_gradientTex, [-2.0, -1.5], [-0.1, 0.9], + [1.50001, 1.49999] + ) + ); + + this.m_caseNdx = 0; + } + catch (e) { + // Clean up to save memory. + this.deinit(); + throw e; + } + }; + + /** + * deinit + */ + es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype.deinit = + function() { + if (this.m_gradientTex) + gl.deleteTexture(this.m_gradientTex.getGLTexture()); + if (this.m_gridTex) + gl.deleteTexture(this.m_gridTex.getGLTexture()); + + this.m_gradientTex = null; + this.m_gridTex = null; + }; + + /** + * iterate + * @return {tcuTestCase.IterateResult} + */ + es3fTextureFilteringTests.Texture2DArrayFilteringCase.prototype.iterate = + function() { + /** @type {glsTextureTestUtil.RandomViewport} */ + var viewport = new glsTextureTestUtil.RandomViewport( + gl.canvas, TEX3D_VIEWPORT_WIDTH, + TEX3D_VIEWPORT_HEIGHT, deMath.binaryOp( + deString.deStringHash(this.fullName()), + deMath.deMathHash(this.m_caseNdx), + deMath.BinaryOp.XOR + ) + ); + + /** @type {es3fTextureFilteringTests.Texture2DArrayFilteringCase. + * FilterCase} */ var curCase = this.m_cases[this.m_caseNdx]; + + /** @type {tcuTexture.TextureFormat} */ + var texFmt = curCase.texture.getRefTexture().getFormat(); + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt); + + bufferedLogToConsole('Test' + this.m_caseNdx); + + /** @type {glsTextureTestUtil.ReferenceParams} */ + var refParams = new glsTextureTestUtil.ReferenceParams( + glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY + ); + + /** @type {tcuSurface.Surface} */ + var rendered = new tcuSurface.Surface(viewport.width, viewport.height); + + if (viewport.width < TEX3D_MIN_VIEWPORT_WIDTH || + viewport.height < TEX3D_MIN_VIEWPORT_HEIGHT) + throw new Error('Too small render target'); + + // Setup params for reference. + refParams.sampler = gluTextureUtil.mapGLSampler( + this.m_wrapS, this.m_wrapT, this.m_wrapT, + this.m_minFilter, this.m_magFilter + ); + refParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt); + refParams.lodMode = glsTextureTestUtil.lodMode.EXACT; + refParams.colorBias = fmtInfo.lookupBias; + refParams.colorScale = fmtInfo.lookupScale; + + // Compute texture coordinates. + bufferedLogToConsole( + 'Approximate lod per axis = ' + curCase.lod + + ', offset = ' + curCase.offset + ); + + /** @type {number} */ var lodX = curCase.lod[0]; + /** @type {number} */ var lodY = curCase.lod[1]; + /** @type {number} */ var oX = curCase.offset[0]; + /** @type {number} */ var oY = curCase.offset[1]; + /** @type {number} */ var sX = Math.pow(2, lodX) * viewport.width / + this.m_gradientTex.getRefTexture().getWidth(); + /** @type {number} */ var sY = Math.pow(2, lodY) * viewport.height / + this.m_gradientTex.getRefTexture().getHeight(); + /** @type {number} */ var l0 = curCase.layerRange[0]; + /** @type {number} */ var l1 = curCase.layerRange[1]; + + /** @type {Array<number>}*/ + var texCoord = [ + oX, oY, l0, + oX, oY + sY, l0 * 0.5 + l1 * 0.5, + oX + sX, oY, l0 * 0.5 + l1 * 0.5, + oX + sX, oY + sY, l1 + ]; + + gl.bindTexture(gl.TEXTURE_2D_ARRAY, curCase.texture.getGLTexture()); + gl.texParameteri( + gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, this.m_minFilter + ); + gl.texParameteri( + gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, this.m_magFilter + ); + gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, this.m_wrapS); + gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, this.m_wrapT); + + gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); + this.m_renderer.renderQuad( + 0, texCoord, + refParams + ); + rendered.readViewport( + gl, [viewport.x, viewport.y, viewport.width, viewport.height] + ); + + /** @type {boolean} */ + var isNearestOnly = this.m_minFilter == gl.NEAREST && + this.m_magFilter == gl.NEAREST; + /** @type {tcuPixelFormat.PixelFormat} */ + var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl); + //(iVec4) + var colorBits = deMath.max( + deMath.addScalar( + glsTextureTestUtil.getBitsVec(pixelFormat), + // 1 inaccurate bit if nearest only, 2 otherwise + -1 * (isNearestOnly ? 1 : 2) + ), + [0, 0, 0, 0] + ); + /** @type {tcuTexLookupVerifier.LodPrecision} */ + var lodPrecision = new tcuTexLookupVerifier.LodPrecision(); + /** @type {tcuTexLookupVerifier.LookupPrecision} */ + var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision(); + + lodPrecision.derivateBits = 18; + lodPrecision.lodBits = 6; + lookupPrecision.colorThreshold = deMath.divide( + tcuTexLookupVerifier.computeFixedPointThreshold(colorBits), + refParams.colorScale + ); + lookupPrecision.coordBits = [20, 20, 20]; + lookupPrecision.uvwBits = [7, 7, 0]; + lookupPrecision.colorMask = + glsTextureTestUtil.getCompareMask(pixelFormat); + + var isHighQuality = glsTextureTestUtil.verifyTexture2DArrayResult( + rendered.getAccess(), curCase.texture.getRefTexture().getView(), + texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat); + + if (!isHighQuality) { + // Evaluate against lower precision requirements. + lodPrecision.lodBits = 3; + lookupPrecision.uvwBits = [3, 3, 0]; + + bufferedLogToConsole( + 'Warning: Verification against high ' + + 'precision requirements failed, ' + + 'trying with lower requirements.' + ); + + var isOk = glsTextureTestUtil.verifyTexture2DArrayResult( + rendered.getAccess(), curCase.texture.getRefTexture().getView(), + texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat + ); + + if (!isOk) { + bufferedLogToConsole( + 'ERROR: Verification against low precision requirements ' + + 'failed, failing test case.' + ); + testFailedOptions('Image verification failed', false); + //In JS version, one mistake and you're out + return tcuTestCase.IterateResult.STOP; + } else + checkMessage( + false, + 'Low-quality filtering result in iteration no. ' + + this.m_caseNdx + ); + } + + this.m_caseNdx += 1; + if (this.m_caseNdx < this.m_cases.length) + return tcuTestCase.IterateResult.CONTINUE; + + testPassed('Verified'); + return tcuTestCase.IterateResult.STOP; + }; + + // 3D filtering + + /** + * @constructor + * @extends {tcuTestCase.DeqpTest} + * @param {string} name + * @param {string} desc + * @param {number} minFilter + * @param {number} magFilter + * @param {number} wrapS + * @param {number} wrapT + * @param {number} wrapR + * @param {number} internalFormat + * @param {number} width + * @param {number} height + * @param {number} depth + */ + es3fTextureFilteringTests.Texture3DFilteringCase = function( + name, desc, minFilter, magFilter, wrapS, wrapT, wrapR, internalFormat, + width, height, depth + ) { + tcuTestCase.DeqpTest.call(this, name, desc); + this.m_minFilter = minFilter; + this.m_magFilter = magFilter; + this.m_wrapS = wrapS; + this.m_wrapT = wrapT; + this.m_wrapR = wrapR; + this.m_internalFormat = internalFormat; + this.m_width = width; + this.m_height = height; + this.m_depth = depth; + this.m_gradientTex = null; + this.m_gridTex = null; + /** @type {glsTextureTestUtil.TextureRenderer} */ + this.m_renderer = new glsTextureTestUtil.TextureRenderer( + es3fTextureFilteringTests.version, + gluShaderUtil.precision.PRECISION_HIGHP + ); + this.m_caseNdx = 0; + this.m_cases = []; + }; + + es3fTextureFilteringTests.Texture3DFilteringCase.prototype = + Object.create(tcuTestCase.DeqpTest.prototype); + + es3fTextureFilteringTests.Texture3DFilteringCase.prototype.constructor = + es3fTextureFilteringTests.Texture3DFilteringCase; + + /** + * @constructor + * @param {gluTexture.Texture3D} tex_ + * @param {Array<number>} lod_ + * @param {Array<number>} offset_ + */ + es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase = function( + tex_, lod_, offset_ + ) { + this.texture = tex_; + this.lod = lod_; + this.offset = offset_; + }; + + /** + * init + */ + es3fTextureFilteringTests.Texture3DFilteringCase.prototype.init = function( + ) { + try { + /** @type {tcuTexture.TextureFormat} */ + var texFmt = + gluTextureUtil.mapGLInternalFormat(this.m_internalFormat); + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt); + var cScale = deMath.subtract( + fmtInfo.valueMax, fmtInfo.valueMin + ); + var cBias = fmtInfo.valueMin; + var numLevels = deMath.logToFloor( + Math.max(Math.max(this.m_width, this.m_height), this.m_depth) + ) + 1; + + // Create textures. + this.m_gradientTex = gluTexture.texture3DFromInternalFormat( + gl, this.m_internalFormat, + this.m_width, this.m_height, this.m_depth + ); + + this.m_gridTex = gluTexture.texture3DFromInternalFormat( + gl, this.m_internalFormat, + this.m_width, this.m_height, this.m_depth + ); + + // Fill first gradient texture. + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + var gMin = deMath.add( + deMath.multiply([0.0, 0.0, 0.0, 1.0], cScale), cBias + ); + + var gMax = deMath.add( + deMath.multiply([1.0, 1.0, 1.0, 0.0], cScale), cBias + ); + + this.m_gradientTex.getRefTexture().allocLevel(levelNdx); + tcuTextureUtil.fillWithComponentGradients( + this.m_gradientTex.getRefTexture().getLevel(levelNdx), + gMin, gMax + ); + } + + // Fill second with grid texture. + for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { + /** @type {number} */ var step = 0x00ffffff / numLevels; + /** @type {number} */ var rgb = step * levelNdx; + /** @type {number} */ var colorA = deMath.binaryOp( + 0xff000000, rgb, deMath.BinaryOp.OR + ); + /** @type {number} */ var colorB = deMath.binaryOp( + 0xff000000, deMath.binaryNot(rgb), deMath.BinaryOp.OR + ); + + this.m_gridTex.getRefTexture().allocLevel(levelNdx); + tcuTextureUtil.fillWithGrid( + this.m_gridTex.getRefTexture().getLevel(levelNdx), 4, + deMath.add( + deMath.multiply( + tcuRGBA.newRGBAFromValue(colorA).toVec(), + cScale + ), + cBias + ), + deMath.add( + deMath.multiply( + tcuRGBA.newRGBAFromValue(colorB).toVec(), + cScale + ), + cBias + ) + ); + } + + // Upload. + this.m_gradientTex.upload(); + this.m_gridTex.upload(); + + // Test cases + this.m_cases.push( + new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase( + this.m_gradientTex, [1.5, 2.8, 1.0], [-1.0, -2.7, -2.275] + ) + ); + this.m_cases.push( + new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase( + this.m_gradientTex, [-2.0, -1.5, -1.8], [-0.1, 0.9, -0.25] + ) + ); + this.m_cases.push( + new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase( + this.m_gridTex, [0.2, 0.175, 0.3], [-2.0, -3.7, -1.825] + ) + ); + this.m_cases.push( + new es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase( + this.m_gridTex, [-0.8, -2.3, -2.5], [0.2, -0.1, 1.325] + ) + ); + + this.m_caseNdx = 0; + } + catch (e) { + // Clean up to save memory. + this.deinit(); + throw e; + } + }; + + /** + * deinit + */ + es3fTextureFilteringTests.Texture3DFilteringCase.prototype.deinit = + function() { + if (this.m_gradientTex) + gl.deleteTexture(this.m_gradientTex.getGLTexture()); + if (this.m_gridTex) + gl.deleteTexture(this.m_gridTex.getGLTexture()); + + this.m_gradientTex = null; + this.m_gridTex = null; + }; + + /** + * @return {tcuTestCase.IterateResult} + */ + es3fTextureFilteringTests.Texture3DFilteringCase.prototype.iterate = + function() { + /** @type {glsTextureTestUtil.RandomViewport} */ + var viewport = new glsTextureTestUtil.RandomViewport( + gl.canvas, TEX3D_VIEWPORT_WIDTH, + TEX3D_VIEWPORT_HEIGHT, deMath.binaryOp( + deString.deStringHash(this.fullName()), + deMath.deMathHash(this.m_caseNdx), + deMath.BinaryOp.XOR + ) + ); + + /** @type {es3fTextureFilteringTests.Texture3DFilteringCase.FilterCase} + */ var curCase = this.m_cases[this.m_caseNdx]; + + /** @type {tcuTexture.TextureFormat} */ + var texFmt = curCase.texture.getRefTexture().getFormat(); + /** @type {tcuTextureUtil.TextureFormatInfo} */ + var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt); + + bufferedLogToConsole('Test' + this.m_caseNdx); + /** @type {glsTextureTestUtil.ReferenceParams} */ + var refParams = new glsTextureTestUtil.ReferenceParams( + glsTextureTestUtil.textureType.TEXTURETYPE_3D + ); + + /** @type {tcuSurface.Surface} */ + var rendered = new tcuSurface.Surface(viewport.width, viewport.height); + /** @type {Array<number>}*/ + var texCoord = []; + + if (viewport.width < TEX3D_MIN_VIEWPORT_WIDTH || + viewport.height < TEX3D_MIN_VIEWPORT_HEIGHT) + throw new Error('Too small render target'); + + // Setup params for reference. + refParams.sampler = gluTextureUtil.mapGLSampler( + this.m_wrapS, this.m_wrapT, this.m_wrapR, + this.m_minFilter, this.m_magFilter + ); + + // Setup params for reference. + refParams.samplerType = glsTextureTestUtil.getSamplerType(texFmt); + refParams.lodMode = glsTextureTestUtil.lodMode.EXACT; + refParams.colorBias = fmtInfo.lookupBias; + refParams.colorScale = fmtInfo.lookupScale; + + // Compute texture coordinates. + bufferedLogToConsole('Approximate lod per axis = ' + curCase.lod + + ', offset = ' + curCase.offset); + + /** @type {number} */ var lodX = curCase.lod[0]; + /** @type {number} */ var lodY = curCase.lod[1]; + /** @type {number} */ var lodZ = curCase.lod[2]; + /** @type {number} */ var oX = curCase.offset[0]; + /** @type {number} */ var oY = curCase.offset[1]; + /** @type {number} */ var oZ = curCase.offset[2]; + /** @type {number} */ var sX = Math.pow(2, lodX) * viewport.width / + this.m_gradientTex.getRefTexture().getWidth(); + /** @type {number} */ var sY = Math.pow(2, lodY) * viewport.height / + this.m_gradientTex.getRefTexture().getHeight(); + /** @type {number} */ var sZ = Math.pow(2, lodZ) * + Math.max(viewport.width, viewport.height) / + this.m_gradientTex.getRefTexture().getDepth(); + + texCoord[0] = oX; texCoord[1] = oY; texCoord[2] = oZ; + texCoord[3] = oX; texCoord[4] = oY + sY; texCoord[5] = oZ + sZ * 0.5; + texCoord[6] = oX + sX; texCoord[7] = oY; texCoord[8] = oZ + sZ * 0.5; + texCoord[9] = oX + sX; texCoord[10] = oY + sY; texCoord[11] = oZ + sZ; + + gl.bindTexture(gl.TEXTURE_3D, curCase.texture.getGLTexture()); + gl.texParameteri( + gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, this.m_minFilter + ); + gl.texParameteri( + gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, this.m_magFilter + ); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, this.m_wrapS); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, this.m_wrapT); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, this.m_wrapR); + + gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); + this.m_renderer.renderQuad(0, texCoord, refParams); + rendered.readViewport( + gl, [viewport.x, viewport.y, viewport.width, viewport.height] + ); + + var isNearestOnly = this.m_minFilter == gl.NEAREST && + this.m_magFilter == gl.NEAREST; + /** @type {tcuPixelFormat.PixelFormat} */ + var pixelFormat = tcuPixelFormat.PixelFormatFromContext(gl); + //(iVec4) + var colorBits = deMath.max( + deMath.addScalar( + glsTextureTestUtil.getBitsVec(pixelFormat), + // 1 inaccurate bit if nearest only, 2 otherwise + -1 * (isNearestOnly ? 1 : 2) + ), + [0, 0, 0, 0] + ); + /** @type {tcuTexLookupVerifier.LodPrecision} */ + var lodPrecision = new tcuTexLookupVerifier.LodPrecision(); + /** @type {tcuTexLookupVerifier.LookupPrecision} */ + var lookupPrecision = new tcuTexLookupVerifier.LookupPrecision(); + + lodPrecision.derivateBits = 18; + lodPrecision.lodBits = 6; + lookupPrecision.colorThreshold = deMath.divide( + tcuTexLookupVerifier.computeFixedPointThreshold(colorBits), + refParams.colorScale + ); + lookupPrecision.coordBits = [20, 20, 20]; + lookupPrecision.uvwBits = [7, 7, 7]; + lookupPrecision.colorMask = + glsTextureTestUtil.getCompareMask(pixelFormat); + + var isHighQuality = glsTextureTestUtil.verifyTexture3DResult( + rendered.getAccess(), curCase.texture.getRefTexture(), + texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat + ); + + if (!isHighQuality) { + // Evaluate against lower precision requirements. + lodPrecision.lodBits = 4; + lookupPrecision.uvwBits = [4, 4, 4]; + + bufferedLogToConsole( + 'Warning: Verification against high precision ' + + 'requirements failed, trying with lower requirements.' + ); + + var isOk = glsTextureTestUtil.verifyTexture3DResult( + rendered.getAccess(), curCase.texture.getRefTexture(), + texCoord, refParams, lookupPrecision, lodPrecision, pixelFormat + ); + + if (!isOk) { + bufferedLogToConsole('ERROR: Verification against low ' + + 'precision requirements failed, failing test case.' + ); + testFailedOptions('Image verification failed', false); + //In JS version, one mistake and you're out + return tcuTestCase.IterateResult.STOP; + } else + checkMessage( + false, + 'Low-quality filtering result in iteration no. ' + + this.m_caseNdx + ); + } + + this.m_caseNdx += 1; + if (this.m_caseNdx < this.m_cases.length) + return tcuTestCase.IterateResult.CONTINUE; + + testPassed('Verified'); + return tcuTestCase.IterateResult.STOP; + }; + + /** @typedef {{name: string, mode: number}} */ + es3fTextureFilteringTests.WrapMode; + + /** @typedef {{name: string, mode: number}} */ + es3fTextureFilteringTests.MinFilterMode; + + /** @typedef {{name: string, mode: number}} */ + es3fTextureFilteringTests.MagFilterModes; + + /** @typedef {{width: number, height: number}} */ + es3fTextureFilteringTests.Sizes2D; + + /** @typedef {{width: number, height: number}} */ + es3fTextureFilteringTests.SizesCube; + + /** @typedef {{width: number, height: number, numLayers: number}} */ + es3fTextureFilteringTests.Sizes2DArray; + + /** @typedef {{width: number, height: number, depth: number}} */ + es3fTextureFilteringTests.Sizes3D; + + /** @typedef {{name: string, format: number}} */ + es3fTextureFilteringTests.FilterableFormatsByType; + + /** + * init + */ + es3fTextureFilteringTests.TextureFilteringTests.prototype.init = + function() { + /** @type {Array<es3fTextureFilteringTests.WrapMode>} */ + var wrapModes = [{ + name: 'clamp', mode: gl.CLAMP_TO_EDGE + }, { + name: 'repeat', mode: gl.REPEAT + }, { + name: 'mirror', mode: gl.MIRRORED_REPEAT + } + ]; + + /** @type {Array<es3fTextureFilteringTests.MinFilterMode>} */ + var minFilterModes = [{ + name: 'nearest', mode: gl.NEAREST + }, { + name: 'linear', mode: gl.LINEAR + }, { + name: 'nearest_mipmap_nearest', mode: gl.NEAREST_MIPMAP_NEAREST + }, { + name: 'linear_mipmap_nearest', mode: gl.LINEAR_MIPMAP_NEAREST + }, { + name: 'nearest_mipmap_linear', mode: gl.NEAREST_MIPMAP_LINEAR + }, { + name: 'linear_mipmap_linear', mode: gl.LINEAR_MIPMAP_LINEAR + } + ]; + + /** @type {Array<es3fTextureFilteringTests.MagFilterModes>} */ + var magFilterModes = [{ + name: 'nearest', mode: gl.NEAREST + }, { + name: 'linear', mode: gl.LINEAR + } + ]; + + /** @type {Array<es3fTextureFilteringTests.Sizes2D>} */ + var sizes2D = [{ + width: 4, height: 8 + }, { + width: 32, height: 64 + }, { + width: 128, height: 128 + }, { + width: 3, height: 7 + }, { + width: 31, height: 55 + }, { + width: 127, height: 99 + } + ]; + + /** @type {Array<es3fTextureFilteringTests.SizesCube>} */ + var sizesCube = [{ + width: 8, height: 8 + }, { + width: 64, height: 64 + }, { + width: 128, height: 128 + }, { + width: 7, height: 7 + }, { + width: 63, height: 63 + } + ]; + + /** @type {Array<es3fTextureFilteringTests.Sizes2DArray>} */ + var sizes2DArray = [{ + width: 4, height: 8, numLayers: 8 + }, { + width: 32, height: 64, numLayers: 16 + }, { + width: 128, height: 32, numLayers: 64 + }, { + width: 3, height: 7, numLayers: 5 + }, { + width: 63, height: 63, numLayers: 63 + } + ]; + + /** @type {Array<es3fTextureFilteringTests.Sizes3D>} */ + var sizes3D = [{ + width: 4, height: 8, depth: 8 + }, { + width: 32, height: 64, depth: 16 + }, { + width: 128, height: 32, depth: 64 + }, { + width: 3, height: 7, depth: 5 + }, { + width: 63, height: 63, depth: 63 + } + ]; + + /** @type {Array<es3fTextureFilteringTests.FilterableFormatsByType>} */ + var filterableFormatsByType = [{ + name: 'rgba16f', format: gl.RGBA16F + }, { + name: 'r11f_g11f_b10f', format: gl.R11F_G11F_B10F + }, { + name: 'rgb9_e5', format: gl.RGB9_E5 + }, { + name: 'rgba8', format: gl.RGBA8 + }, { + name: 'rgba8_snorm', format: gl.RGBA8_SNORM + }, { + name: 'rgb565', format: gl.RGB565 + }, { + name: 'rgba4', format: gl.RGBA4 + }, { + name: 'rgb5_a1', format: gl.RGB5_A1 + }, { + name: 'srgb8_alpha8', format: gl.SRGB8_ALPHA8 + }, { + name: 'rgb10_a2', format: gl.RGB10_A2 + } + ]; + + // 2D texture filtering. + + // Formats. + /** @type {tcuTestCase.DeqpTest} */ + var formatsGroup; + for (var fmtNdx = 0; + fmtNdx < filterableFormatsByType.length; + fmtNdx++) { + formatsGroup = new tcuTestCase.DeqpTest( + '2d_formats', '2D Texture Formats'); + this.addChild(formatsGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + /** @type {number} */ + var minFilter = minFilterModes[filterNdx].mode; + /** @type {string} */ + var filterName = minFilterModes[filterNdx].name; + /** @type {number} */ + var format = filterableFormatsByType[fmtNdx].format; + /** @type {string} */ + var formatName = filterableFormatsByType[fmtNdx].name; + var isMipmap = minFilter != gl.NEAREST && + minFilter != gl.LINEAR; + /** @type {number} */ + var magFilter = isMipmap ? gl.LINEAR : minFilter; + /** @type {string} */ + var name = formatName + '_' + filterName; + /** @type {number} */ + var wrapS = gl.REPEAT; + /** @type {number} */ + var wrapT = gl.REPEAT; + /** @type {number} */ var width = 64; + /** @type {number} */ var height = 64; + + formatsGroup.addChild( + new es3fTextureFilteringTests.Texture2DFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + format, width, height + ) + ); + } + } + + // Sizes. + /** @type {tcuTestCase.DeqpTest} */ + var sizesGroup; + for (var sizeNdx = 0; sizeNdx < sizes2D.length; sizeNdx++) { + sizesGroup = new tcuTestCase.DeqpTest( + '2d_sizes', '2D Texture Sizes'); + this.addChild(sizesGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + minFilter = minFilterModes[filterNdx].mode; + filterName = minFilterModes[filterNdx].name; + format = gl.RGBA8; + isMipmap = minFilter != gl.NEAREST && + minFilter != gl.LINEAR; + magFilter = isMipmap ? gl.LINEAR : minFilter; + wrapS = gl.REPEAT; + wrapT = gl.REPEAT; + width = sizes2D[sizeNdx].width; + height = sizes2D[sizeNdx].height; + name = '' + width + 'x' + height + '_' + filterName; + + sizesGroup.addChild( + new es3fTextureFilteringTests.Texture2DFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + format, width, height + ) + ); + } + } + + // Wrap modes. + /** @type {tcuTestCase.DeqpTest} */ + var combinationsGroup; + for (var minFilterNdx = 0; + minFilterNdx < minFilterModes.length; + minFilterNdx++) { + combinationsGroup = new tcuTestCase.DeqpTest( + '2d_combinations', '2D Filter and wrap mode combinations'); + this.addChild(combinationsGroup); + for (var magFilterNdx = 0; + magFilterNdx < magFilterModes.length; + magFilterNdx++) { + for (var wrapSNdx = 0; + wrapSNdx < wrapModes.length; + wrapSNdx++) { + for (var wrapTNdx = 0; + wrapTNdx < wrapModes.length; + wrapTNdx++) { + minFilter = minFilterModes[minFilterNdx].mode; + magFilter = magFilterModes[magFilterNdx].mode; + format = gl.RGBA8; + wrapS = wrapModes[wrapSNdx].mode; + wrapT = wrapModes[wrapTNdx].mode; + width = 63; + height = 57; + name = minFilterModes[minFilterNdx].name + '_' + + magFilterModes[magFilterNdx].name + '_' + + wrapModes[wrapSNdx].name + '_' + + wrapModes[wrapTNdx].name; + + combinationsGroup.addChild( + new + es3fTextureFilteringTests.Texture2DFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + format, width, height + ) + ); + } + } + } + } + + // Cube map texture filtering. + + // Formats. + for (var fmtNdx = 0; + fmtNdx < filterableFormatsByType.length; + fmtNdx++) { + formatsGroup = new tcuTestCase.DeqpTest( + 'cube_formats', 'Cube Texture Formats'); + this.addChild(formatsGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + minFilter = minFilterModes[filterNdx].mode; + filterName = minFilterModes[filterNdx].name; + format = filterableFormatsByType[fmtNdx].format; + formatName = filterableFormatsByType[fmtNdx].name; + isMipmap = minFilter != gl.NEAREST && + minFilter != gl.LINEAR; + magFilter = isMipmap ? gl.LINEAR : minFilter; + name = formatName + '_' + filterName; + wrapS = gl.REPEAT; + wrapT = gl.REPEAT; + width = 64; + height = 64; + + formatsGroup.addChild( + new es3fTextureFilteringTests.TextureCubeFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + false /* always sample exterior as well */, + format, width, height + ) + ); + } + } + + // Sizes. + for (var sizeNdx = 0; sizeNdx < sizesCube.length; sizeNdx++) { + sizesGroup = new tcuTestCase.DeqpTest( + 'cube_sizes', 'Cube Texture Sizes'); + this.addChild(sizesGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + minFilter = minFilterModes[filterNdx].mode; + filterName = minFilterModes[filterNdx].name; + var format = gl.RGBA8; + isMipmap = minFilter != gl.NEAREST && + minFilter != gl.LINEAR; + magFilter = isMipmap ? gl.LINEAR : minFilter; + wrapS = gl.REPEAT; + wrapT = gl.REPEAT; + width = sizesCube[sizeNdx].width; + height = sizesCube[sizeNdx].height; + name = '' + width + 'x' + height + '_' + filterName; + + sizesGroup.addChild( + new es3fTextureFilteringTests.TextureCubeFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + false, format, width, height + ) + ); + } + } + + // Filter/wrap mode combinations. + for (var minFilterNdx = 0; + minFilterNdx < minFilterModes.length; + minFilterNdx++) { + combinationsGroup = new tcuTestCase.DeqpTest( + 'cube_combinations', 'Cube Filter and wrap mode combinations' + ); + this.addChild(combinationsGroup); + for (var magFilterNdx = 0; + magFilterNdx < magFilterModes.length; + magFilterNdx++) { + for (var wrapSNdx = 0; + wrapSNdx < wrapModes.length; + wrapSNdx++) { + for (var wrapTNdx = 0; + wrapTNdx < wrapModes.length; + wrapTNdx++) { + minFilter = minFilterModes[minFilterNdx].mode; + magFilter = magFilterModes[magFilterNdx].mode; + format = gl.RGBA8; + wrapS = wrapModes[wrapSNdx].mode; + wrapT = wrapModes[wrapTNdx].mode; + width = 63; + height = 63; + name = minFilterModes[minFilterNdx].name + '_' + + magFilterModes[magFilterNdx].name + '_' + + wrapModes[wrapSNdx].name + '_' + + wrapModes[wrapTNdx].name; + + combinationsGroup.addChild( + new es3fTextureFilteringTests. + TextureCubeFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + false, format, width, height + ) + ); + } + } + } + } + + // Cases with no visible cube edges. + /** @type {tcuTestCase.DeqpTest} */ + var onlyFaceInteriorGroup = new tcuTestCase.DeqpTest( + 'cube_no_edges_visible', "Don't sample anywhere near a face's edges" + ); + this.addChild(onlyFaceInteriorGroup); + + for (var isLinearI = 0; isLinearI <= 1; isLinearI++) { + var isLinear = isLinearI != 0; + var filter = isLinear ? gl.LINEAR : gl.NEAREST; + + onlyFaceInteriorGroup.addChild( + new es3fTextureFilteringTests.TextureCubeFilteringCase( + isLinear ? 'linear' : 'nearest', '', + filter, filter, gl.REPEAT, gl.REPEAT, + true, gl.RGBA8, 63, 63 + ) + ); + } + + // Formats. + for (var fmtNdx = 0; + fmtNdx < filterableFormatsByType.length; + fmtNdx++) { + formatsGroup = new tcuTestCase.DeqpTest( + '2d_array_formats', '2D Array Texture Formats'); + this.addChild(formatsGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + minFilter = minFilterModes[filterNdx].mode; + filterName = minFilterModes[filterNdx].name; + format = filterableFormatsByType[fmtNdx].format; + var formatName = filterableFormatsByType[fmtNdx].name; + isMipmap = minFilter != gl.NEAREST && + minFilter != gl.LINEAR; + magFilter = isMipmap ? gl.LINEAR : minFilter; + name = formatName + '_' + filterName; + wrapS = gl.REPEAT; + wrapT = gl.REPEAT; + width = 128; + height = 128; + /** @type {number} */ var numLayers = 8; + + formatsGroup.addChild( + new es3fTextureFilteringTests.Texture2DArrayFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + format, width, height, numLayers + ) + ); + } + } + + // Sizes. + for (var sizeNdx = 0; sizeNdx < sizes2DArray.length; sizeNdx++) { + sizesGroup = new tcuTestCase.DeqpTest( + '2d_array_sizes', '2D Array Texture Sizes'); + this.addChild(sizesGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + minFilter = minFilterModes[filterNdx].mode; + filterName = minFilterModes[filterNdx].name; + format = gl.RGBA8; + isMipmap = minFilter != gl.NEAREST && + minFilter != gl.LINEAR; + magFilter = isMipmap ? gl.LINEAR : minFilter; + wrapS = gl.REPEAT; + wrapT = gl.REPEAT; + width = sizes2DArray[sizeNdx].width; + height = sizes2DArray[sizeNdx].height; + numLayers = sizes2DArray[sizeNdx].numLayers; + name = '' + width + 'x' + height + 'x' + + numLayers + '_' + filterName; + + sizesGroup.addChild( + new es3fTextureFilteringTests.Texture2DArrayFilteringCase( + name, '', minFilter, magFilter, wrapS, wrapT, + format, width, height, numLayers + ) + ); + } + } + + // Wrap modes. + for (var minFilterNdx = 0; + minFilterNdx < minFilterModes.length; + minFilterNdx++) { + combinationsGroup = new tcuTestCase.DeqpTest( + '2d_array_combinations', + '2D Array Filter and wrap mode combinations'); + this.addChild(combinationsGroup); + for (var magFilterNdx = 0; + magFilterNdx < magFilterModes.length; + magFilterNdx++) { + for (var wrapSNdx = 0; + wrapSNdx < wrapModes.length; + wrapSNdx++) { + for (var wrapTNdx = 0; + wrapTNdx < wrapModes.length; + wrapTNdx++) { + minFilter = minFilterModes[minFilterNdx].mode; + magFilter = magFilterModes[magFilterNdx].mode; + format = gl.RGBA8; + wrapS = wrapModes[wrapSNdx].mode; + wrapT = wrapModes[wrapTNdx].mode; + width = 123; + height = 107; + numLayers = 7; + name = minFilterModes[minFilterNdx].name + '_' + + magFilterModes[magFilterNdx].name + '_' + + wrapModes[wrapSNdx].name + '_' + + wrapModes[wrapTNdx].name; + + combinationsGroup.addChild( + new es3fTextureFilteringTests. + Texture2DArrayFilteringCase( + name, '', minFilter, magFilter, + wrapS, wrapT, format, + width, height, numLayers + ) + ); + } + } + } + } + + // 3D texture filtering. + + // Formats. + /** @type {number} */ var depth = 64; + for (var fmtNdx = 0; + fmtNdx < filterableFormatsByType.length; + fmtNdx++) { + formatsGroup = new tcuTestCase.DeqpTest( + '3d_formats', '3D Texture Formats'); + this.addChild(formatsGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + minFilter = minFilterModes[filterNdx].mode; + filterName = minFilterModes[filterNdx].name; + format = filterableFormatsByType[fmtNdx].format; + formatName = filterableFormatsByType[fmtNdx].name; + isMipmap = minFilter != gl.NEAREST && + minFilter != gl.LINEAR; + magFilter = isMipmap ? gl.LINEAR : minFilter; + name = formatName + '_' + filterName; + wrapS = gl.REPEAT; + wrapT = gl.REPEAT; + /** @type {number} */ var wrapR = gl.REPEAT; + width = 64; + height = 64; + depth = 64; + + formatsGroup.addChild( + new es3fTextureFilteringTests.Texture3DFilteringCase( + name, '', minFilter, magFilter, + wrapS, wrapT, wrapR, format, + width, height, depth + ) + ); + } + } + + // Sizes. + for (var sizeNdx = 0; sizeNdx < sizes3D.length; sizeNdx++) { + sizesGroup = new tcuTestCase.DeqpTest( + '3d_sizes', '3D Texture Sizes'); + this.addChild(sizesGroup); + for (var filterNdx = 0; + filterNdx < minFilterModes.length; + filterNdx++) { + minFilter = minFilterModes[filterNdx].mode; + filterName = minFilterModes[filterNdx].name; + format = gl.RGBA8; + isMipmap = + minFilter != gl.NEAREST && minFilter != gl.LINEAR; + magFilter = + isMipmap ? gl.LINEAR : minFilter; + wrapS = gl.REPEAT; + wrapT = gl.REPEAT; + wrapR = gl.REPEAT; + width = sizes3D[sizeNdx].width; + height = sizes3D[sizeNdx].height; + depth = sizes3D[sizeNdx].depth; + name = '' + width + 'x' + height + 'x' + depth + + '_' + filterName; + + sizesGroup.addChild( + new es3fTextureFilteringTests.Texture3DFilteringCase( + name, '', minFilter, magFilter, + wrapS, wrapT, wrapR, format, + width, height, depth + ) + ); + } + } + + // Wrap modes. + for (var minFilterNdx = 0; + minFilterNdx < minFilterModes.length; + minFilterNdx++) { + for (var magFilterNdx = 0; + magFilterNdx < magFilterModes.length; + magFilterNdx++) { + for (var wrapSNdx = 0; + wrapSNdx < wrapModes.length; + wrapSNdx++) { + combinationsGroup = new tcuTestCase.DeqpTest( + '3d_combinations', + '3D Filter and wrap mode combinations'); + this.addChild(combinationsGroup); + for (var wrapTNdx = 0; + wrapTNdx < wrapModes.length; + wrapTNdx++) { + for (var wrapRNdx = 0; + wrapRNdx < wrapModes.length; + wrapRNdx++) { + minFilter = minFilterModes[minFilterNdx].mode; + magFilter = magFilterModes[magFilterNdx].mode; + format = gl.RGBA8; + wrapS = wrapModes[wrapSNdx].mode; + wrapT = wrapModes[wrapTNdx].mode; + wrapR = wrapModes[wrapRNdx].mode; + width = 63; + height = 57; + depth = 67; + name = minFilterModes[minFilterNdx].name + '_' + + magFilterModes[magFilterNdx].name + '_' + + wrapModes[wrapSNdx].name + '_' + + wrapModes[wrapTNdx].name + '_' + + wrapModes[wrapRNdx].name; + + combinationsGroup.addChild( + new + es3fTextureFilteringTests. + Texture3DFilteringCase( + name, '', minFilter, magFilter, + wrapS, wrapT, wrapR, format, + width, height, depth + ) + ); + } + } + } + } + } + }; + + /** + * Create and execute the test cases + * @param {WebGL2RenderingContext} context + * @param {Array<number>=} range Test range + */ + es3fTextureFilteringTests.run = function(context, range) { + gl = context; + + const canvas = gl.canvas; + canvas.width = canvasWH; + canvas.height = canvasWH; + + //Set up Test Root parameters + var state = tcuTestCase.runner; + + state.setRoot(new es3fTextureFilteringTests.TextureFilteringTests()); + if (range) + state.setRange(range); + + //Set up name and description of this test series. + setCurrentTestName(state.testCases.fullName()); + description(state.testCases.getDescription()); + + try { + //Run test cases + tcuTestCase.runTestCases(); + } + catch (err) { + testFailedOptions('Failed to run tests', false); + tcuTestCase.runner.terminate(); + } + }; +}); |