/*------------------------------------------------------------------------- * 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('modules.shared.glsTextureTestUtil'); goog.require('framework.common.tcuImageCompare'); goog.require('framework.common.tcuPixelFormat'); goog.require('framework.common.tcuRGBA'); goog.require('framework.common.tcuStringTemplate'); goog.require('framework.common.tcuSurface'); goog.require('framework.common.tcuTexLookupVerifier'); goog.require('framework.common.tcuTexCompareVerifier'); goog.require('framework.common.tcuTexture'); goog.require('framework.delibs.debase.deMath'); goog.require('framework.opengl.gluDrawUtil'); goog.require('framework.opengl.gluShaderUtil'); goog.require('framework.opengl.gluShaderProgram'); goog.require('framework.delibs.debase.deRandom'); goog.scope(function() { var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier; var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier; var glsTextureTestUtil = modules.shared.glsTextureTestUtil; var gluDrawUtil = framework.opengl.gluDrawUtil; var gluShaderProgram = framework.opengl.gluShaderProgram; var tcuTexture = framework.common.tcuTexture; var tcuSurface = framework.common.tcuSurface; var gluShaderUtil = framework.opengl.gluShaderUtil; var tcuStringTemplate = framework.common.tcuStringTemplate; var deMath = framework.delibs.debase.deMath; var tcuImageCompare = framework.common.tcuImageCompare; var tcuPixelFormat = framework.common.tcuPixelFormat; var tcuRGBA = framework.common.tcuRGBA; var deRandom = framework.delibs.debase.deRandom; var DE_ASSERT = function(x) { if (!x) throw new Error('Assert failed'); }; var MIN_SUBPIXEL_BITS = 4; /** * @enum */ glsTextureTestUtil.textureType = { TEXTURETYPE_2D: 0, TEXTURETYPE_CUBE: 1, TEXTURETYPE_2D_ARRAY: 2, TEXTURETYPE_3D: 3, TEXTURETYPE_CUBE_ARRAY: 4, TEXTURETYPE_1D: 5, TEXTURETYPE_1D_ARRAY: 6, TEXTURETYPE_BUFFER: 7 }; /** * @enum */ glsTextureTestUtil.samplerType = { SAMPLERTYPE_FLOAT: 0, SAMPLERTYPE_INT: 1, SAMPLERTYPE_UINT: 2, SAMPLERTYPE_SHADOW: 3, SAMPLERTYPE_FETCH_FLOAT: 4, SAMPLERTYPE_FETCH_INT: 5, SAMPLERTYPE_FETCH_UINT: 6 }; /** * @param {tcuTexture.TextureFormat} format * @return {glsTextureTestUtil.samplerType} */ glsTextureTestUtil.getSamplerType = function(format) { if (format == null) throw new Error('Missing format information'); switch (format.type) { case tcuTexture.ChannelType.SIGNED_INT8: case tcuTexture.ChannelType.SIGNED_INT16: case tcuTexture.ChannelType.SIGNED_INT32: return glsTextureTestUtil.samplerType.SAMPLERTYPE_INT; case tcuTexture.ChannelType.UNSIGNED_INT8: case tcuTexture.ChannelType.UNSIGNED_INT32: case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: return glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT; // Texture formats used in depth/stencil textures. case tcuTexture.ChannelType.UNSIGNED_INT16: case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS) ? glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT : glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT; default: return glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT; } }; /** * @constructor * @param {HTMLElement} canvas * @param {number} preferredWidth * @param {number} preferredHeight * @param {number=} seed */ glsTextureTestUtil.RandomViewport = function(canvas, preferredWidth, preferredHeight, seed) { this.width = Math.min(canvas.width, preferredWidth); this.height = Math.min(canvas.height, preferredHeight); if (typeof seed === 'undefined') seed = preferredWidth + preferredHeight; var rnd = new deRandom.Random(seed); this.x = rnd.getInt(0, canvas.width - this.width); this.y = rnd.getInt(0, canvas.height - this.height); }; /** * @constructor * @param {glsTextureTestUtil.textureType} texType */ glsTextureTestUtil.RenderParams = function(texType) { this.flags = { projected: false, use_bias: false, log_programs: false, log_uniforms: false }; this.texType = texType; this.w = [1, 1, 1, 1]; this.bias = 0; this.ref = 0; this.colorScale = [1, 1, 1, 1]; this.colorBias = [0, 0, 0, 0]; this.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT; }; /** * @enum */ glsTextureTestUtil.lodMode = { EXACT: 0, //!< Ideal lod computation. MIN_BOUND: 1, //!< Use estimation range minimum bound. MAX_BOUND: 2 //!< Use estimation range maximum bound. }; /** * @constructor * @extends {glsTextureTestUtil.RenderParams} * @param {glsTextureTestUtil.textureType} texType * @param {tcuTexture.Sampler=} sampler * @param {glsTextureTestUtil.lodMode=} lodMode_ */ glsTextureTestUtil.ReferenceParams = function(texType, sampler, lodMode_) { glsTextureTestUtil.RenderParams.call(this, texType); if (sampler) this.sampler = sampler; if (lodMode_) this.lodMode = lodMode_; else this.lodMode = glsTextureTestUtil.lodMode.EXACT; this.minLod = -1000; this.maxLod = 1000; this.baseLevel = 0; this.maxLevel = 1000; }; glsTextureTestUtil.ReferenceParams.prototype = Object.create(glsTextureTestUtil.RenderParams.prototype); /** Copy constructor */ glsTextureTestUtil.ReferenceParams.prototype.constructor = glsTextureTestUtil.ReferenceParams; /** * @param {Array} bottomLeft * @param {Array} topRight * @return {Array} */ glsTextureTestUtil.computeQuadTexCoord2D = function(bottomLeft, topRight) { var dst = []; dst.length = 4 * 2; dst[0] = bottomLeft[0]; dst[1] = bottomLeft[1]; dst[2] = bottomLeft[0]; dst[3] = topRight[1]; dst[4] = topRight[0]; dst[5] = bottomLeft[1]; dst[6] = topRight[0]; dst[7] = topRight[1]; return dst; }; /** * @param {tcuTexture.CubeFace} face * @return {Array} */ glsTextureTestUtil.computeQuadTexCoordCube = function(face) { var texCoordNegX = [ -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1 ]; var texCoordPosX = [ +1, 1, 1, +1, -1, 1, +1, 1, -1, +1, -1, -1 ]; var texCoordNegY = [ -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1 ]; var texCoordPosY = [ -1, +1, -1, -1, +1, 1, 1, +1, -1, 1, +1, 1 ]; var texCoordNegZ = [ 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1 ]; var texCoordPosZ = [ -1, 1, +1, -1, -1, +1, 1, 1, +1, 1, -1, +1 ]; switch (face) { case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: return texCoordNegX; case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: return texCoordPosX; case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: return texCoordNegY; case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: return texCoordPosY; case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: return texCoordNegZ; case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: return texCoordPosZ; } throw new Error('Unrecognized face ' + face); }; /** * @param {tcuTexture.CubeFace} face * @param {Array} bottomLeft * @param {Array} topRight * @return {Array} */ glsTextureTestUtil.computeQuadTexCoordCubeFace = function(face, bottomLeft, topRight) { var dst = []; /** @type {number} */ var sRow = 0; /** @type {number} */ var tRow = 0; /** @type {number} */ var mRow = 0; /** @type {number} */ var sSign = 1.0; /** @type {number} */ var tSign = 1.0; /** @type {number} */ var mSign = 1.0; switch (face) { case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0; tSign = -1.0; break; case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1; sSign = -1.0; tSign = -1.0; break; case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0; tSign = -1.0; break; case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2; break; case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0; sSign = -1.0; tSign = -1.0; break; case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1; tSign = -1.0; break; default: throw new Error('Invalid cube face specified.'); } dst[0 + mRow] = mSign; dst[3 + mRow] = mSign; dst[6 + mRow] = mSign; dst[9 + mRow] = mSign; dst[0 + sRow] = sSign * bottomLeft[0]; dst[3 + sRow] = sSign * bottomLeft[0]; dst[6 + sRow] = sSign * topRight[0]; dst[9 + sRow] = sSign * topRight[0]; dst[0 + tRow] = tSign * bottomLeft[1]; dst[3 + tRow] = tSign * topRight[1]; dst[6 + tRow] = tSign * bottomLeft[1]; dst[9 + tRow] = tSign * topRight[1]; return dst; }; /** * @param {number} layerNdx * @param {Array} bottomLeft * @param {Array} topRight * @return {Array} */ glsTextureTestUtil.computeQuadTexCoord2DArray = function(layerNdx, bottomLeft, topRight) { var dst = []; dst.length = 4 * 3; dst[0] = bottomLeft[0]; dst[1] = bottomLeft[1]; dst[2] = layerNdx; dst[3] = bottomLeft[0]; dst[4] = topRight[1]; dst[5] = layerNdx; dst[6] = topRight[0]; dst[7] = bottomLeft[1]; dst[8] = layerNdx; dst[9] = topRight[0]; dst[10] = topRight[1]; dst[11] = layerNdx; return dst; }; /** * @param {Array} a * @param {Array} b * @param {Array} c * @return {Array} a + (b - a) * c */ glsTextureTestUtil.selectCoords = function(a, b, c) { var x1 = deMath.subtract(b, a); var x2 = deMath.multiply(x1, c); var x3 = deMath.add(a, x2); return x3; }; /** * @param {Array} p0 * @param {Array} p1 * @param {Array} dirSwz * @return {Array} */ glsTextureTestUtil.computeQuadTexCoord3D = function(p0, p1, dirSwz) { var dst = []; dst.length = 4 * 3; var f0 = deMath.swizzle(([0, 0, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]); var f1 = deMath.swizzle(([0, 1, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]); var f2 = deMath.swizzle(([1, 0, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]); var f3 = deMath.swizzle(([1, 1, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]); var v0 = glsTextureTestUtil.selectCoords(p0, p1, f0); var v1 = glsTextureTestUtil.selectCoords(p0, p1, f1); var v2 = glsTextureTestUtil.selectCoords(p0, p1, f2); var v3 = glsTextureTestUtil.selectCoords(p0, p1, f3); dst[0] = v0[0]; dst[1] = v0[1]; dst[2] = v0[2]; dst[3] = v1[0]; dst[4] = v1[1]; dst[5] = v1[2]; dst[6] = v2[0]; dst[7] = v2[1]; dst[8] = v2[2]; dst[9] = v3[0]; dst[10] = v3[1]; dst[11] = v3[2]; return dst; }; /** * @enum */ glsTextureTestUtil.programType = { PROGRAM_2D_FLOAT: 0, PROGRAM_2D_INT: 1, PROGRAM_2D_UINT: 2, PROGRAM_2D_SHADOW: 3, PROGRAM_2D_FLOAT_BIAS: 4, PROGRAM_2D_INT_BIAS: 5, PROGRAM_2D_UINT_BIAS: 6, PROGRAM_2D_SHADOW_BIAS: 7, PROGRAM_1D_FLOAT: 8, PROGRAM_1D_INT: 9, PROGRAM_1D_UINT: 10, PROGRAM_1D_SHADOW: 11, PROGRAM_1D_FLOAT_BIAS: 12, PROGRAM_1D_INT_BIAS: 13, PROGRAM_1D_UINT_BIAS: 14, PROGRAM_1D_SHADOW_BIAS: 15, PROGRAM_CUBE_FLOAT: 16, PROGRAM_CUBE_INT: 17, PROGRAM_CUBE_UINT: 18, PROGRAM_CUBE_SHADOW: 19, PROGRAM_CUBE_FLOAT_BIAS: 20, PROGRAM_CUBE_INT_BIAS: 21, PROGRAM_CUBE_UINT_BIAS: 22, PROGRAM_CUBE_SHADOW_BIAS: 23, PROGRAM_1D_ARRAY_FLOAT: 24, PROGRAM_1D_ARRAY_INT: 25, PROGRAM_1D_ARRAY_UINT: 26, PROGRAM_1D_ARRAY_SHADOW: 27, PROGRAM_2D_ARRAY_FLOAT: 28, PROGRAM_2D_ARRAY_INT: 29, PROGRAM_2D_ARRAY_UINT: 30, PROGRAM_2D_ARRAY_SHADOW: 31, PROGRAM_3D_FLOAT: 32, PROGRAM_3D_INT: 33, PROGRAM_3D_UINT: 34, PROGRAM_3D_FLOAT_BIAS: 35, PROGRAM_3D_INT_BIAS: 36, PROGRAM_3D_UINT_BIAS: 37, PROGRAM_CUBE_ARRAY_FLOAT: 38, PROGRAM_CUBE_ARRAY_INT: 39, PROGRAM_CUBE_ARRAY_UINT: 40, PROGRAM_CUBE_ARRAY_SHADOW: 41, PROGRAM_BUFFER_FLOAT: 42, PROGRAM_BUFFER_INT: 43, PROGRAM_BUFFER_UINT: 44 }; /** * @constructor * @param {string} version GL version * @param {gluShaderUtil.precision} precision */ glsTextureTestUtil.ProgramLibrary = function(version, precision) { this.m_glslVersion = version; this.m_texCoordPrecision = precision; }; /** * @param {glsTextureTestUtil.programType} program * @return {gluShaderProgram.ShaderProgram} */ glsTextureTestUtil.ProgramLibrary.prototype.getProgram = function(program) { /* TODO: Implement */ // if (m_programs.find(program) != m_programs.end()) // return m_programs[program]; // Return from cache. var vertShaderTemplate = '${VTX_HEADER}' + '${VTX_IN} highp vec4 a_position;\n' + '${VTX_IN} ${PRECISION} ${TEXCOORD_TYPE} a_texCoord;\n' + '${VTX_OUT} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n' + '\n' + 'void main (void)\n' + ' {\n' + ' gl_Position = a_position;\n' + ' v_texCoord = a_texCoord;\n' + '}\n'; var fragShaderTemplate = '${FRAG_HEADER}' + '${FRAG_IN} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n' + 'uniform ${PRECISION} float u_bias;\n' + 'uniform ${PRECISION} float u_ref;\n' + 'uniform ${PRECISION} vec4 u_colorScale;\n' + 'uniform ${PRECISION} vec4 u_colorBias;\n' + 'uniform ${PRECISION} ${SAMPLER_TYPE} u_sampler;\n' + '\n' + 'void main (void)\n' + ' {\n' + ' ${FRAG_COLOR} = ${LOOKUP} * u_colorScale + u_colorBias;\n' + '}\n'; var params = []; var isCube = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT, glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS); var isArray = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW) || deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW); var is1D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS) || deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW) || deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT, glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT); var is2D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS) || deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW); var is3D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_3D_FLOAT, glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS); var isCubeArray = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW); var isBuffer = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT, glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT); if (this.m_glslVersion === '100 es') { params['FRAG_HEADER'] = ''; params['VTX_HEADER'] = ''; params['VTX_IN'] = 'attribute'; params['VTX_OUT'] = 'varying'; params['FRAG_IN'] = 'varying'; params['FRAG_COLOR'] = 'gl_FragColor'; } else if (this.m_glslVersion === '300 es' || this.m_glslVersion === '310 es' || this.m_glslVersion === '330 es') { var ext = null; // if (isCubeArray && glu::glslVersionIsES(m_glslVersion)) // ext = "gl.EXT_texture_cube_map_array"; // else if (isBuffer && glu::glslVersionIsES(m_glslVersion)) // ext = "gl.EXT_texture_buffer"; var extension = ''; if (ext) extension = '\n#extension ' + ext + ' : require'; params['FRAG_HEADER'] = '#version ' + this.m_glslVersion + extension + '\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n'; params['VTX_HEADER'] = '#version ' + this.m_glslVersion + '\n'; params['VTX_IN'] = 'in'; params['VTX_OUT'] = 'out'; params['FRAG_IN'] = 'in'; params['FRAG_COLOR'] = 'dEQP_FragColor'; } else throw new Error('Unsupported version: ' + this.m_glslVersion); params['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_texCoordPrecision); if (isCubeArray) params['TEXCOORD_TYPE'] = 'vec4'; else if (isCube || (is2D && isArray) || is3D) params['TEXCOORD_TYPE'] = 'vec3'; else if ((is1D && isArray) || is2D) params['TEXCOORD_TYPE'] = 'vec2'; else if (is1D) params['TEXCOORD_TYPE'] = 'float'; else DE_ASSERT(false); var sampler = null; var lookup = null; if (this.m_glslVersion === '300 es' || this.m_glslVersion === '310 es' || this.m_glslVersion === '330 es') { switch (program) { case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT: sampler = 'sampler2D'; lookup = 'texture(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_2D_INT: sampler = 'isampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_2D_UINT: sampler = 'usampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_2D_SHADOW: sampler = 'sampler2DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS: sampler = 'sampler2D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break; case glsTextureTestUtil.programType.PROGRAM_2D_INT_BIAS: sampler = 'isampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS: sampler = 'usampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_2D_SHADOW_BIAS: sampler = 'sampler2DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_1D_FLOAT: sampler = 'sampler1D'; lookup = 'texture(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_1D_INT: sampler = 'isampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_1D_UINT: sampler = 'usampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_1D_SHADOW: sampler = 'sampler1DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_1D_FLOAT_BIAS: sampler = 'sampler1D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break; case glsTextureTestUtil.programType.PROGRAM_1D_INT_BIAS: sampler = 'isampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS: sampler = 'usampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_1D_SHADOW_BIAS: sampler = 'sampler1DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT: sampler = 'samplerCube'; lookup = 'texture(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_INT: sampler = 'isamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_UINT: sampler = 'usamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW: sampler = 'samplerCubeShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS: sampler = 'samplerCube'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_INT_BIAS: sampler = 'isamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_UINT_BIAS: sampler = 'usamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS: sampler = 'samplerCubeShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT: sampler = 'sampler2DArray'; lookup = 'texture(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_INT: sampler = 'isampler2DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_UINT: sampler = 'usampler2DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW: sampler = 'sampler2DArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_3D_FLOAT: sampler = 'sampler3D'; lookup = 'texture(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_3D_INT: sampler = 'isampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_3D_UINT: sampler = ' usampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_3D_FLOAT_BIAS: sampler = 'sampler3D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break; case glsTextureTestUtil.programType.PROGRAM_3D_INT_BIAS: sampler = 'isampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS: sampler = ' usampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT: sampler = 'samplerCubeArray'; lookup = 'texture(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_INT: sampler = 'isamplerCubeArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_UINT: sampler = 'usamplerCubeArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW: sampler = 'samplerCubeArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT: sampler = 'sampler1DArray'; lookup = 'texture(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_INT: sampler = 'isampler1DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_UINT: sampler = 'usampler1DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW: sampler = 'sampler1DArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break; case glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT: sampler = 'samplerBuffer'; lookup = 'texelFetch(u_sampler, int(v_texCoord))'; break; case glsTextureTestUtil.programType.PROGRAM_BUFFER_INT: sampler = 'isamplerBuffer'; lookup = 'vec4(texelFetch(u_sampler, int(v_texCoord)))'; break; case glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT: sampler = 'usamplerBuffer'; lookup = 'vec4(texelFetch(u_sampler, int(v_texCoord)))'; break; default: DE_ASSERT(false); } } else if (this.m_glslVersion === '100 es') { sampler = isCube ? 'samplerCube' : 'sampler2D'; switch (program) { case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT: lookup = 'texture2D(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS: lookup = 'texture2D(u_sampler, v_texCoord, u_bias)'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT: lookup = 'textureCube(u_sampler, v_texCoord)'; break; case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS: lookup = 'textureCube(u_sampler, v_texCoord, u_bias)'; break; default: DE_ASSERT(false); } } else DE_ASSERT(!'Unsupported version'); params['SAMPLER_TYPE'] = sampler; params['LOOKUP'] = lookup; var vertSrc = tcuStringTemplate.specialize(vertShaderTemplate, params); var fragSrc = tcuStringTemplate.specialize(fragShaderTemplate, params); var progObj = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertSrc, fragSrc)); // if (!progObj.isOk()) { // // log << *progObj; // testFailedOptions("Failed to create shader", true); // } // try // { // m_programs[program] = progObj; // } // catch (...) // { // delete progObj; // throw; // } return progObj; }; // public: // glsTextureTestUtil.ProgramLibrary (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision); // ~glsTextureTestUtil.ProgramLibrary (void); // glu::ShaderProgram* getProgram (Program program); // void clear (void); // private: // glsTextureTestUtil.ProgramLibrary (const glsTextureTestUtil.ProgramLibrary& other); // glsTextureTestUtil.ProgramLibrary& operator= (const glsTextureTestUtil.ProgramLibrary& other); // const glu::RenderContext& m_context; // tcu::TestContext& m_testCtx; // glu::GLSLVersion m_glslVersion; // glu::Precision m_texCoordPrecision; // std::map m_programs; // }; /** * @constructor * @param {string} version GL version * @param {gluShaderUtil.precision} precision */ glsTextureTestUtil.TextureRenderer = function(version, precision) { this.m_programLibrary = new glsTextureTestUtil.ProgramLibrary(version, precision); }; /** * @param {tcuPixelFormat.PixelFormat} format * @return {Array} */ glsTextureTestUtil.getCompareMask = function(format) { return [ format.redBits > 0, format.greenBits > 0, format.blueBits > 0, format.alphaBits > 0 ]; }; /** * @param {tcuPixelFormat.PixelFormat} format * @return {Array} */ glsTextureTestUtil.getBitsVec = function(format) { return [ format.redBits, format.greenBits, format.blueBits, format.alphaBits ]; }; /** * @param {number} texUnit * @param {Array} texCoord * @param {glsTextureTestUtil.RenderParams} params */ glsTextureTestUtil.TextureRenderer.prototype.renderQuad = function(texUnit, texCoord, params) { var wCoord = params.flags.projected ? params.w : [1, 1, 1, 1]; var useBias = params.flags.use_bias; var logUniforms = params.flags.log_uniforms; // Render quad with texture. var position = [ -1 * wCoord[0], -1 * wCoord[0], 0, wCoord[0], -1 * wCoord[1], +1 * wCoord[1], 0, wCoord[1], +1 * wCoord[2], -1 * wCoord[2], 0, wCoord[2], +1 * wCoord[3], +1 * wCoord[3], 0, wCoord[3] ]; /** @const */ var indices = [0, 1, 2, 2, 1, 3]; /** @type {?glsTextureTestUtil.programType} */ var progSpec = null; var numComps = 0; if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_2D) { numComps = 2; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_UINT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_SHADOW; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_1D) { numComps = 1; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_UINT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_SHADOW; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_CUBE) { numComps = 3; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_UINT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_3D) { numComps = 3; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_UINT; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY) { DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias. numComps = 3; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_UINT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_CUBE_ARRAY) { DE_ASSERT(!useBias); numComps = 4; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_UINT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_1D_ARRAY) { DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias. numComps = 2; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_UINT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_BUFFER) { numComps = 1; switch (params.samplerType) { case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_INT; break; case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT; break; default: throw new Error('Unrecognized sampler type:' + params.samplerType); } } else throw new Error('Unrecognized texture type:' + params.texType); if (progSpec === null) throw new Error('Could not find program specification'); var program = this.m_programLibrary.getProgram(progSpec); // \todo [2012-09-26 pyry] Move to glsTextureTestUtil.ProgramLibrary and log unique programs only(?) /* TODO: Port logging if (params.flags.log_programs) log << *program; */ // Program and uniforms. var prog = program.getProgram(); gl.useProgram(prog); var loc = gl.getUniformLocation(prog, 'u_sampler'); gl.uniform1i(loc, texUnit); // if (logUniforms) // log << TestLog::Message << "u_sampler = " << texUnit << TestLog::EndMessage; if (useBias) { gl.uniform1f(gl.getUniformLocation(prog, 'u_bias'), params.bias); // if (logUniforms) // log << TestLog::Message << "u_bias = " << params.bias << TestLog::EndMessage; } if (params.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW) { gl.uniform1f(gl.getUniformLocation(prog, 'u_ref'), params.ref); // if (logUniforms) // log << TestLog::Message << "u_ref = " << params.ref << TestLog::EndMessage; } gl.uniform4fv(gl.getUniformLocation(prog, 'u_colorScale'), params.colorScale); gl.uniform4fv(gl.getUniformLocation(prog, 'u_colorBias'), params.colorBias); // if (logUniforms) // { // log << TestLog::Message << "u_colorScale = " << params.colorScale << TestLog::EndMessage; // log << TestLog::Message << "u_colorBias = " << params.colorBias << TestLog::EndMessage; // } var vertexArrays = []; var posLoc = gl.getAttribLocation(prog, 'a_position'); if (posLoc === -1) { testFailedOptions("no location found for attribute 'a_position'", true); } var texLoc = gl.getAttribLocation(prog, 'a_texCoord'); if (texLoc === -1) { testFailedOptions("no location found for attribute 'a_texCoord'", true); } vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, posLoc, 4, 4, position)); vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, texLoc, numComps, 4, texCoord)); gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices)); }; // public: // glsTextureTestUtil.TextureRenderer (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision); // ~glsTextureTestUtil.TextureRenderer (void); // void clear (void); //!< Frees allocated resources. Destructor will call clear() as well. // void renderQuad (int texUnit, const float* texCoord, TextureType texType); // void renderQuad (int texUnit, const float* texCoord, const glsTextureTestUtil.RenderParams& params); // private: // glsTextureTestUtil.TextureRenderer (const glsTextureTestUtil.TextureRenderer& other); // glsTextureTestUtil.TextureRenderer& operator= (const glsTextureTestUtil.TextureRenderer& other); // const glu::RenderContext& m_renderCtx; // tcu::TestContext& m_testCtx; // glsTextureTestUtil.ProgramLibrary m_programLibrary; // }; /** * @constructor * @param {tcuSurface.Surface} surface * @param {tcuPixelFormat.PixelFormat=} colorFmt * @param {number=} x * @param {number=} y * @param {number=} width * @param {number=} height */ glsTextureTestUtil.SurfaceAccess = function(surface, colorFmt, x, y, width, height) { this.m_surface = surface; this.colorMask = undefined; /*TODO*/ this.m_x = x || 0; this.m_y = y || 0; this.m_width = width || surface.getWidth(); this.m_height = height || surface.getHeight(); }; /** @return {number} */ glsTextureTestUtil.SurfaceAccess.prototype.getWidth = function() { return this.m_width; }; /** @return {number} */ glsTextureTestUtil.SurfaceAccess.prototype.getHeight = function() { return this.m_height; }; /** * @param {Array} color * @param {number} x * @param {number} y */ glsTextureTestUtil.SurfaceAccess.prototype.setPixel = function(color, x, y) { /* TODO: Apply color mask */ var c = color; for (var i = 0; i < c.length; i++) c[i] = deMath.clamp(Math.round(color[i] * 255), 0, 255); this.m_surface.setPixel(x, y, c); }; /** * @param {glsTextureTestUtil.lodMode} mode * @param {number} dudx * @param {number} dvdx * @param {number} dwdx * @param {number} dudy * @param {number} dvdy * @param {number} dwdy * @return {number} */ glsTextureTestUtil.computeLodFromDerivates3D = function(mode, dudx, dvdx, dwdx, dudy, dvdy, dwdy) { var p = 0; switch (mode) { case glsTextureTestUtil.lodMode.EXACT: p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx + dwdx * dwdx), Math.sqrt(dudy * dudy + dvdy * dvdy + dwdy * dwdy)); break; case glsTextureTestUtil.lodMode.MIN_BOUND: case glsTextureTestUtil.lodMode.MAX_BOUND: { var mu = Math.max(Math.abs(dudx), Math.abs(dudy)); var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy)); var mw = Math.max(Math.abs(dwdx), Math.abs(dwdy)); p = (mode == glsTextureTestUtil.lodMode.MIN_BOUND) ? Math.max(mu, mv, mw) : mu + mv + mw; break; } default: DE_ASSERT(false); } // Native dEQP uses 32-bit numbers. So here 64-bit floating numbers should be transformed into 32-bit ones to ensure the correctness of the result. return deMath.toFloat32(Math.log(p)) * deMath.INV_LOG_2_FLOAT32; }; /** * @param {glsTextureTestUtil.lodMode} mode * @param {Array} dstSize * @param {Array} srcSize * @param {Array} sq * @param {Array} tq * @param {Array=} rq * @return {number} */ glsTextureTestUtil.computeNonProjectedTriLod = function(mode, dstSize, srcSize, sq, tq, rq) { var dux = (sq[2] - sq[0]) * srcSize[0]; var duy = (sq[1] - sq[0]) * srcSize[0]; var dvx = (tq[2] - tq[0]) * srcSize[1]; var dvy = (tq[1] - tq[0]) * srcSize[1]; var dwx = 0; var dwy = 0; if (rq) { dwx = (rq[2] - rq[0]) * srcSize[2]; dwy = (rq[1] - rq[0]) * srcSize[2]; } var dx = dstSize[0]; var dy = dstSize[1]; return glsTextureTestUtil.computeLodFromDerivates3D(mode, dux / dx, dvx / dx, dwx / dx, duy / dy, dvy / dy, dwy / dy); }; /** * @param {Array} v * @param {number} x * @param {number} y * @return {number} */ glsTextureTestUtil.triangleInterpolate = function(v, x, y) { return v[0] + (v[2] - v[0]) * x + (v[1] - v[0]) * y; }; /** * @param {Array} s * @param {Array} w * @param {number} wx * @param {number} width * @param {number} ny * @return {number} */ glsTextureTestUtil.triDerivateX = function(s, w, wx, width, ny) { var d = w[1] * w[2] * (width * (ny - 1) + wx) - w[0] * (w[2] * width * ny + w[1] * wx); return (w[0] * w[1] * w[2] * width * (w[1] * (s[0] - s[2]) * (ny - 1) + ny * (w[2] * (s[1] - s[0]) + w[0] * (s[2] - s[1])))) / (d * d); }; /** * @param {Array} s * @param {Array} w * @param {number} wy * @param {number} height * @param {number} nx * @return {number} */ glsTextureTestUtil.triDerivateY = function(s, w, wy, height, nx) { var d = w[1] * w[2] * (height * (nx - 1) + wy) - w[0] * (w[1] * height * nx + w[2] * wy); return (w[0] * w[1] * w[2] * height * (w[2] * (s[0] - s[1]) * (nx - 1) + nx * (w[0] * (s[1] - s[2]) + w[1] * (s[2] - s[0])))) / (d * d); }; /** * @param {(tcuTexture.Texture2DView|tcuTexture.Texture2DArrayView|tcuTexture.TextureCubeView)} src * @param {glsTextureTestUtil.ReferenceParams} params * @param {Array} texCoord Texture coordinates * @param {number} lod * @return {Array} sample */ glsTextureTestUtil.execSample = function(src, params, texCoord, lod) { if (params.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW) return [src.sampleCompare(params.sampler, params.ref, texCoord, lod), 0, 0, 1]; else return src.sample(params.sampler, texCoord, lod); }; /** * @param {Array} pixel * @param {Array} scale * @param {Array} bias */ glsTextureTestUtil.applyScaleAndBias = function(pixel, scale, bias) { pixel[0] = pixel[0] * scale[0] + bias[0]; pixel[1] = pixel[1] * scale[1] + bias[1]; pixel[2] = pixel[2] * scale[2] + bias[2]; pixel[3] = pixel[3] * scale[3] + bias[3]; }; /** * @param {Array} pixel * @param {Array} scale * @param {Array} bias */ glsTextureTestUtil.deapplyScaleAndBias = function(pixel, scale, bias) { pixel[0] = (pixel[0] - bias[0]) / scale[0]; pixel[1] = (pixel[1] - bias[1]) / scale[1]; pixel[2] = (pixel[2] - bias[2]) / scale[2]; pixel[3] = (pixel[3] - bias[3]) / scale[3]; }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.Texture2DView} src * @param {Array} sq * @param {Array} tq * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTextureProjected2D = function(dst, src, sq, tq, params) { /** @type {number} */ var lodBias = params.flags.use_bias ? params.bias : 0.0; /** @type {number} */ var dstW = dst.getWidth(); /** @type {number} */ var dstH = dst.getHeight(); /** @type {Array} */ var uq = deMath.scale(sq, src.getWidth()); /** @type {Array} */ var vq = deMath.scale(tq, src.getHeight()); /** @type {Array>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; /** @type {Array>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; /** @type {Array>} */ var triU = [deMath.swizzle(uq, [0, 1, 2]), deMath.swizzle(uq, [3, 2, 1])]; /** @type {Array>} */ var triV = [deMath.swizzle(vq, [0, 1, 2]), deMath.swizzle(vq, [3, 2, 1])]; /** @type {Array>} */ var triW = [deMath.swizzle(params.w, [0, 1, 2]), deMath.swizzle(params.w, [3, 2, 1])]; for (var py = 0; py < dst.getHeight(); py++) { for (var px = 0; px < dst.getWidth(); px++) { /** @type {number} */ var wx = px + 0.5; /** @type {number} */ var wy = py + 0.5; /** @type {number} */ var nx = wx / dstW; /** @type {number} */ var ny = wy / dstH; /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0; /** @type {number} */ var triWx = triNdx ? dstW - wx : wx; /** @type {number} */ var triWy = triNdx ? dstH - wy : wy; /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx; /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny; /** @type {number} */ var s = glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy); /** @type {number} */ var t = glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy); /** @type {number} */ var lod = glsTextureTestUtil.computeProjectedTriLod2D(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triWx, triWy, dst.getWidth(), dst.getHeight()) + lodBias; var pixel = glsTextureTestUtil.execSample(src, params, [s, t], lod); glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias); dst.setPixel(pixel, px, py); } } }; /** * @param {glsTextureTestUtil.lodMode} mode * @param {Array} u * @param {Array} v * @param {Array} projection * @param {number} wx * @param {number} wy * @param {number} width * @param {number} height * @return {number} */ glsTextureTestUtil.computeProjectedTriLod2D = function(mode, u, v, projection, wx, wy, width, height) { // Exact derivatives. /** @type {number} */ var dudx = glsTextureTestUtil.triDerivateX(u, projection, wx, width, wy / height); /** @type {number} */ var dvdx = glsTextureTestUtil.triDerivateX(v, projection, wx, width, wy / height); /** @type {number} */ var dudy = glsTextureTestUtil.triDerivateY(u, projection, wy, height, wx / width); /** @type {number} */ var dvdy = glsTextureTestUtil.triDerivateY(v, projection, wy, height, wx / width); return glsTextureTestUtil.computeLodFromDerivates2D(mode, dudx, dvdx, dudy, dvdy); }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.Texture2DView} src * @param {Array} sq * @param {Array} tq * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTextureNonProjected2D = function(dst, src, sq, tq, params) { var lodBias = params.flags.use_bias ? params.bias : 0; var dstSize = [dst.getWidth(), dst.getHeight()]; var srcSize = [src.getWidth(), src.getHeight()]; // Coordinates and lod per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triLod = [deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias), params.minLod, params.maxLod), deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias), params.minLod, params.maxLod)]; for (var y = 0; y < dst.getHeight(); y++) { for (var x = 0; x < dst.getWidth(); x++) { var yf = (y + 0.5) / dst.getHeight(); var xf = (x + 0.5) / dst.getWidth(); var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule. var triX = triNdx ? 1 - xf : xf; var triY = triNdx ? 1 - yf : yf; var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY); var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY); var lod = triLod[triNdx]; var pixel = glsTextureTestUtil.execSample(src, params, [s, t], lod); glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias); dst.setPixel(pixel, x, y); } } }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.Texture2DArrayView} src * @param {Array} sq * @param {Array} tq * @param {Array} rq * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTextureNonProjected2DArray = function(dst, src, sq, tq, rq, params) { var lodBias = (params.flags.use_bias) ? params.bias : 0; var dstSize = [dst.getWidth(), dst.getHeight()]; var srcSize = [src.getWidth(), src.getHeight()]; // Coordinates and lod per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; var triLod = [glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias]; for (var y = 0; y < dst.getHeight(); y++) { for (var x = 0; x < dst.getWidth(); x++) { var yf = (y + 0.5) / dst.getHeight(); var xf = (x + 0.5) / dst.getWidth(); var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule. var triX = triNdx ? 1 - xf : xf; var triY = triNdx ? 1 - yf : yf; var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY); var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY); var r = glsTextureTestUtil.triangleInterpolate(triR[triNdx], triX, triY); var lod = triLod[triNdx]; var pixel = glsTextureTestUtil.execSample(src, params, [s, t, r], lod); glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias); dst.setPixel(pixel, x, y); } } }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.Texture2DView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTexture2D = function(dst, src, texCoord, params) { var view = src.getSubView(params.baseLevel, params.maxLevel); var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]]; var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]]; if (params.flags.projected) glsTextureTestUtil.sampleTextureProjected2D(dst, view, sq, tq, params); else glsTextureTestUtil.sampleTextureNonProjected2D(dst, view, sq, tq, params); }; /** * @param {glsTextureTestUtil.lodMode} mode * @param {number} dudx * @param {number} dvdx * @param {number} dudy * @param {number} dvdy * @return {number} */ glsTextureTestUtil.computeLodFromDerivates2D = function(mode, dudx, dvdx, dudy, dvdy) { var p = 0; switch (mode) { case glsTextureTestUtil.lodMode.EXACT: p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx), Math.sqrt(dudy * dudy + dvdy * dvdy)); break; case glsTextureTestUtil.lodMode.MIN_BOUND: case glsTextureTestUtil.lodMode.MAX_BOUND: { var mu = Math.max(Math.abs(dudx), Math.abs(dudy)); var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy)); p = (mode == glsTextureTestUtil.lodMode.MIN_BOUND) ? Math.max(mu, mv) : mu + mv; break; } default: throw new Error('Unrecognized mode:' + mode); } // Native dEQP uses 32-bit numbers. So here 64-bit floating numbers should be transformed into 32-bit ones to ensure the correctness of the result. return deMath.toFloat32(Math.log(p)) * deMath.INV_LOG_2_FLOAT32; }; /** * @param {glsTextureTestUtil.lodMode} lodModeParm * @param {Array} coord * @param {Array} coordDx * @param {Array} coordDy * @param {number} faceSize * @return {number} */ glsTextureTestUtil.computeCubeLodFromDerivates = function(lodModeParm, coord, coordDx, coordDy, faceSize) { var face = tcuTexture.selectCubeFace(coord); var maNdx = 0; var sNdx = 0; var tNdx = 0; // \note Derivate signs don't matter when computing lod switch (face) { case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break; case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break; case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break; default: throw new Error('Unrecognized face ' + face); } { var sc = coord[sNdx]; var tc = coord[tNdx]; var ma = Math.abs(coord[maNdx]); var scdx = coordDx[sNdx]; var tcdx = coordDx[tNdx]; var madx = Math.abs(coordDx[maNdx]); var scdy = coordDy[sNdx]; var tcdy = coordDy[tNdx]; var mady = Math.abs(coordDy[maNdx]); var dudx = faceSize * 0.5 * (scdx * ma - sc * madx) / (ma * ma); var dvdx = faceSize * 0.5 * (tcdx * ma - tc * madx) / (ma * ma); var dudy = faceSize * 0.5 * (scdy * ma - sc * mady) / (ma * ma); var dvdy = faceSize * 0.5 * (tcdy * ma - tc * mady) / (ma * ma); return glsTextureTestUtil.computeLodFromDerivates2D(lodModeParm, dudx, dvdx, dudy, dvdy); } }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.TextureCubeView} src * @param {Array} sq * @param {Array} tq * @param {Array} rq * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTextureCube_str = function(dst, src, sq, tq, rq, params) { var dstSize = [dst.getWidth(), dst.getHeight()]; var dstW = dstSize[0]; var dstH = dstSize[1]; var srcSize = src.getSize(); // Coordinates per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; var triW = [deMath.swizzle(params.w, [0, 1, 2]), deMath.swizzle(params.w, [3, 2, 1])]; var lodBias = (params.flags.use_bias ? params.bias : 0); for (var py = 0; py < dst.getHeight(); py++) { for (var px = 0; px < dst.getWidth(); px++) { var wx = px + 0.5; var wy = py + 0.5; var nx = wx / dstW; var ny = wy / dstH; var triNdx = nx + ny >= 1 ? 1 : 0; var triNx = triNdx ? 1 - nx : nx; var triNy = triNdx ? 1 - ny : ny; var coord = [glsTextureTestUtil.triangleInterpolate(triS[triNdx], triNx, triNy), glsTextureTestUtil.triangleInterpolate(triT[triNdx], triNx, triNy), glsTextureTestUtil.triangleInterpolate(triR[triNdx], triNx, triNy)]; var coordDx = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)]; var coordDy = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)]; var lod = deMath.clamp((glsTextureTestUtil.computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, srcSize) + lodBias), params.minLod, params.maxLod); var pixel = glsTextureTestUtil.execSample(src, params, coord, lod); glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias); dst.setPixel(pixel, px, py); } } }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.TextureCubeView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTextureCube = function(dst, src, texCoord, params) { /*const tcu::TextureCubeView*/ var view = src.getSubView(params.baseLevel, params.maxLevel); var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; glsTextureTestUtil.sampleTextureCube_str(dst, view, sq, tq, rq, params); }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.Texture2DArrayView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTexture2DArray = function(dst, src, texCoord, params) { var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; DE_ASSERT(!(params.flags.projected)); // \todo [2012-02-17 pyry] Support projected lookups. glsTextureTestUtil.sampleTextureNonProjected2DArray(dst, src, sq, tq, rq, params); }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.Texture3DView} src * @param {Array} sq * @param {Array} tq * @param {Array} rq * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTextureNonProjected3D = function(dst, src, sq, tq, rq, params) { var lodBias = params.flags.use_bias ? params.bias : 0; var dstSize = [dst.getWidth(), dst.getHeight()]; var srcSize = [src.getWidth(), src.getHeight(), src.getDepth()]; // Coordinates and lod per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; var triLod = [deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias), params.minLod, params.maxLod), deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias), params.minLod, params.maxLod)]; for (var y = 0; y < dst.getHeight(); y++) { for (var x = 0; x < dst.getWidth(); x++) { var yf = (y + 0.5) / dst.getHeight(); var xf = (x + 0.5) / dst.getWidth(); var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule. var triX = triNdx ? 1 - xf : xf; var triY = triNdx ? 1 - yf : yf; var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY); var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY); var r = glsTextureTestUtil.triangleInterpolate(triR[triNdx], triX, triY); var lod = triLod[triNdx]; var pixel = src.sample(params.sampler, [s, t, r], lod); glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias); dst.setPixel(pixel, x, y); } } }; /** * @param {glsTextureTestUtil.SurfaceAccess} dst * @param {tcuTexture.Texture3DView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} params */ glsTextureTestUtil.sampleTexture3D = function(dst, src, texCoord, params) { /*const tcu::TextureCubeView*/ var view = src.getSubView(params.baseLevel, params.maxLevel); var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; glsTextureTestUtil.sampleTextureNonProjected3D(dst, view, sq, tq, rq, params); }; /** * @param {tcuSurface.Surface} reference * @param {tcuSurface.Surface} rendered * @param {Array} threshold * @param {Array< Array >} skipPixels * * @return {boolean} */ glsTextureTestUtil.compareImages = function(reference, rendered, threshold, skipPixels) { return tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', reference, rendered, threshold, undefined /*tcu::COMPARE_LOG_RESULT*/, skipPixels); }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.Texture2DView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {tcuPixelFormat.PixelFormat} pixelFormat * @return {boolean} */ glsTextureTestUtil.verifyTexture2DResult = function(result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat) { DE_ASSERT(deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask)); /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight()); /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight()); /** @type {number} */ var numFailedPixels; /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat); glsTextureTestUtil.sampleTexture2D(surface, src, texCoord, sampleParams); numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff2D(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec/*, testCtx.getWatchDog()*/); if (numFailedPixels > 0) tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess()); return numFailedPixels == 0; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.ConstPixelBufferAccess} reference * @param {tcuTexture.PixelBufferAccess} errorMask * @param {tcuTexture.Texture2DView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {Array} nonShadowThreshold * @return {number} */ glsTextureTestUtil.computeTextureCompareDiff2D = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) { DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]]; var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]]; var dstSize = [result.getWidth(), result.getHeight()]; var dstW = dstSize[0]; var dstH = dstSize[1]; var srcSize = [src.getWidth(), src.getHeight()]; // Coordinates and lod per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])]; var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0]; var numFailed = 0; var lodOffsets = [ [-1, 0], [1, 0], [0, -1], [0, 1] ]; /** @type {Array} */ var green = [0, 255, 0, 255]; errorMask.clear(green); /** @type {Array} */ var red = []; for (var py = 0; py < result.getHeight(); py++) { for (var px = 0; px < result.getWidth(); px++) { /** @type {Array} */ var resPix = result.getPixel(px, py); /** @type {Array} */ var refPix = reference.getPixel(px, py); if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(refPix, [1, 2, 3]), deMath.swizzle(resPix, [1, 2, 3])), nonShadowThreshold))) { red = [255, 0, 0, 255]; errorMask.setPixel(red, px, py); numFailed += 1; continue; } if (resPix[0] != refPix[0]) { var wx = px + 0.5; var wy = py + 0.5; var nx = wx / dstW; var ny = wy / dstH; var triNdx = nx + ny >= 1.0 ? 1 : 0; var triWx = triNdx ? dstW - wx : wx; var triWy = triNdx ? dstH - wy : wy; var triNx = triNdx ? 1.0 - nx : nx; var triNy = triNdx ? 1.0 - ny : ny; var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)]; var coordDx = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize); var coordDy = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize); var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec); // Compute lod bounds across lodOffsets range. for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) { var wxo = triWx + lodOffsets[lodOffsNdx][0]; var wyo = triWy + lodOffsets[lodOffsNdx][1]; var nxo = wxo / dstW; var nyo = wyo / dstH; var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)]; var coordDxo = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize); var coordDyo = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize); var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec); lodBounds[0] = Math.min(lodBounds[0], lodO[0]); lodBounds[1] = Math.max(lodBounds[1], lodO[1]); } var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec); var isOk = tcuTexCompareVerifier.isTexCompareResultValid2D(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]); if (!isOk) { red = [255, 0, 0, 255]; errorMask.setPixel(red, px, py); numFailed += 1; } } } } return numFailed; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.Texture3DView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {tcuPixelFormat.PixelFormat} pixelFormat * @return {boolean} */ glsTextureTestUtil.verifyTexture3DResult = function( result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat ) { /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight()); /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight()); var numFailedPixels = 0; assertMsgOptions( deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask), 'Compare color masks do not match', false, true ); /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat); glsTextureTestUtil.sampleTexture3D(surface, src, texCoord, sampleParams); numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff3D(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec); if (numFailedPixels > 0) tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess()); return numFailedPixels == 0; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.ConstPixelBufferAccess} reference * @param {tcuTexture.PixelBufferAccess} errorMask * @param {tcuTexture.Texture3DView} baseView * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @return {number} */ glsTextureTestUtil.computeTextureLookupDiff3D = function( result, reference, errorMask, baseView, texCoord, sampleParams, lookupPrec, lodPrec ) { assertMsgOptions( result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Result and reference images are not the same size', false, true ); assertMsgOptions( result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight(), 'Result and error mask images are not the same size', false, true ); /** @type {tcuTexture.Texture3DView} */ var src = baseView.getSubView( sampleParams.baseLevel, sampleParams.maxLevel ); var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; var dstSize = [result.getWidth(), result.getHeight()]; var dstW = dstSize[0]; var dstH = dstSize[1]; var srcSize = [src.getWidth(), src.getHeight(), src.getDepth()]; // Coordinates and lod per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; var triW = [ deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1]) ]; var lodBias = sampleParams.flags.useBias ? sampleParams.bias : 0.0; var posEps = 1.0 / ((1 << MIN_SUBPIXEL_BITS) + 1); var numFailed = 0; var lodOffsets = [ [-1, 0], [+1, 0], [0, -1], [0, +1] ]; var green = [0, 255, 0, 255]; errorMask.clear(new tcuRGBA.RGBA(green).toVec()); for (var py = 0; py < result.getHeight(); py++) { // Ugly hack, validation can take way too long at the moment. /*TODO: if (watchDog) qpWatchDog_touch(watchDog);*/ for (var px = 0; px < result.getWidth(); px++) { /** @type {Array} */ var resPix = result.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias); /** @type {Array} */ var refPix = reference.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias); // Try comparison to ideal reference first, // and if that fails use slower verificator. if (!deMath.boolAll(deMath.lessThanEqual( deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold)) ) { /** @type {number} */ var wx = px + 0.5; /** @type {number} */ var wy = py + 0.5; /** @type {number} */ var nx = wx / dstW; /** @type {number} */ var ny = wy / dstH; /** @type {boolean} */ var tri0 = nx + ny - posEps <= 1.0; /** @type {boolean} */ var tri1 = nx + ny + posEps >= 1.0; var isOk = false; assertMsgOptions( tri0 || tri1, 'Pixel should belong at least to one triangle', false, true ); // Pixel can belong to either of the triangles // if it lies close enough to the edge. for (var triNdx = (tri0 ? 0 : 1); triNdx <= (tri1 ? 1 : 0); triNdx++) { var triWx = triNdx ? dstW - wx : wx; var triWy = triNdx ? dstH - wy : wy; var triNx = triNdx ? 1.0 - nx : nx; var triNy = triNdx ? 1.0 - ny : ny; var coord = [ glsTextureTestUtil.projectedTriInterpolate( triS[triNdx], triW[triNdx], triNx, triNy ), glsTextureTestUtil.projectedTriInterpolate( triT[triNdx], triW[triNdx], triNx, triNy ), glsTextureTestUtil.projectedTriInterpolate( triR[triNdx], triW[triNdx], triNx, triNy ) ]; var coordDx = deMath.multiply([ glsTextureTestUtil.triDerivateX( triS[triNdx], triW[triNdx], wx, dstW, triNy ), glsTextureTestUtil.triDerivateX( triT[triNdx], triW[triNdx], wx, dstW, triNy ), glsTextureTestUtil.triDerivateX( triR[triNdx], triW[triNdx], wx, dstW, triNy ) ], srcSize); var coordDy = deMath.multiply([ glsTextureTestUtil.triDerivateY( triS[triNdx], triW[triNdx], wy, dstH, triNx ), glsTextureTestUtil.triDerivateY( triT[triNdx], triW[triNdx], wy, dstH, triNx ), glsTextureTestUtil.triDerivateY( triR[triNdx], triW[triNdx], wy, dstH, triNx ) ], srcSize); var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivates( coordDx[0], coordDx[1], coordDx[2], coordDy[0], coordDy[1], coordDy[2], lodPrec ); // Compute lod bounds across lodOffsets range. for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) { var wxo = triWx + lodOffsets[lodOffsNdx][0]; var wyo = triWy + lodOffsets[lodOffsNdx][1]; var nxo = wxo / dstW; var nyo = wyo / dstH; var coordO = [ glsTextureTestUtil.projectedTriInterpolate( triS[triNdx], triW[triNdx], nxo, nyo ), glsTextureTestUtil.projectedTriInterpolate( triT[triNdx], triW[triNdx], nxo, nyo ), glsTextureTestUtil.projectedTriInterpolate( triR[triNdx], triW[triNdx], nxo, nyo ) ]; var coordDxo = deMath.multiply([ glsTextureTestUtil.triDerivateX( triS[triNdx], triW[triNdx], wxo, dstW, nyo ), glsTextureTestUtil.triDerivateX( triT[triNdx], triW[triNdx], wxo, dstW, nyo ), glsTextureTestUtil.triDerivateX( triR[triNdx], triW[triNdx], wxo, dstW, nyo ) ], srcSize); var coordDyo = deMath.multiply([ glsTextureTestUtil.triDerivateY( triS[triNdx], triW[triNdx], wyo, dstH, nxo ), glsTextureTestUtil.triDerivateY( triT[triNdx], triW[triNdx], wyo, dstH, nxo ), glsTextureTestUtil.triDerivateY( triR[triNdx], triW[triNdx], wyo, dstH, nxo ) ], srcSize); var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivates( coordDxo[0], coordDxo[1], coordDxo[2], coordDyo[0], coordDyo[1], coordDyo[2], lodPrec ); lodBounds[0] = Math.min(lodBounds[0], lodO[0]); lodBounds[1] = Math.max(lodBounds[1], lodO[1]); } var clampedLod = tcuTexLookupVerifier.clampLodBounds( deMath.addScalar(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec ); if ( tcuTexLookupVerifier.isLookupResultValid( src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix ) ) { isOk = true; break; } } if (!isOk) { var red = [255, 0, 0, 255]; errorMask.setPixel(new tcuRGBA.RGBA(red).toVec(), px, py); numFailed += 1; } } } } return numFailed; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.TextureCubeView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {tcuPixelFormat.PixelFormat} pixelFormat * @return {boolean} */ glsTextureTestUtil.verifyTextureCubeResult = function( result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat ) { /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface( result.getWidth(), result.getHeight() ); /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface( result.getWidth(), result.getHeight() ); /** @type {number} */ var numFailedPixels = 0; assertMsgOptions( deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask), 'Compare color masks do not match', false, true ); /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat); glsTextureTestUtil.sampleTextureCube( surface, src, texCoord, sampleParams ); numFailedPixels = glsTextureTestUtil.computeTextureLookupDiffCube( result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec /*, testCtx.getWatchDog()*/ ); if (numFailedPixels > 0) tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess()); return numFailedPixels == 0; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.ConstPixelBufferAccess} reference * @param {tcuTexture.PixelBufferAccess} errorMask * @param {tcuTexture.TextureCubeView} baseView * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @return {number} */ glsTextureTestUtil.computeTextureLookupDiffCube = function( result, reference, errorMask, baseView, texCoord, sampleParams, lookupPrec, lodPrec ) { assertMsgOptions( result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Result and reference images are not the same size', false, true ); assertMsgOptions( result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight(), 'Result and error mask images are not the same size', false, true ); /** @type {tcuTexture.TextureCubeView} */ var src = baseView.getSubView( sampleParams.baseLevel, sampleParams.maxLevel ); var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; var dstSize = [result.getWidth(), result.getHeight()]; var dstW = dstSize[0]; var dstH = dstSize[1]; var srcSize = [src.getSize(), src.getSize()]; // Coordinates and lod per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; var triW = [ deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1]) ]; var lodBias = sampleParams.flags.useBias ? sampleParams.bias : 0.0; var posEps = 1.0 / ((1 << MIN_SUBPIXEL_BITS) + 1); var numFailed = 0; var lodOffsets = [ [-1, 0], [+1, 0], [0, -1], [0, +1], // \note Not strictly allowed by spec, // but implementations do this in practice. [-1, -1], [-1, 1], [1, -1], [1, 1] ]; var green = [0, 255, 0, 255]; errorMask.clear(new tcuRGBA.RGBA(green).toVec()); for (var py = 0; py < result.getHeight(); py++) { // Ugly hack, validation can take way too long at the moment. /*TODO: if (watchDog) qpWatchDog_touch(watchDog);*/ for (var px = 0; px < result.getWidth(); px++) { /** @type {Array} */ var resPix = result.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias); /** @type {Array} */ var refPix = reference.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias); // Try comparison to ideal reference first, // and if that fails use slower verificator. if (!deMath.boolAll(deMath.lessThanEqual( deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold)) ) { /** @type {number} */ var wx = px + 0.5; /** @type {number} */ var wy = py + 0.5; /** @type {number} */ var nx = wx / dstW; /** @type {number} */ var ny = wy / dstH; /** @type {boolean} */ var tri0 = nx + ny - posEps <= 1.0; /** @type {boolean} */ var tri1 = nx + ny + posEps >= 1.0; var isOk = false; assertMsgOptions( tri0 || tri1, 'Pixel should belong at least to one triangle', false, true ); // Pixel can belong to either of the triangles // if it lies close enough to the edge. for (var triNdx = (tri0 ? 0 : 1); triNdx <= (tri1 ? 1 : 0); triNdx++) { var triWx = triNdx ? dstW - wx : wx; var triWy = triNdx ? dstH - wy : wy; var triNx = triNdx ? 1.0 - nx : nx; var triNy = triNdx ? 1.0 - ny : ny; var coord = [ glsTextureTestUtil.projectedTriInterpolate( triS[triNdx], triW[triNdx], triNx, triNy ), glsTextureTestUtil.projectedTriInterpolate( triT[triNdx], triW[triNdx], triNx, triNy ), glsTextureTestUtil.projectedTriInterpolate( triR[triNdx], triW[triNdx], triNx, triNy ) ]; var coordDx = [ glsTextureTestUtil.triDerivateX( triS[triNdx], triW[triNdx], wx, dstW, triNy ), glsTextureTestUtil.triDerivateX( triT[triNdx], triW[triNdx], wx, dstW, triNy ), glsTextureTestUtil.triDerivateX( triR[triNdx], triW[triNdx], wx, dstW, triNy ) ]; var coordDy = [ glsTextureTestUtil.triDerivateY( triS[triNdx], triW[triNdx], wy, dstH, triNx ), glsTextureTestUtil.triDerivateY( triT[triNdx], triW[triNdx], wy, dstH, triNx ), glsTextureTestUtil.triDerivateY( triR[triNdx], triW[triNdx], wy, dstH, triNx ) ]; var lodBounds = tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates( coord, coordDx, coordDy, src.getSize(), lodPrec ); // Compute lod bounds across lodOffsets range. for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) { var wxo = triWx + lodOffsets[lodOffsNdx][0]; var wyo = triWy + lodOffsets[lodOffsNdx][1]; var nxo = wxo / dstW; var nyo = wyo / dstH; var coordO = [ glsTextureTestUtil.projectedTriInterpolate( triS[triNdx], triW[triNdx], nxo, nyo ), glsTextureTestUtil.projectedTriInterpolate( triT[triNdx], triW[triNdx], nxo, nyo ), glsTextureTestUtil.projectedTriInterpolate( triR[triNdx], triW[triNdx], nxo, nyo ) ]; var coordDxo = [ glsTextureTestUtil.triDerivateX( triS[triNdx], triW[triNdx], wxo, dstW, nyo ), glsTextureTestUtil.triDerivateX( triT[triNdx], triW[triNdx], wxo, dstW, nyo ), glsTextureTestUtil.triDerivateX( triR[triNdx], triW[triNdx], wxo, dstW, nyo ) ]; var coordDyo = [ glsTextureTestUtil.triDerivateY( triS[triNdx], triW[triNdx], wyo, dstH, nxo ), glsTextureTestUtil.triDerivateY( triT[triNdx], triW[triNdx], wyo, dstH, nxo ), glsTextureTestUtil.triDerivateY( triR[triNdx], triW[triNdx], wyo, dstH, nxo ) ]; var lodO = tcuTexLookupVerifier. computeCubeLodBoundsFromDerivates( coordO, coordDxo, coordDyo, src.getSize(), lodPrec ); lodBounds[0] = Math.min(lodBounds[0], lodO[0]); lodBounds[1] = Math.max(lodBounds[1], lodO[1]); } var clampedLod = tcuTexLookupVerifier.clampLodBounds( deMath.addScalar(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec ); if (tcuTexLookupVerifier. isLookupResultValid_TextureCubeView( src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix ) ) { isOk = true; break; } } if (!isOk) { var red = [255, 0, 0, 255]; errorMask.setPixel(new tcuRGBA.RGBA(red).toVec(), px, py); numFailed += 1; } } } } return numFailed; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.Texture2DArrayView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {tcuPixelFormat.PixelFormat} pixelFormat * @return {boolean} */ glsTextureTestUtil.verifyTexture2DArrayResult = function(result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat) { DE_ASSERT(deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask)); /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight()); /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight()); /** @type {number} */ var numFailedPixels; /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat); glsTextureTestUtil.sampleTexture2DArray(surface, src, texCoord, sampleParams); numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff2DArray(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec/*, testCtx.getWatchDog()*/); if (numFailedPixels > 0) tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess()); return numFailedPixels == 0; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.ConstPixelBufferAccess} reference * @param {tcuTexture.PixelBufferAccess} errorMask * @param {tcuTexture.Texture2DArrayView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {Array} nonShadowThreshold * @return {number} */ glsTextureTestUtil.computeTextureCompareDiff2DArray = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) { DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; var dstSize = [result.getWidth(), result.getHeight()]; var dstW = dstSize[0]; var dstH = dstSize[1]; var srcSize = [src.getWidth(), src.getHeight()]; // Coordinates and lod per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])]; var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0]; var numFailed = 0; var lodOffsets = [ [-1, 0], [1, 0], [0, -1], [0, 1] ]; /** @type {Array} */ var green = [0, 255, 0, 255]; errorMask.clear(green); /** @type {Array} */ var red = []; for (var py = 0; py < result.getHeight(); py++) { for (var px = 0; px < result.getWidth(); px++) { /** @type {Array} */ var resPix = result.getPixel(px, py); /** @type {Array} */ var refPix = reference.getPixel(px, py); if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(refPix, [1, 2, 3]), deMath.swizzle(resPix, [1, 2, 3])), nonShadowThreshold))) { red = [255, 0, 0, 255]; errorMask.setPixel(red, px, py); numFailed += 1; continue; } if (resPix[0] != refPix[0]) { var wx = px + 0.5; var wy = py + 0.5; var nx = wx / dstW; var ny = wy / dstH; var triNdx = nx + ny >= 1.0 ? 1 : 0; var triWx = triNdx ? dstW - wx : wx; var triWy = triNdx ? dstH - wy : wy; var triNx = triNdx ? 1.0 - nx : nx; var triNy = triNdx ? 1.0 - ny : ny; var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)]; var coordDx = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize); var coordDy = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize); var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec); // Compute lod bounds across lodOffsets range. for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) { var wxo = triWx + lodOffsets[lodOffsNdx][0]; var wyo = triWy + lodOffsets[lodOffsNdx][1]; var nxo = wxo / dstW; var nyo = wyo / dstH; var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)]; var coordDxo = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize); var coordDyo = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize); var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec); lodBounds[0] = Math.min(lodBounds[0], lodO[0]); lodBounds[1] = Math.max(lodBounds[1], lodO[1]); } var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec); var isOk = tcuTexCompareVerifier.isTexCompareResultValid2DArray(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]); if (!isOk) { red = [255, 0, 0, 255]; errorMask.setPixel(red, px, py); numFailed += 1; } } } } return numFailed; }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.ConstPixelBufferAccess} reference * @param {tcuTexture.PixelBufferAccess} errorMask * @param {tcuTexture.TextureCubeView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {Array} nonShadowThreshold * @return {number} */ glsTextureTestUtil.computeTextureCompareDiffCube = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) { DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; var dstSize = [result.getWidth(), result.getHeight()]; var dstW = dstSize[0]; var dstH = dstSize[1]; var srcSize = src.getSize(); // Coordinates per triangle. var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])]; var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0]; var numFailed = 0; var lodOffsets = [ [-1, 0], [1, 0], [0, -1], [0, 1] ]; /** @type {Array} */ var green = [0, 255, 0, 255]; errorMask.clear(new tcuRGBA.RGBA(green).toVec()); /** @type {Array} */ var red = []; for (var py = 0; py < result.getHeight(); py++) { for (var px = 0; px < result.getWidth(); px++) { /** @type {Array} */ var resPix = result.getPixel(px, py); /** @type {Array} */ var refPix = reference.getPixel(px, py); if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(resPix, [1, 2, 3]), deMath.swizzle(refPix, [1, 2, 3])), nonShadowThreshold))) { red = [255, 0, 0, 255]; errorMask.setPixel(red, px, py); numFailed += 1; continue; } if (resPix[0] != refPix[0]) { var wx = px + 0.5; var wy = py + 0.5; var nx = wx / dstW; var ny = wy / dstH; var triNdx = nx + ny >= 1.0 ? 1 : 0; var triWx = triNdx ? dstW - wx : wx; var triWy = triNdx ? dstH - wy : wy; var triNx = triNdx ? 1.0 - nx : nx; var triNy = triNdx ? 1.0 - ny : ny; var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)]; var coordDx = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)]; var coordDy = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)]; var lodBounds = tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec); // Compute lod bounds across lodOffsets range. for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) { var wxo = triWx + lodOffsets[lodOffsNdx][0]; var wyo = triWy + lodOffsets[lodOffsNdx][1]; var nxo = wxo / dstW; var nyo = wyo / dstH; var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo), glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)]; var coordDxo = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo), glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)]; var coordDyo = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo), glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)]; var lodO = tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec); lodBounds[0] = Math.min(lodBounds[0], lodO[0]); lodBounds[1] = Math.max(lodBounds[1], lodO[1]); } var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec); var isOk = tcuTexCompareVerifier.isTexCompareResultValidCube(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]); if (!isOk) { red = [255, 0, 0, 255]; errorMask.setPixel(red, px, py); numFailed += 1; } } } } return numFailed; }; /** * @param {Array} s * @param {Array} w * @param {number} nx * @param {number} ny * @return {number} */ glsTextureTestUtil.projectedTriInterpolate = function(s, w, nx, ny) { return (s[0] * (1.0 - nx - ny) / w[0] + s[1] * ny / w[1] + s[2] * nx / w[2]) / ((1.0 - nx - ny) / w[0] + ny / w[1] + nx / w[2]); }; /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.ConstPixelBufferAccess} reference * @param {tcuTexture.PixelBufferAccess} errorMask * @param {tcuTexture.Texture2DView} baseView * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {*=} watchDog - TODO: ?? * @return {number} */ glsTextureTestUtil.computeTextureLookupDiff2D = function(result, reference, errorMask, baseView, texCoord, sampleParams, lookupPrec, lodPrec, watchDog) { DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); /** @type {tcuTexture.Texture2DView} */ var src = baseView.getSubView(sampleParams.baseLevel, sampleParams.maxLevel); /** @type {Array} */ var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]]; /** @type {Array} */ var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]]; /** @type {Array} */ var dstSize = [result.getWidth(), result.getHeight()]; /** @type {number} */ var dstW = dstSize[0]; /** @type {number} */ var dstH = dstSize[1]; /** @type {Array} */ var srcSize = [src.getWidth(), src.getHeight()]; // Coordinates and lod per triangle. /** @type {Array>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; /** @type {Array>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; /** @type {Array>} */ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])]; /** @type {Array} */ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0.0, 0.0]; /** @type {number} */ var numFailed = 0; /** @type {Array>} */ var lodOffsets = [ [-1, 0], [1, 0], [0, -1], [0, 1] ]; /** @type {Array} */ var green = [0, 255, 0, 255]; errorMask.clear(new tcuRGBA.RGBA(green).toVec()); for (var py = 0; py < result.getHeight(); py++) { // Ugly hack, validation can take way too long at the moment. // TODO:are we implementing qpWatchDog? skipping in the meantime // if (watchDog) // qpWatchDog_touch(watchDog); for (var px = 0; px < result.getWidth(); px++) { /** @type {Array} */ var resPix = result.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias); /** @type {Array} */ var refPix = reference.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias); // Try comparison to ideal reference first, and if that fails use slower verificator. if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold))) { /** @type {number} */ var wx = px + 0.5; /** @type {number} */ var wy = py + 0.5; /** @type {number} */ var nx = wx / dstW; /** @type {number} */ var ny = wy / dstH; /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0; /** @type {number} */ var triWx = triNdx ? dstW - wx : wx; /** @type {number} */ var triWy = triNdx ? dstH - wy : wy; /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx; /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny; /** @type {Array} */ var coord = [ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy) ]; /** @type {Array} */ var coordDx = deMath.multiply([ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize); /** @type {Array} */ var coordDy = deMath.multiply([ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize); /** @type {Array} */ var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec); // Compute lod bounds across lodOffsets range. for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) { /** @type {number} */ var wxo = triWx + lodOffsets[lodOffsNdx][0]; /** @type {number} */ var wyo = triWy + lodOffsets[lodOffsNdx][1]; /** @type {number} */ var nxo = wxo / dstW; /** @type {number} */ var nyo = wyo / dstH; /** @type {Array} */ var coordO = [ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)]; /** @type {Array} */ var coordDxo = deMath.multiply([ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize); /** @type {Array} */ var coordDyo = deMath.multiply([ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize); /** @type {Array} */ var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec); lodBounds[0] = Math.min(lodBounds[0], lodO[0]); lodBounds[1] = Math.max(lodBounds[1], lodO[1]); } /** @type {Array} */ var clampedLod = tcuTexLookupVerifier.clampLodBounds( deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec); /** @type {boolean} */ var isOk = tcuTexLookupVerifier.isLookupResultValid_Texture2DView(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix); if (!isOk) { /** @type {tcuRGBA.RGBA} */ var red = tcuRGBA.newRGBAComponents(255, 0, 0, 255); errorMask.setPixel(red.toVec(), px, py); numFailed += 1; } } } } return numFailed; }; // Verifies texture lookup results and returns number of failed pixels. /** * @param {tcuTexture.ConstPixelBufferAccess} result * @param {tcuTexture.ConstPixelBufferAccess} reference * @param {tcuTexture.PixelBufferAccess} errorMask * @param {tcuTexture.Texture2DArrayView} src * @param {Array} texCoord * @param {glsTextureTestUtil.ReferenceParams} sampleParams * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec * @param {tcuTexLookupVerifier.LodPrecision} lodPrec * @param {*=} watchDog - TODO: ?? * @return {number} */ glsTextureTestUtil.computeTextureLookupDiff2DArray = function(result, reference, errorMask, src, texCoord, sampleParams, lookupPrec, lodPrec, watchDog) { DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); /** @type {Array} */ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]]; /** @type {Array} */ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]]; /** @type {Array} */ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]]; /** @type {Array} */ var dstSize = [result.getWidth(), result.getHeight()]; /** @type {number} */ var dstW = dstSize[0]; /** @type {number} */ var dstH = dstSize[1]; /** @type {Array} */ var srcSize = [src.getWidth(), src.getHeight()]; // Coordinates and lod per triangle. /** @type {Array>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])]; /** @type {Array>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])]; /** @type {Array>} */ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])]; /** @type {Array>} */ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])]; /** @type {Array} */ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0.0, 0.0]; /** @type {number} */ var numFailed = 0; /** @type {Array>} */ var lodOffsets = [ [-1, 0], [1, 0], [0, -1], [0, 1] ]; /** @type {Array} */ var green = [0, 255, 0, 255]; errorMask.clear(new tcuRGBA.RGBA(green).toVec()); for (var py = 0; py < result.getHeight(); py++) { // Ugly hack, validation can take way too long at the moment. // TODO:are we implementing qpWatchDog? skipping in the meantime // if (watchDog) // qpWatchDog_touch(watchDog); for (var px = 0; px < result.getWidth(); px++) { /** @type {Array} */ var resPix = result.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias); /** @type {Array} */ var refPix = reference.getPixel(px, py); glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias); // Try comparison to ideal reference first, and if that fails use slower verificator. if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold))) { /** @type {number} */ var wx = px + 0.5; /** @type {number} */ var wy = py + 0.5; /** @type {number} */ var nx = wx / dstW; /** @type {number} */ var ny = wy / dstH; /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0; /** @type {number} */ var triWx = triNdx ? dstW - wx : wx; /** @type {number} */ var triWy = triNdx ? dstH - wy : wy; /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx; /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny; /** @type {Array} */ var coord = [ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy) ]; /** @type {Array} */ var coordDx = deMath.multiply([ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize); /** @type {Array} */ var coordDy = deMath.multiply([ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize); /** @type {Array} */ var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec); // Compute lod bounds across lodOffsets range. for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) { /** @type {number} */ var wxo = triWx + lodOffsets[lodOffsNdx][0]; /** @type {number} */ var wyo = triWy + lodOffsets[lodOffsNdx][1]; /** @type {number} */ var nxo = wxo / dstW; /** @type {number} */ var nyo = wyo / dstH; /** @type {Array} */ var coordO = [ glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo), glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo) ]; /** @type {Array} */ var coordDxo = deMath.multiply([ glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize ); /** @type {Array} */ var coordDyo = deMath.multiply([ glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize ); /** @type {Array} */ var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec); lodBounds[0] = Math.min(lodBounds[0], lodO[0]); lodBounds[1] = Math.max(lodBounds[1], lodO[1]); } /** @type {Array} */ var clampedLod = tcuTexLookupVerifier.clampLodBounds( deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec); /** @type {boolean} */ var isOk = tcuTexLookupVerifier.isLookupResultValid_Texture2DArrayView(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix); if (!isOk) { /** @type {tcuRGBA.RGBA} */ var red = tcuRGBA.newRGBAComponents(255, 0, 0, 255); errorMask.setPixel(red.toVec(), px, py); numFailed += 1; } } } } return numFailed; }; });