summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fTextureFilteringTests.js2282
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();
+ }
+ };
+});