Bug 1918529 - fix some subpixel misalignment issues with gfx.webrender.svg-filter...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / framework / common / tcuTexCompareVerifier.js
blob254963ae6663af2748841609ce0d8189f4f14a05
1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 'use strict';
22 goog.provide('framework.common.tcuTexCompareVerifier');
23 goog.require('framework.common.tcuTexVerifierUtil');
24 goog.require('framework.common.tcuTexture');
25 goog.require('framework.common.tcuTextureUtil');
26 goog.require('framework.delibs.debase.deMath');
28 goog.scope(function() {
30 var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier;
31 var tcuTexture = framework.common.tcuTexture;
32 var deMath = framework.delibs.debase.deMath;
33 var tcuTextureUtil = framework.common.tcuTextureUtil;
34 var tcuTexVerifierUtil = framework.common.tcuTexVerifierUtil;
36 /**
37 * \brief Texture compare (shadow) lookup precision parameters.
38 * @constructor
39 * @struct
40 * @param {Array<number>=} coordBits
41 * @param {Array<number>=} uvwBits
42 * @param {number=} pcfBits
43 * @param {number=} referenceBits
44 * @param {number=} resultBits
46 tcuTexCompareVerifier.TexComparePrecision = function(coordBits, uvwBits, pcfBits, referenceBits, resultBits) {
47 this.coordBits = coordBits === undefined ? [22, 22, 22] : coordBits;
48 this.uvwBits = uvwBits === undefined ? [22, 22, 22] : uvwBits;
49 this.pcfBits = pcfBits === undefined ? 16 : pcfBits;
50 this.referenceBits = referenceBits === undefined ? 16 : referenceBits;
51 this.resultBits = resultBits === undefined ? 16 : resultBits;
54 /**
55 * @constructor
56 * @struct
58 tcuTexCompareVerifier.CmpResultSet = function() {
59 this.isTrue = false;
60 this.isFalse = false;
63 /**
64 * @param {tcuTexture.CompareMode} compareMode
65 * @param {number} cmpValue_
66 * @param {number} cmpReference_
67 * @param {number} referenceBits
68 * @param {boolean} isFixedPoint
69 * @return {tcuTexCompareVerifier.CmpResultSet}
71 tcuTexCompareVerifier.execCompare = function(compareMode,
72 cmpValue_,
73 cmpReference_,
74 referenceBits,
75 isFixedPoint) {
76 var clampValues = isFixedPoint; // if comparing against a floating point texture, ref (and value) is not clamped
77 var cmpValue = (clampValues) ? (deMath.clamp(cmpValue_, 0, 1)) : (cmpValue_);
78 var cmpReference = (clampValues) ? (deMath.clamp(cmpReference_, 0, 1)) : (cmpReference_);
79 var err = tcuTexVerifierUtil.computeFixedPointError(referenceBits);
80 var res = new tcuTexCompareVerifier.CmpResultSet();
82 switch (compareMode) {
83 case tcuTexture.CompareMode.COMPAREMODE_LESS:
84 res.isTrue = cmpReference - err < cmpValue;
85 res.isFalse = cmpReference + err >= cmpValue;
86 break;
88 case tcuTexture.CompareMode.COMPAREMODE_LESS_OR_EQUAL:
89 res.isTrue = cmpReference - err <= cmpValue;
90 res.isFalse = cmpReference + err > cmpValue;
91 break;
93 case tcuTexture.CompareMode.COMPAREMODE_GREATER:
94 res.isTrue = cmpReference + err > cmpValue;
95 res.isFalse = cmpReference - err <= cmpValue;
96 break;
98 case tcuTexture.CompareMode.COMPAREMODE_GREATER_OR_EQUAL:
99 res.isTrue = cmpReference + err >= cmpValue;
100 res.isFalse = cmpReference - err < cmpValue;
101 break;
103 case tcuTexture.CompareMode.COMPAREMODE_EQUAL:
104 res.isTrue = deMath.deInRange32(cmpValue, cmpReference - err, cmpReference + err);
105 res.isFalse = err != 0 || cmpValue != cmpReference;
106 break;
108 case tcuTexture.CompareMode.COMPAREMODE_NOT_EQUAL:
109 res.isTrue = err != 0 || cmpValue != cmpReference;
110 res.isFalse = deMath.deInRange32(cmpValue, cmpReference - err, cmpReference + err);
111 break;
113 case tcuTexture.CompareMode.COMPAREMODE_ALWAYS:
114 res.isTrue = true;
115 break;
117 case tcuTexture.CompareMode.COMPAREMODE_NEVER:
118 res.isFalse = true;
119 break;
121 default:
122 throw new Error('Invalid compare mode:' + compareMode);
125 assertMsgOptions(res.isTrue || res.isFalse, 'Both tests failed!', false, true);
126 return res;
130 * @param {tcuTexture.TextureFormat} format
131 * @return {boolean}
133 tcuTexCompareVerifier.isFixedPointDepthTextureFormat = function(format) {
134 var channelClass = tcuTexture.getTextureChannelClass(format.type);
136 if (format.order == tcuTexture.ChannelOrder.D) {
137 // depth internal formats cannot be non-normalized integers
138 return channelClass != tcuTexture.TextureChannelClass.FLOATING_POINT;
139 } else if (format.order == tcuTexture.ChannelOrder.DS) {
140 // combined formats have no single channel class, detect format manually
141 switch (format.type) {
142 case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return false;
143 case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return true;
145 default:
146 throw new Error('Invalid texture format: ' + format);
150 return false;
154 * @param {tcuTexture.CompareMode} compareMode
155 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
156 * @param {Array<number>} depths
157 * @param {Array<number>} fBounds
158 * @param {number} cmpReference
159 * @param {number} result
160 * @param {boolean} isFixedPointDepth
161 * @return {boolean}
163 tcuTexCompareVerifier.isLinearCompareValid = function(compareMode, prec, depths, fBounds, cmpReference, result, isFixedPointDepth) {
164 assertMsgOptions(fBounds[0] >= 0 && fBounds[0] <= fBounds[1] && fBounds[1] <= 1, 'Invalid fBounds', false, true);
166 var d0 = depths[0];
167 var d1 = depths[1];
169 var cmp0 = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
170 var cmp1 = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
171 var cmp = [cmp0, cmp1];
173 var isTrue = getMask(cmp, function(x) {return x.isTrue;});
174 var isFalse = getMask(cmp, function(x) {return x.isFalse;});
176 var f0 = fBounds[0];
177 var f1 = fBounds[1];
179 var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits);
180 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
181 var totalErr = pcfErr + resErr;
183 for (var comb = 0; comb < 4; comb++) {
184 if (((comb & isTrue) | (~comb & isFalse )) != 3)
185 continue;
187 var cmp0True = ((comb >> 0) & 1) != 0;
188 var cmp1True = ((comb >> 1) & 1) != 0;
190 var ref0 = cmp0True ? 1 : 0;
191 var ref1 = cmp1True ? 1 : 0;
193 var v0 = ref0 * (1 - f0) + ref1 * f0;
194 var v1 = ref0 * (1 - f1) + ref1 * f1;
195 var minV = Math.min(v0, v1);
196 var maxV = Math.max(v0, v1);
197 var minR = minV - totalErr;
198 var maxR = maxV + totalErr;
200 if (deMath.deInRange32(result, minR, maxR))
201 return true;
203 return false;
207 * @param {number} val
208 * @param {number} offset
209 * @return {Array<boolean>}
211 tcuTexCompareVerifier.extractBVec4 = function(val, offset) {
212 return [
213 ((val >> (offset + 0)) & 1) != 0,
214 ((val >> (offset + 1)) & 1) != 0,
215 ((val >> (offset + 2)) & 1) != 0,
216 ((val >> (offset + 3)) & 1) != 0];
220 * Values are in order (0,0), (1,0), (0,1), (1,1)
221 * @param {Array<number>} values
222 * @param {number} x
223 * @param {number} y
224 * @return {number}
226 tcuTexCompareVerifier.bilinearInterpolate = function(values, x, y) {
227 var v00 = values[0];
228 var v10 = values[1];
229 var v01 = values[2];
230 var v11 = values[3];
231 var res = v00 * (1 - x) * (1 - y) + v10 * x * (1 - y) + v01 * (1 - x) * y + v11 * x * y;
232 return res;
236 * @param {tcuTexture.CompareMode} compareMode
237 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
238 * @param {Array<number>} depths vec4
239 * @param {number} cmpReference
240 * @param {number} result
241 * @param {boolean} isFixedPointDepth
242 * @return {boolean}
244 tcuTexCompareVerifier.isBilinearAnyCompareValid = function(compareMode,
245 prec,
246 depths,
247 cmpReference,
248 result,
249 isFixedPointDepth) {
250 assertMsgOptions(prec.pcfBits === 0, 'PCF bits must be 0', false, true);
252 var d0 = depths[0];
253 var d1 = depths[1];
254 var d2 = depths[2];
255 var d3 = depths[3];
257 var cmp0 = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
258 var cmp1 = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
259 var cmp2 = tcuTexCompareVerifier.execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
260 var cmp3 = tcuTexCompareVerifier.execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);
262 var canBeTrue = cmp0.isTrue || cmp1.isTrue || cmp2.isTrue || cmp3.isTrue;
263 var canBeFalse = cmp0.isFalse || cmp1.isFalse || cmp2.isFalse || cmp3.isFalse;
265 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
267 var minBound = canBeFalse ? 0 : 1;
268 var maxBound = canBeTrue ? 1 : 0;
270 return deMath.deInRange32(result, minBound - resErr, maxBound + resErr);
274 * @param {Array<tcuTexCompareVerifier.CmpResultSet>} arr
275 * @param {function(tcuTexCompareVerifier.CmpResultSet): boolean} getValue
276 * @return {number}
278 var getMask = function(arr, getValue) {
279 var mask = 0;
280 for (var i = 0; i < arr.length; i++) {
281 var val = getValue(arr[i]);
282 if (val)
283 mask |= 1 << i;
285 return mask;
289 * @param {tcuTexture.CompareMode} compareMode
290 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
291 * @param {Array<number>} depths vec4
292 * @param {Array<number>} xBounds vec2
293 * @param {Array<number>} yBounds vec2
294 * @param {number} cmpReference
295 * @param {number} result
296 * @param {boolean} isFixedPointDepth
297 * @return {boolean}
299 tcuTexCompareVerifier.isBilinearPCFCompareValid = function(compareMode,
300 prec,
301 depths,
302 xBounds,
303 yBounds,
304 cmpReference,
305 result,
306 isFixedPointDepth) {
307 assertMsgOptions(0.0 <= xBounds[0] && xBounds[0] <= xBounds[1] && xBounds[1] <= 1.0, 'x coordinate out of bounds', false, true);
308 assertMsgOptions(0.0 <= yBounds[0] && yBounds[0] <= yBounds[1] && yBounds[1] <= 1.0, 'y coordinate out of bounds', false, true);
309 assertMsgOptions(prec.pcfBits > 0, 'PCF bits must be > 0', false, true);
311 var d0 = depths[0];
312 var d1 = depths[1];
313 var d2 = depths[2];
314 var d3 = depths[3];
316 /** @type {Array<tcuTexCompareVerifier.CmpResultSet>} */ var cmp = [];
317 cmp[0] = tcuTexCompareVerifier.execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
318 cmp[1] = tcuTexCompareVerifier.execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
319 cmp[2] = tcuTexCompareVerifier.execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
320 cmp[3] = tcuTexCompareVerifier.execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);
322 var isTrue = getMask(cmp, function(x) {return x.isTrue});
323 var isFalse = getMask(cmp, function(x) {return x.isFalse});
325 // Interpolation parameters
326 var x0 = xBounds[0];
327 var x1 = xBounds[1];
328 var y0 = yBounds[0];
329 var y1 = yBounds[1];
331 // Error parameters
332 var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits);
333 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
334 var totalErr = pcfErr + resErr;
336 // Iterate over all valid combinations.
337 // \note It is not enough to compute minmax over all possible result sets, as ranges may
338 // not necessarily overlap, i.e. there are gaps between valid ranges.
339 for (var comb = 0; comb < (1 << 4); comb++) {
340 // Filter out invalid combinations:
341 // 1) True bit is set in comb but not in isTrue => sample can not be true
342 // 2) True bit is NOT set in comb and not in isFalse => sample can not be false
343 if (((comb & isTrue) | (~comb & isFalse)) != (1 << 4) - 1)
344 continue;
346 var cmpTrue = tcuTexCompareVerifier.extractBVec4(comb, 0);
347 var refVal = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue);
349 var v0 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x0, y0);
350 var v1 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x1, y0);
351 var v2 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x0, y1);
352 var v3 = tcuTexCompareVerifier.bilinearInterpolate(refVal, x1, y1);
353 var minV = Math.min(v0, v1, v2, v3);
354 var maxV = Math.max(v0, v1, v2, v3);
355 var minR = minV - totalErr;
356 var maxR = maxV + totalErr;
358 if (deMath.deInRange32(result, minR, maxR))
359 return true;
362 return false;
366 * @param {tcuTexture.CompareMode} compareMode
367 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
368 * @param {Array<number>} depths vec4
369 * @param {Array<number>} xBounds vec2
370 * @param {Array<number>} yBounds vec2
371 * @param {number} cmpReference
372 * @param {number} result
373 * @param {boolean} isFixedPointDepth
374 * @return {boolean}
376 tcuTexCompareVerifier.isBilinearCompareValid = function(compareMode,
377 prec,
378 depths,
379 xBounds,
380 yBounds,
381 cmpReference,
382 result,
383 isFixedPointDepth) {
384 if (prec.pcfBits > 0)
385 return tcuTexCompareVerifier.isBilinearPCFCompareValid(compareMode, prec, depths, xBounds, yBounds, cmpReference, result, isFixedPointDepth);
386 else
387 return tcuTexCompareVerifier.isBilinearAnyCompareValid(compareMode, prec, depths, cmpReference, result, isFixedPointDepth);
390 * @param {tcuTexture.ConstPixelBufferAccess} level
391 * @param {tcuTexture.Sampler} sampler
392 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
393 * @param {Array<number>} coord vec2 texture coordinates
394 * @param {number} coordZ
395 * @param {number} cmpReference
396 * @param {number} result
397 * @return {boolean}
399 tcuTexCompareVerifier.isLinearCompareResultValid = function(level,
400 sampler,
401 prec,
402 coord,
403 coordZ,
404 cmpReference,
405 result) {
406 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level.getFormat());
407 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
408 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
410 // Integer coordinate bounds for (x0,y0) - without wrap mode
411 var minI = Math.floor(uBounds[0] - 0.5);
412 var maxI = Math.floor(uBounds[1] - 0.5);
413 var minJ = Math.floor(vBounds[0] - 0.5);
414 var maxJ = Math.floor(vBounds[1] - 0.5);
416 var w = level.getWidth();
417 var h = level.getHeight();
419 // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
421 for (var j = minJ; j <= maxJ; j++) {
422 for (var i = minI; i <= maxI; i++) {
423 // Wrapped coordinates
424 var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i, w);
425 var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i + 1, w);
426 var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j, h);
427 var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j + 1, h);
429 // Bounds for filtering factors
430 var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
431 var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
432 var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1);
433 var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1);
435 var depths = [
436 level.getPixDepth(x0, y0, coordZ),
437 level.getPixDepth(x1, y0, coordZ),
438 level.getPixDepth(x0, y1, coordZ),
439 level.getPixDepth(x1, y1, coordZ)
442 if (tcuTexCompareVerifier.isBilinearCompareValid(sampler.compare, prec, depths, [minA, maxA], [minB, maxB], cmpReference, result, isFixedPointDepth))
443 return true;
447 return false;
451 * @param {tcuTexCompareVerifier.CmpResultSet} resultSet
452 * @param {number} result
453 * @param {number} resultBits
455 tcuTexCompareVerifier.isResultInSet = function(resultSet, result, resultBits) {
456 var err = tcuTexVerifierUtil.computeFixedPointError(resultBits);
457 var minR = result - err;
458 var maxR = result + err;
460 return (resultSet.isTrue && deMath.deInRange32(1, minR, maxR)) ||
461 (resultSet.isFalse && deMath.deInRange32(0, minR, maxR));
465 * @param {tcuTexture.ConstPixelBufferAccess} level
466 * @param {tcuTexture.Sampler} sampler
467 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
468 * @param {Array<number>} coord vec2 texture coordinates
469 * @param {number} coordZ
470 * @param {number} cmpReference
471 * @param {number} result
472 * @return {boolean}
474 tcuTexCompareVerifier.isNearestCompareResultValid = function(level,
475 sampler,
476 prec,
477 coord,
478 coordZ,
479 cmpReference,
480 result) {
481 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level.getFormat());
482 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord[0], prec.coordBits[0], prec.uvwBits[0]);
483 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord[1], prec.coordBits[1], prec.uvwBits[1]);
485 // Integer coordinates - without wrap mode
486 var minI = Math.floor(uBounds[0]);
487 var maxI = Math.floor(uBounds[1]);
488 var minJ = Math.floor(vBounds[0]);
489 var maxJ = Math.floor(vBounds[1]);
491 for (var j = minJ; j <= maxJ; j++) {
492 for (var i = minI; i <= maxI; i++) {
493 var x = tcuTexVerifierUtil.wrap(sampler.wrapS, i, level.getWidth());
494 var y = tcuTexVerifierUtil.wrap(sampler.wrapT, j, level.getHeight());
495 var depth = level.getPixDepth(x, y, coordZ);
496 var resSet = tcuTexCompareVerifier.execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);
498 if (tcuTexCompareVerifier.isResultInSet(resSet, result, prec.resultBits))
499 return true;
503 return false;
507 * @param {tcuTexture.ConstPixelBufferAccess} level
508 * @param {tcuTexture.Sampler} sampler
509 * @param {tcuTexture.FilterMode} filterMode
510 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
511 * @param {Array<number>} coord vec2 texture coordinates
512 * @param {number} coordZ
513 * @param {number} cmpReference
514 * @param {number} result
515 * @return {boolean}
517 tcuTexCompareVerifier.isLevelCompareResultValid = function(level,
518 sampler,
519 filterMode,
520 prec,
521 coord,
522 coordZ,
523 cmpReference,
524 result) {
525 if (filterMode == tcuTexture.FilterMode.LINEAR)
526 return tcuTexCompareVerifier.isLinearCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
527 else
528 return tcuTexCompareVerifier.isNearestCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
532 * @param {tcuTexture.CompareMode} compareMode
533 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
534 * @param {Array<number>} depths0 vec4
535 * @param {Array<number>} depths1 vec4
536 * @param {number} cmpReference
537 * @param {number} result
538 * @param {boolean} isFixedPointDepth
539 * @return {boolean}
541 tcuTexCompareVerifier.isTrilinearAnyCompareValid = function(compareMode,
542 prec,
543 depths0,
544 depths1,
545 cmpReference,
546 result,
547 isFixedPointDepth) {
548 assertMsgOptions(prec.pcfBits === 0, 'PCF bits must be 0', false, true);
550 var cmp00 = tcuTexCompareVerifier.execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth);
551 var cmp01 = tcuTexCompareVerifier.execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth);
552 var cmp02 = tcuTexCompareVerifier.execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth);
553 var cmp03 = tcuTexCompareVerifier.execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth);
554 var cmp10 = tcuTexCompareVerifier.execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth);
555 var cmp11 = tcuTexCompareVerifier.execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth);
556 var cmp12 = tcuTexCompareVerifier.execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth);
557 var cmp13 = tcuTexCompareVerifier.execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth);
559 var canBeTrue = cmp00.isTrue ||
560 cmp01.isTrue ||
561 cmp02.isTrue ||
562 cmp03.isTrue ||
563 cmp10.isTrue ||
564 cmp11.isTrue ||
565 cmp12.isTrue ||
566 cmp13.isTrue;
567 var canBeFalse = cmp00.isFalse ||
568 cmp01.isFalse ||
569 cmp02.isFalse ||
570 cmp03.isFalse ||
571 cmp10.isFalse ||
572 cmp11.isFalse ||
573 cmp12.isFalse ||
574 cmp13.isFalse;
576 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
578 var minBound = canBeFalse ? 0 : 1;
579 var maxBound = canBeTrue ? 1 : 0;
581 return deMath.deInRange32(result, minBound - resErr, maxBound + resErr);
585 * @param {tcuTexture.CompareMode} compareMode
586 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
587 * @param {Array<number>} depths0 vec4
588 * @param {Array<number>} depths1 vec4
589 * @param {Array<number>} xBounds0
590 * @param {Array<number>} yBounds0
591 * @param {Array<number>} xBounds1
592 * @param {Array<number>} yBounds1
593 * @param {Array<number>} fBounds
594 * @param {number} cmpReference
595 * @param {number} result
596 * @param {boolean} isFixedPointDepth
597 * @return {boolean}
599 tcuTexCompareVerifier.isTrilinearPCFCompareValid = function(compareMode,
600 prec,
601 depths0,
602 depths1,
603 xBounds0,
604 yBounds0,
605 xBounds1,
606 yBounds1,
607 fBounds,
608 cmpReference,
609 result,
610 isFixedPointDepth) {
611 assertMsgOptions(0.0 <= xBounds0[0] && xBounds0[0] <= xBounds0[1] && xBounds0[1] <= 1.0, 'x0 coordinate out of bounds', false, true);
612 assertMsgOptions(0.0 <= yBounds0[0] && yBounds0[0] <= yBounds0[1] && yBounds0[1] <= 1.0, 'y0 coordinate out of bounds', false, true);
613 assertMsgOptions(0.0 <= xBounds1[0] && xBounds1[0] <= xBounds1[1] && xBounds1[1] <= 1.0, 'x1 coordinate out of bounds', false, true);
614 assertMsgOptions(0.0 <= yBounds1[0] && yBounds1[0] <= yBounds1[1] && yBounds1[1] <= 1.0, 'y1 coordinate out of bounds', false, true);
615 assertMsgOptions(0.0 <= fBounds[0] && fBounds[0] <= fBounds[1] && fBounds[1] <= 1.0, 'linear factor out of bounds', false, true);
616 assertMsgOptions(prec.pcfBits > 0, 'PCF bits must be > 0', false, true);
618 /** @type {Array<tcuTexCompareVerifier.CmpResultSet>} */ var cmp = [];
619 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth));
620 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth));
621 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth));
622 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth));
623 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth));
624 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth));
625 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth));
626 cmp.push(tcuTexCompareVerifier.execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth));
628 var isTrue = getMask(cmp, function(x) {return x.isTrue});
629 var isFalse = getMask(cmp, function(x) {return x.isFalse});
631 // Error parameters
632 var pcfErr = tcuTexVerifierUtil.computeFixedPointError(prec.pcfBits);
633 var resErr = tcuTexVerifierUtil.computeFixedPointError(prec.resultBits);
634 var totalErr = pcfErr + resErr;
636 // Iterate over all valid combinations.
637 for (var comb = 0; comb < (1 << 8); comb++) {
638 // Filter out invalid combinations.
639 if (((comb & isTrue) | (~comb & isFalse)) != (1 << 8) - 1)
640 continue;
642 var cmpTrue0 = tcuTexCompareVerifier.extractBVec4(comb, 0);
643 var cmpTrue1 = tcuTexCompareVerifier.extractBVec4(comb, 4);
644 var refVal0 = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue0);
645 var refVal1 = tcuTextureUtil.select([1, 1, 1, 1], [0, 0, 0, 0], cmpTrue1);
647 // Bilinear interpolation within levels.
648 var v00 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[0], yBounds0[0]);
649 var v01 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[1], yBounds0[0]);
650 var v02 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[0], yBounds0[1]);
651 var v03 = tcuTexCompareVerifier.bilinearInterpolate(refVal0, xBounds0[1], yBounds0[1]);
652 var minV0 = Math.min(v00, v01, v02, v03);
653 var maxV0 = Math.max(v00, v01, v02, v03);
655 var v10 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[0], yBounds1[0]);
656 var v11 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[1], yBounds1[0]);
657 var v12 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[0], yBounds1[1]);
658 var v13 = tcuTexCompareVerifier.bilinearInterpolate(refVal1, xBounds1[1], yBounds1[1]);
659 var minV1 = Math.min(v10, v11, v12, v13);
660 var maxV1 = Math.max(v10, v11, v12, v13);
662 // Compute min-max bounds by filtering between minimum bounds and maximum bounds between levels.
663 // HW can end up choosing pretty much any of samples between levels, and thus interpolating
664 // between minimums should yield lower bound for range, and same for upper bound.
665 // \todo [2013-07-17 pyry] This seems separable? Can this be optimized? At least ranges could be pre-computed and later combined.
666 var minF0 = minV0 * (1 - fBounds[0]) + minV1 * fBounds[0];
667 var minF1 = minV0 * (1 - fBounds[1]) + minV1 * fBounds[1];
668 var maxF0 = maxV0 * (1 - fBounds[0]) + maxV1 * fBounds[0];
669 var maxF1 = maxV0 * (1 - fBounds[1]) + maxV1 * fBounds[1];
671 var minF = Math.min(minF0, minF1);
672 var maxF = Math.max(maxF0, maxF1);
674 var minR = minF - totalErr;
675 var maxR = maxF + totalErr;
677 if (deMath.deInRange32(result, minR, maxR))
678 return true;
681 return false;
686 * @param {tcuTexture.CompareMode} compareMode
687 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
688 * @param {Array<number>} depths0 vec4
689 * @param {Array<number>} depths1 vec4
690 * @param {Array<number>} xBounds0
691 * @param {Array<number>} yBounds0
692 * @param {Array<number>} xBounds1
693 * @param {Array<number>} yBounds1
694 * @param {Array<number>} fBounds
695 * @param {number} cmpReference
696 * @param {number} result
697 * @param {boolean} isFixedPointDepth
698 * @return {boolean}
700 tcuTexCompareVerifier.isTrilinearCompareValid = function(compareMode,
701 prec,
702 depths0,
703 depths1,
704 xBounds0,
705 yBounds0,
706 xBounds1,
707 yBounds1,
708 fBounds,
709 cmpReference,
710 result,
711 isFixedPointDepth) {
712 if (prec.pcfBits > 0)
713 return tcuTexCompareVerifier.isTrilinearPCFCompareValid(compareMode, prec, depths0, depths1, xBounds0, yBounds0, xBounds1, yBounds1, fBounds, cmpReference, result, isFixedPointDepth);
714 else
715 return tcuTexCompareVerifier.isTrilinearAnyCompareValid(compareMode, prec, depths0, depths1, cmpReference, result, isFixedPointDepth);
719 * @param {tcuTexture.ConstPixelBufferAccess} level0
720 * @param {tcuTexture.ConstPixelBufferAccess} level1
721 * @param {tcuTexture.Sampler} sampler
722 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
723 * @param {Array<number>} coord vec2 texture coordinates
724 * @param {number} coordZ
725 * @param {Array<number>} fBounds vec2
726 * @param {number} cmpReference
727 * @param {number} result
728 * @return {boolean}
730 tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid = function(level0,
731 level1,
732 sampler,
733 prec,
734 coord,
735 coordZ,
736 fBounds,
737 cmpReference,
738 result) {
739 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level0.getFormat());
741 // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
742 // Right now this allows pairing any two valid bilinear quads.
744 var w0 = level0.getWidth();
745 var w1 = level1.getWidth();
746 var h0 = level0.getHeight();
747 var h1 = level1.getHeight();
749 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
750 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
751 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
752 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
754 // Integer coordinates - without wrap mode
755 var minI0 = Math.floor(uBounds0[0] - 0.5);
756 var maxI0 = Math.floor(uBounds0[1] - 0.5);
757 var minI1 = Math.floor(uBounds1[0] - 0.5);
758 var maxI1 = Math.floor(uBounds1[1] - 0.5);
759 var minJ0 = Math.floor(vBounds0[0] - 0.5);
760 var maxJ0 = Math.floor(vBounds0[1] - 0.5);
761 var minJ1 = Math.floor(vBounds1[0] - 0.5);
762 var maxJ1 = Math.floor(vBounds1[1] - 0.5);
764 for (var j0 = minJ0; j0 <= maxJ0; j0++) {
765 for (var i0 = minI0; i0 <= maxI0; i0++) {
766 var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1);
767 var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1);
768 var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1);
769 var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1);
770 var depths0 = [];
772 var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0);
773 var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0 + 1, w0);
774 var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0);
775 var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0 + 1, h0);
777 depths0[0] = level0.getPixDepth(x0, y0, coordZ);
778 depths0[1] = level0.getPixDepth(x1, y0, coordZ);
779 depths0[2] = level0.getPixDepth(x0, y1, coordZ);
780 depths0[3] = level0.getPixDepth(x1, y1, coordZ);
782 for (var j1 = minJ1; j1 <= maxJ1; j1++) {
783 for (var i1 = minI1; i1 <= maxI1; i1++) {
784 var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1);
785 var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1);
786 var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1);
787 var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1);
788 var depths1 = [];
790 x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1);
791 x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1 + 1, w1);
792 y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1);
793 y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1 + 1, h1);
795 depths1[0] = level1.getPixDepth(x0, y0, coordZ);
796 depths1[1] = level1.getPixDepth(x1, y0, coordZ);
797 depths1[2] = level1.getPixDepth(x0, y1, coordZ);
798 depths1[3] = level1.getPixDepth(x1, y1, coordZ);
800 if (tcuTexCompareVerifier.isTrilinearCompareValid(sampler.compare, prec, depths0, depths1,
801 [minA0, maxA0], [minB0, maxB0],
802 [minA1, maxA1], [minB1, maxB1],
803 fBounds, cmpReference, result, isFixedPointDepth))
804 return true;
810 return false;
814 * @param {tcuTexture.ConstPixelBufferAccess} level0
815 * @param {tcuTexture.ConstPixelBufferAccess} level1
816 * @param {tcuTexture.Sampler} sampler
817 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
818 * @param {Array<number>} coord vec2 texture coordinates
819 * @param {number} coordZ
820 * @param {Array<number>} fBounds vec2
821 * @param {number} cmpReference
822 * @param {number} result
823 * @return {boolean}
825 tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid = function(level0,
826 level1,
827 sampler,
828 prec,
829 coord,
830 coordZ,
831 fBounds,
832 cmpReference,
833 result) {
834 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(level0.getFormat());
836 var w0 = level0.getWidth();
837 var w1 = level1.getWidth();
838 var h0 = level0.getHeight();
839 var h1 = level1.getHeight();
841 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord[0], prec.coordBits[0], prec.uvwBits[0]);
842 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord[0], prec.coordBits[0], prec.uvwBits[0]);
843 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord[1], prec.coordBits[1], prec.uvwBits[1]);
844 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord[1], prec.coordBits[1], prec.uvwBits[1]);
846 var minI0 = Math.floor(uBounds0[0]);
847 var maxI0 = Math.floor(uBounds0[1]);
848 var minI1 = Math.floor(uBounds1[0]);
849 var maxI1 = Math.floor(uBounds1[1]);
850 var minJ0 = Math.floor(vBounds0[0]);
851 var maxJ0 = Math.floor(vBounds0[1]);
852 var minJ1 = Math.floor(vBounds1[0]);
853 var maxJ1 = Math.floor(vBounds1[1]);
855 for (var j0 = minJ0; j0 <= maxJ0; j0++) {
856 for (var i0 = minI0; i0 <= maxI0; i0++) {
857 var x0 = tcuTexVerifierUtil.wrap(sampler.wrapS, i0, w0);
858 var y0 = tcuTexVerifierUtil.wrap(sampler.wrapT, j0, h0);
860 // Derivated from C++ dEQP function lookupDepth()
861 // Since x0 and y0 are wrapped, here lookupDepth() returns the same result as getPixDepth()
862 assertMsgOptions(deMath.deInBounds32(x0, 0, level0.getWidth()) && deMath.deInBounds32(y0, 0, level0.getHeight()) && deMath.deInBounds32(coordZ, 0, level0.getDepth()), 'x0, y0 or coordZ out of bound.', false, true);
863 var depth0 = level0.getPixDepth(x0, y0, coordZ);
865 for (var j1 = minJ1; j1 <= maxJ1; j1++) {
866 for (var i1 = minI1; i1 <= maxI1; i1++) {
867 var x1 = tcuTexVerifierUtil.wrap(sampler.wrapS, i1, w1);
868 var y1 = tcuTexVerifierUtil.wrap(sampler.wrapT, j1, h1);
870 // Derivated from C++ dEQP function lookupDepth()
871 // Since x1 and y1 are wrapped, here lookupDepth() returns the same result as getPixDepth()
872 assertMsgOptions(deMath.deInBounds32(x1, 0, level1.getWidth()) && deMath.deInBounds32(y1, 0, level1.getHeight()), 'x1 or y1 out of bound.', false, true);
873 var depth1 = level1.getPixDepth(x1, y1, coordZ);
875 if (tcuTexCompareVerifier.isLinearCompareValid(sampler.compare, prec, [depth0, depth1], fBounds, cmpReference, result, isFixedPointDepth))
876 return true;
882 return false;
886 * @param {tcuTexture.ConstPixelBufferAccess} level0
887 * @param {tcuTexture.ConstPixelBufferAccess} level1
888 * @param {tcuTexture.Sampler} sampler
889 * @param {tcuTexture.FilterMode} levelFilter
890 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
891 * @param {Array<number>} coord vec2 texture coordinates
892 * @param {number} coordZ
893 * @param {Array<number>} fBounds vec2
894 * @param {number} cmpReference
895 * @param {number} result
896 * @return {boolean}
898 tcuTexCompareVerifier.isMipmapLinearCompareResultValid = function(level0,
899 level1,
900 sampler,
901 levelFilter,
902 prec,
903 coord,
904 coordZ,
905 fBounds,
906 cmpReference,
907 result) {
908 if (levelFilter == tcuTexture.FilterMode.LINEAR)
909 return tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result);
910 else
911 return tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result);
915 * @param {tcuTexture.Texture2DView} texture
916 * @param {tcuTexture.Sampler} sampler
917 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
918 * @param {Array<number>} coord vec2 texture coordinates
919 * @param {Array<number>} lodBounds vec2 level-of-detail bounds
920 * @param {number} cmpReference
921 * @param {number} result
922 * @return {boolean}
924 tcuTexCompareVerifier.isTexCompareResultValid2D = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) {
925 var minLod = lodBounds[0];
926 var maxLod = lodBounds[1];
927 var canBeMagnified = minLod <= sampler.lodThreshold;
928 var canBeMinified = maxLod > sampler.lodThreshold;
930 if (canBeMagnified) {
931 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, cmpReference, result))
932 return true;
935 if (canBeMinified) {
936 var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
937 var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
938 var minTexLevel = 0;
939 var maxTexLevel = texture.getNumLevels() - 1;
941 assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true);
943 if (isLinearMipmap) {
944 var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
945 var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
947 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
949 for (var level = minLevel; level <= maxLevel; level++) {
950 var minF = deMath.clamp(minLod - level, 0, 1);
951 var maxF = deMath.clamp(maxLod - level, 0, 1);
953 if (tcuTexCompareVerifier.isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, [minF, maxF], cmpReference, result))
954 return true;
956 } else if (isNearestMipmap) {
957 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
958 // decision to allow floor(lod + 0.5) as well.
959 var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
960 var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
962 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
964 for (var level = minLevel; level <= maxLevel; level++) {
965 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, coord, 0, cmpReference, result))
966 return true;
968 } else {
969 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, cmpReference, result))
970 return true;
974 return false;
978 * @param {tcuTexture.TextureCubeView} texture
979 * @param {number} baseLevelNdx
980 * @param {tcuTexture.Sampler} sampler
981 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
982 * @param {tcuTexture.CubeFaceCoords} coords
983 * @param {Array<number>} fBounds vec2
984 * @param {number} cmpReference
985 * @param {number} result
986 * @return {boolean}
988 tcuTexCompareVerifier.isSeamplessLinearMipmapLinearCompareResultValid = function(texture,
989 baseLevelNdx,
990 sampler,
991 prec,
992 coords,
993 fBounds,
994 cmpReference,
995 result) {
996 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(texture.getLevelFace(baseLevelNdx, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X).getFormat());
997 var size0 = texture.getLevelFace(baseLevelNdx, coords.face).getWidth();
998 var size1 = texture.getLevelFace(baseLevelNdx + 1, coords.face).getWidth();
1000 var uBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.s, prec.coordBits[0], prec.uvwBits[0]);
1001 var uBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.s, prec.coordBits[0], prec.uvwBits[0]);
1002 var vBounds0 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.t, prec.coordBits[1], prec.uvwBits[1]);
1003 var vBounds1 = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.t, prec.coordBits[1], prec.uvwBits[1]);
1005 // Integer coordinates - without wrap mode
1006 var minI0 = Math.floor(uBounds0[0] - 0.5);
1007 var maxI0 = Math.floor(uBounds0[1] - 0.5);
1008 var minI1 = Math.floor(uBounds1[0] - 0.5);
1009 var maxI1 = Math.floor(uBounds1[1] - 0.5);
1010 var minJ0 = Math.floor(vBounds0[0] - 0.5);
1011 var maxJ0 = Math.floor(vBounds0[1] - 0.5);
1012 var minJ1 = Math.floor(vBounds1[0] - 0.5);
1013 var maxJ1 = Math.floor(vBounds1[1] - 0.5);
1015 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces0 = [];
1016 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces1 = [];
1018 for (var key in tcuTexture.CubeFace) {
1019 var face = tcuTexture.CubeFace[key];
1020 faces0[face] = texture.getLevelFace(baseLevelNdx, face);
1021 faces1[face] = texture.getLevelFace(baseLevelNdx + 1, face);
1024 for (var j0 = minJ0; j0 <= maxJ0; j0++) {
1025 for (var i0 = minI0; i0 <= maxI0; i0++) {
1026 var minA0 = deMath.clamp((uBounds0[0] - 0.5) - i0, 0, 1);
1027 var maxA0 = deMath.clamp((uBounds0[1] - 0.5) - i0, 0, 1);
1028 var minB0 = deMath.clamp((vBounds0[0] - 0.5) - j0, 0, 1);
1029 var maxB0 = deMath.clamp((vBounds0[1] - 0.5) - j0, 0, 1);
1030 var depths0 = [];
1032 var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 0]), size0);
1033 var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 0]), size0);
1034 var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 0, j0 + 1]), size0);
1035 var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i0 + 1, j0 + 1]), size0);
1037 // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
1038 // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
1039 if (c00 == null || c01 == null || c10 == null || c11 == null)
1040 return true;
1042 depths0[0] = faces0[c00.face].getPixDepth(c00.s, c00.t);
1043 depths0[1] = faces0[c10.face].getPixDepth(c10.s, c10.t);
1044 depths0[2] = faces0[c01.face].getPixDepth(c01.s, c01.t);
1045 depths0[3] = faces0[c11.face].getPixDepth(c11.s, c11.t);
1047 for (var j1 = minJ1; j1 <= maxJ1; j1++) {
1048 for (var i1 = minI1; i1 <= maxI1; i1++) {
1049 var minA1 = deMath.clamp((uBounds1[0] - 0.5) - i1, 0, 1);
1050 var maxA1 = deMath.clamp((uBounds1[1] - 0.5) - i1, 0, 1);
1051 var minB1 = deMath.clamp((vBounds1[0] - 0.5) - j1, 0, 1);
1052 var maxB1 = deMath.clamp((vBounds1[1] - 0.5) - j1, 0, 1);
1053 var depths1 = [];
1055 c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 0]), size1);
1056 c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 0]), size1);
1057 c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 0, j1 + 1]), size1);
1058 c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i1 + 1, j1 + 1]), size1);
1060 if (c00 == null || c01 == null || c10 == null || c11 == null)
1061 return true;
1063 depths1[0] = faces1[c00.face].getPixDepth(c00.s, c00.t);
1064 depths1[1] = faces1[c10.face].getPixDepth(c10.s, c10.t);
1065 depths1[2] = faces1[c01.face].getPixDepth(c01.s, c01.t);
1066 depths1[3] = faces1[c11.face].getPixDepth(c11.s, c11.t);
1068 if (tcuTexCompareVerifier.isTrilinearCompareValid(sampler.compare, prec, depths0, depths1,
1069 [minA0, maxA0], [minB0, maxB0],
1070 [minA1, maxA1], [minB1, maxB1],
1071 fBounds, cmpReference, result, isFixedPointDepth))
1072 return true;
1078 return false;
1082 * @param {tcuTexture.TextureCubeView} texture
1083 * @param {number} levelNdx
1084 * @param {tcuTexture.Sampler} sampler
1085 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
1086 * @param {tcuTexture.CubeFaceCoords} coords
1087 * @param {number} cmpReference
1088 * @param {number} result
1089 * @return {boolean}
1092 tcuTexCompareVerifier.isSeamlessLinearCompareResultValid = function(texture,
1093 levelNdx,
1094 sampler,
1095 prec,
1096 coords,
1097 cmpReference,
1098 result) {
1099 var isFixedPointDepth = tcuTexCompareVerifier.isFixedPointDepthTextureFormat(texture.getLevelFace(levelNdx, tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X).getFormat());
1100 var size = texture.getLevelFace(levelNdx, coords.face).getWidth();
1102 var uBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits[0], prec.uvwBits[0]);
1103 var vBounds = tcuTexVerifierUtil.computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits[1], prec.uvwBits[1]);
1105 // Integer coordinate bounds for (x0,y0) - without wrap mode
1106 var minI = Math.floor(uBounds[0] - 0.5);
1107 var maxI = Math.floor(uBounds[1] - 0.5);
1108 var minJ = Math.floor(vBounds[0] - 0.5);
1109 var maxJ = Math.floor(vBounds[1] - 0.5);
1111 // Face accesses
1112 /** @type {Array<tcuTexture.ConstPixelBufferAccess>} */ var faces = [];
1114 for (var key in tcuTexture.CubeFace) {
1115 var face = tcuTexture.CubeFace[key];
1116 faces[face] = texture.getLevelFace(levelNdx, face);
1119 for (var j = minJ; j <= maxJ; j++) {
1120 for (var i = minI; i <= maxI; i++) {
1121 var c00 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 0]), size);
1122 var c10 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 0]), size);
1123 var c01 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 0, j + 1]), size);
1124 var c11 = tcuTexture.remapCubeEdgeCoords(new tcuTexture.CubeFaceCoords(coords.face, [i + 1, j + 1]), size);
1126 // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
1127 // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
1128 if (!c00 || !c01 || !c10 || !c11)
1129 return true;
1131 // Bounds for filtering factors
1132 var minA = deMath.clamp((uBounds[0] - 0.5) - i, 0, 1);
1133 var maxA = deMath.clamp((uBounds[1] - 0.5) - i, 0, 1);
1134 var minB = deMath.clamp((vBounds[0] - 0.5) - j, 0, 1);
1135 var maxB = deMath.clamp((vBounds[1] - 0.5) - j, 0, 1);
1137 var depths = [];
1138 depths[0] = faces[c00.face].getPixDepth(c00.s, c00.t);
1139 depths[1] = faces[c10.face].getPixDepth(c10.s, c10.t);
1140 depths[2] = faces[c01.face].getPixDepth(c01.s, c01.t);
1141 depths[3] = faces[c11.face].getPixDepth(c11.s, c11.t);
1143 if (tcuTexCompareVerifier.isBilinearCompareValid(sampler.compare, prec, depths, [minA, maxA], [minB, maxB], cmpReference, result, isFixedPointDepth))
1144 return true;
1148 return false;
1152 * @param {tcuTexture.TextureCubeView} texture
1153 * @param {number} levelNdx
1154 * @param {tcuTexture.Sampler} sampler
1155 * @param {tcuTexture.FilterMode} filterMode
1156 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
1157 * @param {tcuTexture.CubeFaceCoords} coords
1158 * @param {number} cmpReference
1159 * @param {number} result
1160 * @return {boolean}
1162 tcuTexCompareVerifier.isCubeLevelCompareResultValid = function(texture,
1163 levelNdx,
1164 sampler,
1165 filterMode,
1166 prec,
1167 coords,
1168 cmpReference,
1169 result) {
1170 if (filterMode == tcuTexture.FilterMode.LINEAR) {
1171 if (sampler.seamlessCubeMap)
1172 return tcuTexCompareVerifier.isSeamlessLinearCompareResultValid(texture, levelNdx, sampler, prec, coords, cmpReference, result);
1173 else
1174 return tcuTexCompareVerifier.isLinearCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, [coords.s, coords.t], 0, cmpReference, result);
1175 } else
1176 return tcuTexCompareVerifier.isNearestCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, [coords.s, coords.t], 0, cmpReference, result);
1180 * @param {tcuTexture.TextureCubeView} texture
1181 * @param {number} baseLevelNdx
1182 * @param {tcuTexture.Sampler} sampler
1183 * @param {tcuTexture.FilterMode} levelFilter
1184 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
1185 * @param {tcuTexture.CubeFaceCoords} coords
1186 * @param {Array<number>} fBounds vec2
1187 * @param {number} cmpReference
1188 * @param {number} result
1189 * @return {boolean}
1191 tcuTexCompareVerifier.isCubeMipmapLinearCompareResultValid = function(texture,
1192 baseLevelNdx,
1193 sampler,
1194 levelFilter,
1195 prec,
1196 coords,
1197 fBounds,
1198 cmpReference,
1199 result) {
1200 if (levelFilter == tcuTexture.FilterMode.LINEAR) {
1201 if (sampler.seamlessCubeMap)
1202 return tcuTexCompareVerifier.isSeamplessLinearMipmapLinearCompareResultValid(texture, baseLevelNdx, sampler, prec, coords, fBounds, cmpReference, result);
1203 else
1204 return tcuTexCompareVerifier.isLinearMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx, coords.face),
1205 texture.getLevelFace(baseLevelNdx + 1, coords.face),
1206 sampler, prec, [coords.s, coords.t], 0, fBounds, cmpReference, result);
1207 } else
1208 return tcuTexCompareVerifier.isNearestMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx, coords.face),
1209 texture.getLevelFace(baseLevelNdx + 1, coords.face),
1210 sampler, prec, [coords.s, coords.t], 0, fBounds, cmpReference, result);
1214 * @param {tcuTexture.TextureCubeView} texture
1215 * @param {tcuTexture.Sampler} sampler
1216 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
1217 * @param {Array<number>} coord vec2 texture coordinates
1218 * @param {Array<number>} lodBounds vec2 level-of-detail bounds
1219 * @param {number} cmpReference
1220 * @param {number} result
1221 * @return {boolean}
1223 tcuTexCompareVerifier.isTexCompareResultValidCube = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) {
1224 /** @type {Array<tcuTexture.CubeFace>} */var possibleFaces = tcuTexVerifierUtil.getPossibleCubeFaces(coord, prec.coordBits);
1226 if (!possibleFaces)
1227 return true; // Result is undefined.
1229 for (var tryFaceNdx = 0; tryFaceNdx < possibleFaces.length; tryFaceNdx++) {
1230 var face = possibleFaces[tryFaceNdx];
1231 var faceCoords = new tcuTexture.CubeFaceCoords(face, tcuTexture.projectToFace(face, coord));
1232 var minLod = lodBounds[0];
1233 var maxLod = lodBounds[1];
1234 var canBeMagnified = minLod <= sampler.lodThreshold;
1235 var canBeMinified = maxLod > sampler.lodThreshold;
1237 if (canBeMagnified) {
1238 if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, 0, sampler, sampler.magFilter, prec, faceCoords, cmpReference, result))
1239 return true;
1242 if (canBeMinified) {
1243 var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
1244 var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
1245 var minTexLevel = 0;
1246 var maxTexLevel = texture.getNumLevels() - 1;
1248 assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true);
1250 if (isLinearMipmap) {
1251 var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
1252 var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
1254 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
1256 for (var level = minLevel; level <= maxLevel; level++) {
1257 var minF = deMath.clamp(minLod - level, 0, 1);
1258 var maxF = deMath.clamp(maxLod - level, 0, 1);
1260 if (tcuTexCompareVerifier.isCubeMipmapLinearCompareResultValid(texture, level, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, [minF, maxF], cmpReference, result))
1261 return true;
1263 } else if (isNearestMipmap) {
1264 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1265 // decision to allow floor(lod + 0.5) as well.
1266 var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
1267 var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
1269 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
1271 for (var level = minLevel; level <= maxLevel; level++) {
1272 if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, level, sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, faceCoords, cmpReference, result))
1273 return true;
1275 } else {
1276 if (tcuTexCompareVerifier.isCubeLevelCompareResultValid(texture, 0, sampler, sampler.minFilter, prec, faceCoords, cmpReference, result))
1277 return true;
1282 return false;
1286 * @param {tcuTexture.Texture2DArrayView} texture
1287 * @param {tcuTexture.Sampler} sampler
1288 * @param {tcuTexCompareVerifier.TexComparePrecision} prec
1289 * @param {Array<number>} coord vec3 texture coordinates
1290 * @param {Array<number>} lodBounds vec2 level-of-detail bounds
1291 * @param {number} cmpReference
1292 * @param {number} result
1293 * @return {boolean}
1295 tcuTexCompareVerifier.isTexCompareResultValid2DArray = function(texture, sampler, prec, coord, lodBounds, cmpReference, result) {
1296 var depthErr = tcuTexVerifierUtil.computeFloatingPointError(coord[2], prec.coordBits[2]) + tcuTexVerifierUtil.computeFixedPointError(prec.uvwBits[2]);
1297 var minZ = coord[2] - depthErr;
1298 var maxZ = coord[2] + depthErr;
1299 var minLayer = deMath.clamp(Math.floor(minZ + 0.5), 0, texture.getNumLayers() - 1);
1300 var maxLayer = deMath.clamp(Math.floor(maxZ + 0.5), 0, texture.getNumLayers() - 1);
1302 for (var layer = minLayer; layer <= maxLayer; layer++) {
1303 var minLod = lodBounds[0];
1304 var maxLod = lodBounds[1];
1305 var canBeMagnified = minLod <= sampler.lodThreshold;
1306 var canBeMinified = maxLod > sampler.lodThreshold;
1308 if (canBeMagnified) {
1309 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result))
1310 return true;
1313 if (canBeMinified) {
1314 var isNearestMipmap = tcuTexVerifierUtil.isNearestMipmapFilter(sampler.minFilter);
1315 var isLinearMipmap = tcuTexVerifierUtil.isLinearMipmapFilter(sampler.minFilter);
1316 var minTexLevel = 0;
1317 var maxTexLevel = texture.getNumLevels() - 1;
1319 assertMsgOptions(minTexLevel < maxTexLevel, 'Invalid texture levels.', false, true);
1321 if (isLinearMipmap) {
1322 var minLevel = deMath.clamp(Math.floor(minLod), minTexLevel, maxTexLevel - 1);
1323 var maxLevel = deMath.clamp(Math.floor(maxLod), minTexLevel, maxTexLevel - 1);
1325 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
1327 for (var level = minLevel; level <= maxLevel; level++) {
1328 var minF = deMath.clamp(minLod - level, 0, 1);
1329 var maxF = deMath.clamp(maxLod - level, 0, 1);
1331 if (tcuTexCompareVerifier.isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, deMath.swizzle(coord, [0, 1]), layer, [minF, maxF], cmpReference, result))
1332 return true;
1334 } else if (isNearestMipmap) {
1335 // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1336 // decision to allow floor(lod + 0.5) as well.
1337 var minLevel = deMath.clamp(Math.ceil(minLod + 0.5) - 1, minTexLevel, maxTexLevel);
1338 var maxLevel = deMath.clamp(Math.floor(maxLod + 0.5), minTexLevel, maxTexLevel);
1340 assertMsgOptions(minLevel <= maxLevel, 'Invalid texture levels.', false, true);
1342 for (var level = minLevel; level <= maxLevel; level++) {
1343 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(level), sampler, tcuTexVerifierUtil.getLevelFilter(sampler.minFilter), prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result))
1344 return true;
1346 } else {
1347 if (tcuTexCompareVerifier.isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, deMath.swizzle(coord, [0, 1]), layer, cmpReference, result))
1348 return true;
1353 return false;