1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program Tester Core
3*35238bceSAndroid Build Coastguard Worker * ----------------------------------------
4*35238bceSAndroid Build Coastguard Worker *
5*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker *
11*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker *
19*35238bceSAndroid Build Coastguard Worker *//*!
20*35238bceSAndroid Build Coastguard Worker * \file
21*35238bceSAndroid Build Coastguard Worker * \brief Texture compare (shadow) result verifier.
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "tcuTexCompareVerifier.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuTexVerifierUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
29*35238bceSAndroid Build Coastguard Worker
30*35238bceSAndroid Build Coastguard Worker namespace tcu
31*35238bceSAndroid Build Coastguard Worker {
32*35238bceSAndroid Build Coastguard Worker
33*35238bceSAndroid Build Coastguard Worker using namespace TexVerifierUtil;
34*35238bceSAndroid Build Coastguard Worker
35*35238bceSAndroid Build Coastguard Worker // Generic utilities
36*35238bceSAndroid Build Coastguard Worker
37*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
isSamplerSupported(const Sampler & sampler)38*35238bceSAndroid Build Coastguard Worker static bool isSamplerSupported(const Sampler &sampler)
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker return sampler.compare != Sampler::COMPAREMODE_NONE && isWrapModeSupported(sampler.wrapS) &&
41*35238bceSAndroid Build Coastguard Worker isWrapModeSupported(sampler.wrapT) && isWrapModeSupported(sampler.wrapR);
42*35238bceSAndroid Build Coastguard Worker }
43*35238bceSAndroid Build Coastguard Worker #endif // DE_DEBUG
44*35238bceSAndroid Build Coastguard Worker
45*35238bceSAndroid Build Coastguard Worker struct CmpResultSet
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker bool isTrue;
48*35238bceSAndroid Build Coastguard Worker bool isFalse;
49*35238bceSAndroid Build Coastguard Worker
CmpResultSettcu::CmpResultSet50*35238bceSAndroid Build Coastguard Worker CmpResultSet(void) : isTrue(false), isFalse(false)
51*35238bceSAndroid Build Coastguard Worker {
52*35238bceSAndroid Build Coastguard Worker }
53*35238bceSAndroid Build Coastguard Worker };
54*35238bceSAndroid Build Coastguard Worker
execCompare(const Sampler::CompareMode compareMode,const float cmpValue_,const float cmpReference_,const int referenceBits,const bool isFixedPoint)55*35238bceSAndroid Build Coastguard Worker static CmpResultSet execCompare(const Sampler::CompareMode compareMode, const float cmpValue_,
56*35238bceSAndroid Build Coastguard Worker const float cmpReference_, const int referenceBits, const bool isFixedPoint)
57*35238bceSAndroid Build Coastguard Worker {
58*35238bceSAndroid Build Coastguard Worker const bool clampValues =
59*35238bceSAndroid Build Coastguard Worker isFixedPoint; // if comparing against a floating point texture, ref (and value) is not clamped
60*35238bceSAndroid Build Coastguard Worker const float cmpValue = (clampValues) ? (de::clamp(cmpValue_, 0.0f, 1.0f)) : (cmpValue_);
61*35238bceSAndroid Build Coastguard Worker const float cmpReference = (clampValues) ? (de::clamp(cmpReference_, 0.0f, 1.0f)) : (cmpReference_);
62*35238bceSAndroid Build Coastguard Worker const float err = computeFixedPointError(referenceBits);
63*35238bceSAndroid Build Coastguard Worker CmpResultSet res;
64*35238bceSAndroid Build Coastguard Worker
65*35238bceSAndroid Build Coastguard Worker switch (compareMode)
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_LESS:
68*35238bceSAndroid Build Coastguard Worker res.isTrue = cmpReference - err < cmpValue;
69*35238bceSAndroid Build Coastguard Worker res.isFalse = cmpReference + err >= cmpValue;
70*35238bceSAndroid Build Coastguard Worker break;
71*35238bceSAndroid Build Coastguard Worker
72*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_LESS_OR_EQUAL:
73*35238bceSAndroid Build Coastguard Worker res.isTrue = cmpReference - err <= cmpValue;
74*35238bceSAndroid Build Coastguard Worker res.isFalse = cmpReference + err > cmpValue;
75*35238bceSAndroid Build Coastguard Worker break;
76*35238bceSAndroid Build Coastguard Worker
77*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_GREATER:
78*35238bceSAndroid Build Coastguard Worker res.isTrue = cmpReference + err > cmpValue;
79*35238bceSAndroid Build Coastguard Worker res.isFalse = cmpReference - err <= cmpValue;
80*35238bceSAndroid Build Coastguard Worker break;
81*35238bceSAndroid Build Coastguard Worker
82*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_GREATER_OR_EQUAL:
83*35238bceSAndroid Build Coastguard Worker res.isTrue = cmpReference + err >= cmpValue;
84*35238bceSAndroid Build Coastguard Worker res.isFalse = cmpReference - err < cmpValue;
85*35238bceSAndroid Build Coastguard Worker break;
86*35238bceSAndroid Build Coastguard Worker
87*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_EQUAL:
88*35238bceSAndroid Build Coastguard Worker res.isTrue = de::inRange(cmpValue, cmpReference - err, cmpReference + err);
89*35238bceSAndroid Build Coastguard Worker res.isFalse = err != 0.0f || cmpValue != cmpReference;
90*35238bceSAndroid Build Coastguard Worker break;
91*35238bceSAndroid Build Coastguard Worker
92*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_NOT_EQUAL:
93*35238bceSAndroid Build Coastguard Worker res.isTrue = err != 0.0f || cmpValue != cmpReference;
94*35238bceSAndroid Build Coastguard Worker res.isFalse = de::inRange(cmpValue, cmpReference - err, cmpReference + err);
95*35238bceSAndroid Build Coastguard Worker break;
96*35238bceSAndroid Build Coastguard Worker
97*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_ALWAYS:
98*35238bceSAndroid Build Coastguard Worker res.isTrue = true;
99*35238bceSAndroid Build Coastguard Worker break;
100*35238bceSAndroid Build Coastguard Worker
101*35238bceSAndroid Build Coastguard Worker case Sampler::COMPAREMODE_NEVER:
102*35238bceSAndroid Build Coastguard Worker res.isFalse = true;
103*35238bceSAndroid Build Coastguard Worker break;
104*35238bceSAndroid Build Coastguard Worker
105*35238bceSAndroid Build Coastguard Worker default:
106*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
107*35238bceSAndroid Build Coastguard Worker }
108*35238bceSAndroid Build Coastguard Worker
109*35238bceSAndroid Build Coastguard Worker DE_ASSERT(res.isTrue || res.isFalse);
110*35238bceSAndroid Build Coastguard Worker return res;
111*35238bceSAndroid Build Coastguard Worker }
112*35238bceSAndroid Build Coastguard Worker
isResultInSet(const CmpResultSet resultSet,const float result,const int resultBits)113*35238bceSAndroid Build Coastguard Worker static inline bool isResultInSet(const CmpResultSet resultSet, const float result, const int resultBits)
114*35238bceSAndroid Build Coastguard Worker {
115*35238bceSAndroid Build Coastguard Worker const float err = computeFixedPointError(resultBits);
116*35238bceSAndroid Build Coastguard Worker const float minR = result - err;
117*35238bceSAndroid Build Coastguard Worker const float maxR = result + err;
118*35238bceSAndroid Build Coastguard Worker
119*35238bceSAndroid Build Coastguard Worker return (resultSet.isTrue && de::inRange(1.0f, minR, maxR)) || (resultSet.isFalse && de::inRange(0.0f, minR, maxR));
120*35238bceSAndroid Build Coastguard Worker }
121*35238bceSAndroid Build Coastguard Worker
coordsInBounds(const ConstPixelBufferAccess & access,int x,int y,int z)122*35238bceSAndroid Build Coastguard Worker static inline bool coordsInBounds(const ConstPixelBufferAccess &access, int x, int y, int z)
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker return de::inBounds(x, 0, access.getWidth()) && de::inBounds(y, 0, access.getHeight()) &&
125*35238bceSAndroid Build Coastguard Worker de::inBounds(z, 0, access.getDepth());
126*35238bceSAndroid Build Coastguard Worker }
127*35238bceSAndroid Build Coastguard Worker
128*35238bceSAndroid Build Coastguard Worker // lookup depth value at a point that is guaranteed to not sample border such as cube map faces.
lookupDepthNoBorder(const tcu::ConstPixelBufferAccess & access,const Sampler & sampler,int i,int j,int k=0)129*35238bceSAndroid Build Coastguard Worker static float lookupDepthNoBorder(const tcu::ConstPixelBufferAccess &access, const Sampler &sampler, int i, int j,
130*35238bceSAndroid Build Coastguard Worker int k = 0)
131*35238bceSAndroid Build Coastguard Worker {
132*35238bceSAndroid Build Coastguard Worker DE_UNREF(sampler);
133*35238bceSAndroid Build Coastguard Worker DE_ASSERT(coordsInBounds(access, i, j, k));
134*35238bceSAndroid Build Coastguard Worker DE_ASSERT(access.getFormat().order == TextureFormat::D || access.getFormat().order == TextureFormat::DS ||
135*35238bceSAndroid Build Coastguard Worker access.getFormat().order == TextureFormat::R);
136*35238bceSAndroid Build Coastguard Worker
137*35238bceSAndroid Build Coastguard Worker if (access.getFormat().order == TextureFormat::R)
138*35238bceSAndroid Build Coastguard Worker return access.getPixel(i, j, k).x();
139*35238bceSAndroid Build Coastguard Worker else
140*35238bceSAndroid Build Coastguard Worker return access.getPixDepth(i, j, k);
141*35238bceSAndroid Build Coastguard Worker }
142*35238bceSAndroid Build Coastguard Worker
lookupDepth(const tcu::ConstPixelBufferAccess & access,const Sampler & sampler,int i,int j,int k)143*35238bceSAndroid Build Coastguard Worker static float lookupDepth(const tcu::ConstPixelBufferAccess &access, const Sampler &sampler, int i, int j, int k)
144*35238bceSAndroid Build Coastguard Worker {
145*35238bceSAndroid Build Coastguard Worker if (coordsInBounds(access, i, j, k))
146*35238bceSAndroid Build Coastguard Worker return lookupDepthNoBorder(access, sampler, i, j, k);
147*35238bceSAndroid Build Coastguard Worker else
148*35238bceSAndroid Build Coastguard Worker return sampleTextureBorder<float>(access.getFormat(), sampler).x();
149*35238bceSAndroid Build Coastguard Worker }
150*35238bceSAndroid Build Coastguard Worker
151*35238bceSAndroid Build Coastguard Worker // Values are in order (0,0), (1,0), (0,1), (1,1)
bilinearInterpolate(const Vec4 & values,const float x,const float y)152*35238bceSAndroid Build Coastguard Worker static float bilinearInterpolate(const Vec4 &values, const float x, const float y)
153*35238bceSAndroid Build Coastguard Worker {
154*35238bceSAndroid Build Coastguard Worker const float v00 = values[0];
155*35238bceSAndroid Build Coastguard Worker const float v10 = values[1];
156*35238bceSAndroid Build Coastguard Worker const float v01 = values[2];
157*35238bceSAndroid Build Coastguard Worker const float v11 = values[3];
158*35238bceSAndroid Build Coastguard Worker const float res = v00 * (1.0f - x) * (1.0f - y) + v10 * x * (1.0f - y) + v01 * (1.0f - x) * y + v11 * x * y;
159*35238bceSAndroid Build Coastguard Worker return res;
160*35238bceSAndroid Build Coastguard Worker }
161*35238bceSAndroid Build Coastguard Worker
isFixedPointDepthTextureFormat(const tcu::TextureFormat & format)162*35238bceSAndroid Build Coastguard Worker static bool isFixedPointDepthTextureFormat(const tcu::TextureFormat &format)
163*35238bceSAndroid Build Coastguard Worker {
164*35238bceSAndroid Build Coastguard Worker const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
165*35238bceSAndroid Build Coastguard Worker
166*35238bceSAndroid Build Coastguard Worker if (format.order == TextureFormat::D || format.order == TextureFormat::R)
167*35238bceSAndroid Build Coastguard Worker {
168*35238bceSAndroid Build Coastguard Worker // depth internal formats cannot be non-normalized integers
169*35238bceSAndroid Build Coastguard Worker return channelClass != tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
170*35238bceSAndroid Build Coastguard Worker }
171*35238bceSAndroid Build Coastguard Worker else if (format.order == TextureFormat::DS)
172*35238bceSAndroid Build Coastguard Worker {
173*35238bceSAndroid Build Coastguard Worker // combined formats have no single channel class, detect format manually
174*35238bceSAndroid Build Coastguard Worker switch (format.type)
175*35238bceSAndroid Build Coastguard Worker {
176*35238bceSAndroid Build Coastguard Worker case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
177*35238bceSAndroid Build Coastguard Worker return false;
178*35238bceSAndroid Build Coastguard Worker case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
179*35238bceSAndroid Build Coastguard Worker return true;
180*35238bceSAndroid Build Coastguard Worker case tcu::TextureFormat::UNSIGNED_INT_24_8:
181*35238bceSAndroid Build Coastguard Worker return true;
182*35238bceSAndroid Build Coastguard Worker case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
183*35238bceSAndroid Build Coastguard Worker return true;
184*35238bceSAndroid Build Coastguard Worker
185*35238bceSAndroid Build Coastguard Worker default:
186*35238bceSAndroid Build Coastguard Worker {
187*35238bceSAndroid Build Coastguard Worker // unknown format
188*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
189*35238bceSAndroid Build Coastguard Worker return true;
190*35238bceSAndroid Build Coastguard Worker }
191*35238bceSAndroid Build Coastguard Worker }
192*35238bceSAndroid Build Coastguard Worker }
193*35238bceSAndroid Build Coastguard Worker
194*35238bceSAndroid Build Coastguard Worker return false;
195*35238bceSAndroid Build Coastguard Worker }
196*35238bceSAndroid Build Coastguard Worker
isLinearCompareValid(const Sampler::CompareMode compareMode,const TexComparePrecision & prec,const Vec2 & depths,const Vec2 & fBounds,const float cmpReference,const float result,const bool isFixedPointDepth)197*35238bceSAndroid Build Coastguard Worker static bool isLinearCompareValid(const Sampler::CompareMode compareMode, const TexComparePrecision &prec,
198*35238bceSAndroid Build Coastguard Worker const Vec2 &depths, const Vec2 &fBounds, const float cmpReference, const float result,
199*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth)
200*35238bceSAndroid Build Coastguard Worker {
201*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= fBounds.x() && fBounds.x() <= fBounds.y() && fBounds.y() <= 1.0f);
202*35238bceSAndroid Build Coastguard Worker
203*35238bceSAndroid Build Coastguard Worker const float d0 = depths[0];
204*35238bceSAndroid Build Coastguard Worker const float d1 = depths[1];
205*35238bceSAndroid Build Coastguard Worker
206*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp0 = execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
207*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp1 = execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
208*35238bceSAndroid Build Coastguard Worker
209*35238bceSAndroid Build Coastguard Worker const uint32_t isTrue = (uint32_t(cmp0.isTrue) << 0) | (uint32_t(cmp1.isTrue) << 1);
210*35238bceSAndroid Build Coastguard Worker const uint32_t isFalse = (uint32_t(cmp0.isFalse) << 0) | (uint32_t(cmp1.isFalse) << 1);
211*35238bceSAndroid Build Coastguard Worker
212*35238bceSAndroid Build Coastguard Worker // Interpolation parameters
213*35238bceSAndroid Build Coastguard Worker const float f0 = fBounds.x();
214*35238bceSAndroid Build Coastguard Worker const float f1 = fBounds.y();
215*35238bceSAndroid Build Coastguard Worker
216*35238bceSAndroid Build Coastguard Worker // Error parameters
217*35238bceSAndroid Build Coastguard Worker const float pcfErr = computeFixedPointError(prec.pcfBits);
218*35238bceSAndroid Build Coastguard Worker const float resErr = computeFixedPointError(prec.resultBits);
219*35238bceSAndroid Build Coastguard Worker const float totalErr = pcfErr + resErr;
220*35238bceSAndroid Build Coastguard Worker
221*35238bceSAndroid Build Coastguard Worker // Iterate over all valid combinations.
222*35238bceSAndroid Build Coastguard Worker for (uint32_t comb = 0; comb < (1 << 2); comb++)
223*35238bceSAndroid Build Coastguard Worker {
224*35238bceSAndroid Build Coastguard Worker // Filter out invalid combinations.
225*35238bceSAndroid Build Coastguard Worker if (((comb & isTrue) | (~comb & isFalse)) != (1 << 2) - 1)
226*35238bceSAndroid Build Coastguard Worker continue;
227*35238bceSAndroid Build Coastguard Worker
228*35238bceSAndroid Build Coastguard Worker const bool cmp0True = ((comb >> 0) & 1) != 0;
229*35238bceSAndroid Build Coastguard Worker const bool cmp1True = ((comb >> 1) & 1) != 0;
230*35238bceSAndroid Build Coastguard Worker
231*35238bceSAndroid Build Coastguard Worker const float ref0 = cmp0True ? 1.0f : 0.0f;
232*35238bceSAndroid Build Coastguard Worker const float ref1 = cmp1True ? 1.0f : 0.0f;
233*35238bceSAndroid Build Coastguard Worker
234*35238bceSAndroid Build Coastguard Worker const float v0 = ref0 * (1.0f - f0) + ref1 * f0;
235*35238bceSAndroid Build Coastguard Worker const float v1 = ref0 * (1.0f - f1) + ref1 * f1;
236*35238bceSAndroid Build Coastguard Worker const float minV = de::min(v0, v1);
237*35238bceSAndroid Build Coastguard Worker const float maxV = de::max(v0, v1);
238*35238bceSAndroid Build Coastguard Worker const float minR = minV - totalErr;
239*35238bceSAndroid Build Coastguard Worker const float maxR = maxV + totalErr;
240*35238bceSAndroid Build Coastguard Worker
241*35238bceSAndroid Build Coastguard Worker if (de::inRange(result, minR, maxR))
242*35238bceSAndroid Build Coastguard Worker return true;
243*35238bceSAndroid Build Coastguard Worker }
244*35238bceSAndroid Build Coastguard Worker
245*35238bceSAndroid Build Coastguard Worker return false;
246*35238bceSAndroid Build Coastguard Worker }
247*35238bceSAndroid Build Coastguard Worker
extractBVec4(const uint32_t val,int offset)248*35238bceSAndroid Build Coastguard Worker static inline BVec4 extractBVec4(const uint32_t val, int offset)
249*35238bceSAndroid Build Coastguard Worker {
250*35238bceSAndroid Build Coastguard Worker return BVec4(((val >> (offset + 0)) & 1) != 0, ((val >> (offset + 1)) & 1) != 0, ((val >> (offset + 2)) & 1) != 0,
251*35238bceSAndroid Build Coastguard Worker ((val >> (offset + 3)) & 1) != 0);
252*35238bceSAndroid Build Coastguard Worker }
253*35238bceSAndroid Build Coastguard Worker
isBilinearAnyCompareValid(const Sampler::CompareMode compareMode,const TexComparePrecision & prec,const Vec4 & depths,const float cmpReference,const float result,const bool isFixedPointDepth)254*35238bceSAndroid Build Coastguard Worker static bool isBilinearAnyCompareValid(const Sampler::CompareMode compareMode, const TexComparePrecision &prec,
255*35238bceSAndroid Build Coastguard Worker const Vec4 &depths, const float cmpReference, const float result,
256*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth)
257*35238bceSAndroid Build Coastguard Worker {
258*35238bceSAndroid Build Coastguard Worker DE_ASSERT(prec.pcfBits == 0);
259*35238bceSAndroid Build Coastguard Worker
260*35238bceSAndroid Build Coastguard Worker const float d0 = depths[0];
261*35238bceSAndroid Build Coastguard Worker const float d1 = depths[1];
262*35238bceSAndroid Build Coastguard Worker const float d2 = depths[2];
263*35238bceSAndroid Build Coastguard Worker const float d3 = depths[3];
264*35238bceSAndroid Build Coastguard Worker
265*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp0 = execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
266*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp1 = execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
267*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp2 = execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
268*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp3 = execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);
269*35238bceSAndroid Build Coastguard Worker
270*35238bceSAndroid Build Coastguard Worker const bool canBeTrue = cmp0.isTrue || cmp1.isTrue || cmp2.isTrue || cmp3.isTrue;
271*35238bceSAndroid Build Coastguard Worker const bool canBeFalse = cmp0.isFalse || cmp1.isFalse || cmp2.isFalse || cmp3.isFalse;
272*35238bceSAndroid Build Coastguard Worker
273*35238bceSAndroid Build Coastguard Worker const float resErr = computeFixedPointError(prec.resultBits);
274*35238bceSAndroid Build Coastguard Worker
275*35238bceSAndroid Build Coastguard Worker const float minBound = canBeFalse ? 0.0f : 1.0f;
276*35238bceSAndroid Build Coastguard Worker const float maxBound = canBeTrue ? 1.0f : 0.0f;
277*35238bceSAndroid Build Coastguard Worker
278*35238bceSAndroid Build Coastguard Worker return de::inRange(result, minBound - resErr, maxBound + resErr);
279*35238bceSAndroid Build Coastguard Worker }
280*35238bceSAndroid Build Coastguard Worker
isBilinearPCFCompareValid(const Sampler::CompareMode compareMode,const TexComparePrecision & prec,const Vec4 & depths,const Vec2 & xBounds,const Vec2 & yBounds,const float cmpReference,const float result,const bool isFixedPointDepth)281*35238bceSAndroid Build Coastguard Worker static bool isBilinearPCFCompareValid(const Sampler::CompareMode compareMode, const TexComparePrecision &prec,
282*35238bceSAndroid Build Coastguard Worker const Vec4 &depths, const Vec2 &xBounds, const Vec2 &yBounds,
283*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result, const bool isFixedPointDepth)
284*35238bceSAndroid Build Coastguard Worker {
285*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= xBounds.x() && xBounds.x() <= xBounds.y() && xBounds.y() <= 1.0f);
286*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= yBounds.x() && yBounds.x() <= yBounds.y() && yBounds.y() <= 1.0f);
287*35238bceSAndroid Build Coastguard Worker DE_ASSERT(prec.pcfBits > 0);
288*35238bceSAndroid Build Coastguard Worker
289*35238bceSAndroid Build Coastguard Worker const float d0 = depths[0];
290*35238bceSAndroid Build Coastguard Worker const float d1 = depths[1];
291*35238bceSAndroid Build Coastguard Worker const float d2 = depths[2];
292*35238bceSAndroid Build Coastguard Worker const float d3 = depths[3];
293*35238bceSAndroid Build Coastguard Worker
294*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp0 = execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
295*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp1 = execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
296*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp2 = execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
297*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp3 = execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);
298*35238bceSAndroid Build Coastguard Worker
299*35238bceSAndroid Build Coastguard Worker const uint32_t isTrue = (uint32_t(cmp0.isTrue) << 0) | (uint32_t(cmp1.isTrue) << 1) | (uint32_t(cmp2.isTrue) << 2) |
300*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp3.isTrue) << 3);
301*35238bceSAndroid Build Coastguard Worker const uint32_t isFalse = (uint32_t(cmp0.isFalse) << 0) | (uint32_t(cmp1.isFalse) << 1) |
302*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp2.isFalse) << 2) | (uint32_t(cmp3.isFalse) << 3);
303*35238bceSAndroid Build Coastguard Worker
304*35238bceSAndroid Build Coastguard Worker // Interpolation parameters
305*35238bceSAndroid Build Coastguard Worker const float x0 = xBounds.x();
306*35238bceSAndroid Build Coastguard Worker const float x1 = xBounds.y();
307*35238bceSAndroid Build Coastguard Worker const float y0 = yBounds.x();
308*35238bceSAndroid Build Coastguard Worker const float y1 = yBounds.y();
309*35238bceSAndroid Build Coastguard Worker
310*35238bceSAndroid Build Coastguard Worker // Error parameters
311*35238bceSAndroid Build Coastguard Worker const float pcfErr = computeFixedPointError(prec.pcfBits);
312*35238bceSAndroid Build Coastguard Worker const float resErr = computeFixedPointError(prec.resultBits);
313*35238bceSAndroid Build Coastguard Worker const float totalErr = pcfErr + resErr;
314*35238bceSAndroid Build Coastguard Worker
315*35238bceSAndroid Build Coastguard Worker // Iterate over all valid combinations.
316*35238bceSAndroid Build Coastguard Worker // \note It is not enough to compute minmax over all possible result sets, as ranges may
317*35238bceSAndroid Build Coastguard Worker // not necessarily overlap, i.e. there are gaps between valid ranges.
318*35238bceSAndroid Build Coastguard Worker for (uint32_t comb = 0; comb < (1 << 4); comb++)
319*35238bceSAndroid Build Coastguard Worker {
320*35238bceSAndroid Build Coastguard Worker // Filter out invalid combinations:
321*35238bceSAndroid Build Coastguard Worker // 1) True bit is set in comb but not in isTrue => sample can not be true
322*35238bceSAndroid Build Coastguard Worker // 2) True bit is NOT set in comb and not in isFalse => sample can not be false
323*35238bceSAndroid Build Coastguard Worker if (((comb & isTrue) | (~comb & isFalse)) != (1 << 4) - 1)
324*35238bceSAndroid Build Coastguard Worker continue;
325*35238bceSAndroid Build Coastguard Worker
326*35238bceSAndroid Build Coastguard Worker const BVec4 cmpTrue = extractBVec4(comb, 0);
327*35238bceSAndroid Build Coastguard Worker const Vec4 refVal = select(Vec4(1.0f), Vec4(0.0f), cmpTrue);
328*35238bceSAndroid Build Coastguard Worker
329*35238bceSAndroid Build Coastguard Worker const float v0 = bilinearInterpolate(refVal, x0, y0);
330*35238bceSAndroid Build Coastguard Worker const float v1 = bilinearInterpolate(refVal, x1, y0);
331*35238bceSAndroid Build Coastguard Worker const float v2 = bilinearInterpolate(refVal, x0, y1);
332*35238bceSAndroid Build Coastguard Worker const float v3 = bilinearInterpolate(refVal, x1, y1);
333*35238bceSAndroid Build Coastguard Worker const float minV = de::min(v0, de::min(v1, de::min(v2, v3)));
334*35238bceSAndroid Build Coastguard Worker const float maxV = de::max(v0, de::max(v1, de::max(v2, v3)));
335*35238bceSAndroid Build Coastguard Worker const float minR = minV - totalErr;
336*35238bceSAndroid Build Coastguard Worker const float maxR = maxV + totalErr;
337*35238bceSAndroid Build Coastguard Worker
338*35238bceSAndroid Build Coastguard Worker if (de::inRange(result, minR, maxR))
339*35238bceSAndroid Build Coastguard Worker return true;
340*35238bceSAndroid Build Coastguard Worker }
341*35238bceSAndroid Build Coastguard Worker
342*35238bceSAndroid Build Coastguard Worker return false;
343*35238bceSAndroid Build Coastguard Worker }
344*35238bceSAndroid Build Coastguard Worker
isBilinearCompareValid(const Sampler::CompareMode compareMode,const TexComparePrecision & prec,const Vec4 & depths,const Vec2 & xBounds,const Vec2 & yBounds,const float cmpReference,const float result,const bool isFixedPointDepth)345*35238bceSAndroid Build Coastguard Worker static bool isBilinearCompareValid(const Sampler::CompareMode compareMode, const TexComparePrecision &prec,
346*35238bceSAndroid Build Coastguard Worker const Vec4 &depths, const Vec2 &xBounds, const Vec2 &yBounds,
347*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result, const bool isFixedPointDepth)
348*35238bceSAndroid Build Coastguard Worker {
349*35238bceSAndroid Build Coastguard Worker if (prec.pcfBits > 0)
350*35238bceSAndroid Build Coastguard Worker return isBilinearPCFCompareValid(compareMode, prec, depths, xBounds, yBounds, cmpReference, result,
351*35238bceSAndroid Build Coastguard Worker isFixedPointDepth);
352*35238bceSAndroid Build Coastguard Worker else
353*35238bceSAndroid Build Coastguard Worker return isBilinearAnyCompareValid(compareMode, prec, depths, cmpReference, result, isFixedPointDepth);
354*35238bceSAndroid Build Coastguard Worker }
355*35238bceSAndroid Build Coastguard Worker
isTrilinearAnyCompareValid(const Sampler::CompareMode compareMode,const TexComparePrecision & prec,const Vec4 & depths0,const Vec4 & depths1,const float cmpReference,const float result,const bool isFixedPointDepth)356*35238bceSAndroid Build Coastguard Worker static bool isTrilinearAnyCompareValid(const Sampler::CompareMode compareMode, const TexComparePrecision &prec,
357*35238bceSAndroid Build Coastguard Worker const Vec4 &depths0, const Vec4 &depths1, const float cmpReference,
358*35238bceSAndroid Build Coastguard Worker const float result, const bool isFixedPointDepth)
359*35238bceSAndroid Build Coastguard Worker {
360*35238bceSAndroid Build Coastguard Worker DE_ASSERT(prec.pcfBits == 0);
361*35238bceSAndroid Build Coastguard Worker
362*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp00 =
363*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth);
364*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp01 =
365*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth);
366*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp02 =
367*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth);
368*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp03 =
369*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth);
370*35238bceSAndroid Build Coastguard Worker
371*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp10 =
372*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth);
373*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp11 =
374*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth);
375*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp12 =
376*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth);
377*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp13 =
378*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth);
379*35238bceSAndroid Build Coastguard Worker
380*35238bceSAndroid Build Coastguard Worker const bool canBeTrue = cmp00.isTrue || cmp01.isTrue || cmp02.isTrue || cmp03.isTrue || cmp10.isTrue ||
381*35238bceSAndroid Build Coastguard Worker cmp11.isTrue || cmp12.isTrue || cmp13.isTrue;
382*35238bceSAndroid Build Coastguard Worker const bool canBeFalse = cmp00.isFalse || cmp01.isFalse || cmp02.isFalse || cmp03.isFalse || cmp10.isFalse ||
383*35238bceSAndroid Build Coastguard Worker cmp11.isFalse || cmp12.isFalse || cmp13.isFalse;
384*35238bceSAndroid Build Coastguard Worker
385*35238bceSAndroid Build Coastguard Worker const float resErr = computeFixedPointError(prec.resultBits);
386*35238bceSAndroid Build Coastguard Worker
387*35238bceSAndroid Build Coastguard Worker const float minBound = canBeFalse ? 0.0f : 1.0f;
388*35238bceSAndroid Build Coastguard Worker const float maxBound = canBeTrue ? 1.0f : 0.0f;
389*35238bceSAndroid Build Coastguard Worker
390*35238bceSAndroid Build Coastguard Worker return de::inRange(result, minBound - resErr, maxBound + resErr);
391*35238bceSAndroid Build Coastguard Worker }
392*35238bceSAndroid Build Coastguard Worker
isTrilinearPCFCompareValid(const Sampler::CompareMode compareMode,const TexComparePrecision & prec,const Vec4 & depths0,const Vec4 & depths1,const Vec2 & xBounds0,const Vec2 & yBounds0,const Vec2 & xBounds1,const Vec2 & yBounds1,const Vec2 & fBounds,const float cmpReference,const float result,const bool isFixedPointDepth)393*35238bceSAndroid Build Coastguard Worker static bool isTrilinearPCFCompareValid(const Sampler::CompareMode compareMode, const TexComparePrecision &prec,
394*35238bceSAndroid Build Coastguard Worker const Vec4 &depths0, const Vec4 &depths1, const Vec2 &xBounds0,
395*35238bceSAndroid Build Coastguard Worker const Vec2 &yBounds0, const Vec2 &xBounds1, const Vec2 &yBounds1,
396*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const float cmpReference, const float result,
397*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth)
398*35238bceSAndroid Build Coastguard Worker {
399*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= xBounds0.x() && xBounds0.x() <= xBounds0.y() && xBounds0.y() <= 1.0f);
400*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= yBounds0.x() && yBounds0.x() <= yBounds0.y() && yBounds0.y() <= 1.0f);
401*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= xBounds1.x() && xBounds1.x() <= xBounds1.y() && xBounds1.y() <= 1.0f);
402*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= yBounds1.x() && yBounds1.x() <= yBounds1.y() && yBounds1.y() <= 1.0f);
403*35238bceSAndroid Build Coastguard Worker DE_ASSERT(0.0f <= fBounds.x() && fBounds.x() <= fBounds.y() && fBounds.y() <= 1.0f);
404*35238bceSAndroid Build Coastguard Worker DE_ASSERT(prec.pcfBits > 0);
405*35238bceSAndroid Build Coastguard Worker
406*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp00 =
407*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth);
408*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp01 =
409*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth);
410*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp02 =
411*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth);
412*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp03 =
413*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth);
414*35238bceSAndroid Build Coastguard Worker
415*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp10 =
416*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth);
417*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp11 =
418*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth);
419*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp12 =
420*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth);
421*35238bceSAndroid Build Coastguard Worker const CmpResultSet cmp13 =
422*35238bceSAndroid Build Coastguard Worker execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth);
423*35238bceSAndroid Build Coastguard Worker
424*35238bceSAndroid Build Coastguard Worker const uint32_t isTrue = (uint32_t(cmp00.isTrue) << 0) | (uint32_t(cmp01.isTrue) << 1) |
425*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp02.isTrue) << 2) | (uint32_t(cmp03.isTrue) << 3) |
426*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp10.isTrue) << 4) | (uint32_t(cmp11.isTrue) << 5) |
427*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp12.isTrue) << 6) | (uint32_t(cmp13.isTrue) << 7);
428*35238bceSAndroid Build Coastguard Worker const uint32_t isFalse = (uint32_t(cmp00.isFalse) << 0) | (uint32_t(cmp01.isFalse) << 1) |
429*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp02.isFalse) << 2) | (uint32_t(cmp03.isFalse) << 3) |
430*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp10.isFalse) << 4) | (uint32_t(cmp11.isFalse) << 5) |
431*35238bceSAndroid Build Coastguard Worker (uint32_t(cmp12.isFalse) << 6) | (uint32_t(cmp13.isFalse) << 7);
432*35238bceSAndroid Build Coastguard Worker
433*35238bceSAndroid Build Coastguard Worker // Error parameters
434*35238bceSAndroid Build Coastguard Worker const float pcfErr = computeFixedPointError(prec.pcfBits);
435*35238bceSAndroid Build Coastguard Worker const float resErr = computeFixedPointError(prec.resultBits);
436*35238bceSAndroid Build Coastguard Worker const float totalErr = pcfErr + resErr;
437*35238bceSAndroid Build Coastguard Worker
438*35238bceSAndroid Build Coastguard Worker // Iterate over all valid combinations.
439*35238bceSAndroid Build Coastguard Worker for (uint32_t comb = 0; comb < (1 << 8); comb++)
440*35238bceSAndroid Build Coastguard Worker {
441*35238bceSAndroid Build Coastguard Worker // Filter out invalid combinations.
442*35238bceSAndroid Build Coastguard Worker if (((comb & isTrue) | (~comb & isFalse)) != (1 << 8) - 1)
443*35238bceSAndroid Build Coastguard Worker continue;
444*35238bceSAndroid Build Coastguard Worker
445*35238bceSAndroid Build Coastguard Worker const BVec4 cmpTrue0 = extractBVec4(comb, 0);
446*35238bceSAndroid Build Coastguard Worker const BVec4 cmpTrue1 = extractBVec4(comb, 4);
447*35238bceSAndroid Build Coastguard Worker const Vec4 refVal0 = select(Vec4(1.0f), Vec4(0.0f), cmpTrue0);
448*35238bceSAndroid Build Coastguard Worker const Vec4 refVal1 = select(Vec4(1.0f), Vec4(0.0f), cmpTrue1);
449*35238bceSAndroid Build Coastguard Worker
450*35238bceSAndroid Build Coastguard Worker // Bilinear interpolation within levels.
451*35238bceSAndroid Build Coastguard Worker const float v00 = bilinearInterpolate(refVal0, xBounds0.x(), yBounds0.x());
452*35238bceSAndroid Build Coastguard Worker const float v01 = bilinearInterpolate(refVal0, xBounds0.y(), yBounds0.x());
453*35238bceSAndroid Build Coastguard Worker const float v02 = bilinearInterpolate(refVal0, xBounds0.x(), yBounds0.y());
454*35238bceSAndroid Build Coastguard Worker const float v03 = bilinearInterpolate(refVal0, xBounds0.y(), yBounds0.y());
455*35238bceSAndroid Build Coastguard Worker const float minV0 = de::min(v00, de::min(v01, de::min(v02, v03)));
456*35238bceSAndroid Build Coastguard Worker const float maxV0 = de::max(v00, de::max(v01, de::max(v02, v03)));
457*35238bceSAndroid Build Coastguard Worker
458*35238bceSAndroid Build Coastguard Worker const float v10 = bilinearInterpolate(refVal1, xBounds1.x(), yBounds1.x());
459*35238bceSAndroid Build Coastguard Worker const float v11 = bilinearInterpolate(refVal1, xBounds1.y(), yBounds1.x());
460*35238bceSAndroid Build Coastguard Worker const float v12 = bilinearInterpolate(refVal1, xBounds1.x(), yBounds1.y());
461*35238bceSAndroid Build Coastguard Worker const float v13 = bilinearInterpolate(refVal1, xBounds1.y(), yBounds1.y());
462*35238bceSAndroid Build Coastguard Worker const float minV1 = de::min(v10, de::min(v11, de::min(v12, v13)));
463*35238bceSAndroid Build Coastguard Worker const float maxV1 = de::max(v10, de::max(v11, de::max(v12, v13)));
464*35238bceSAndroid Build Coastguard Worker
465*35238bceSAndroid Build Coastguard Worker // Compute min-max bounds by filtering between minimum bounds and maximum bounds between levels.
466*35238bceSAndroid Build Coastguard Worker // HW can end up choosing pretty much any of samples between levels, and thus interpolating
467*35238bceSAndroid Build Coastguard Worker // between minimums should yield lower bound for range, and same for upper bound.
468*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-17 pyry] This seems separable? Can this be optimized? At least ranges could be pre-computed and later combined.
469*35238bceSAndroid Build Coastguard Worker const float minF0 = minV0 * (1.0f - fBounds.x()) + minV1 * fBounds.x();
470*35238bceSAndroid Build Coastguard Worker const float minF1 = minV0 * (1.0f - fBounds.y()) + minV1 * fBounds.y();
471*35238bceSAndroid Build Coastguard Worker const float maxF0 = maxV0 * (1.0f - fBounds.x()) + maxV1 * fBounds.x();
472*35238bceSAndroid Build Coastguard Worker const float maxF1 = maxV0 * (1.0f - fBounds.y()) + maxV1 * fBounds.y();
473*35238bceSAndroid Build Coastguard Worker
474*35238bceSAndroid Build Coastguard Worker const float minF = de::min(minF0, minF1);
475*35238bceSAndroid Build Coastguard Worker const float maxF = de::max(maxF0, maxF1);
476*35238bceSAndroid Build Coastguard Worker
477*35238bceSAndroid Build Coastguard Worker const float minR = minF - totalErr;
478*35238bceSAndroid Build Coastguard Worker const float maxR = maxF + totalErr;
479*35238bceSAndroid Build Coastguard Worker
480*35238bceSAndroid Build Coastguard Worker if (de::inRange(result, minR, maxR))
481*35238bceSAndroid Build Coastguard Worker return true;
482*35238bceSAndroid Build Coastguard Worker }
483*35238bceSAndroid Build Coastguard Worker
484*35238bceSAndroid Build Coastguard Worker return false;
485*35238bceSAndroid Build Coastguard Worker }
486*35238bceSAndroid Build Coastguard Worker
isTrilinearCompareValid(const Sampler::CompareMode compareMode,const TexComparePrecision & prec,const Vec4 & depths0,const Vec4 & depths1,const Vec2 & xBounds0,const Vec2 & yBounds0,const Vec2 & xBounds1,const Vec2 & yBounds1,const Vec2 & fBounds,const float cmpReference,const float result,const bool isFixedPointDepth)487*35238bceSAndroid Build Coastguard Worker static bool isTrilinearCompareValid(const Sampler::CompareMode compareMode, const TexComparePrecision &prec,
488*35238bceSAndroid Build Coastguard Worker const Vec4 &depths0, const Vec4 &depths1, const Vec2 &xBounds0,
489*35238bceSAndroid Build Coastguard Worker const Vec2 &yBounds0, const Vec2 &xBounds1, const Vec2 &yBounds1,
490*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const float cmpReference, const float result,
491*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth)
492*35238bceSAndroid Build Coastguard Worker {
493*35238bceSAndroid Build Coastguard Worker if (prec.pcfBits > 0)
494*35238bceSAndroid Build Coastguard Worker return isTrilinearPCFCompareValid(compareMode, prec, depths0, depths1, xBounds0, yBounds0, xBounds1, yBounds1,
495*35238bceSAndroid Build Coastguard Worker fBounds, cmpReference, result, isFixedPointDepth);
496*35238bceSAndroid Build Coastguard Worker else
497*35238bceSAndroid Build Coastguard Worker return isTrilinearAnyCompareValid(compareMode, prec, depths0, depths1, cmpReference, result, isFixedPointDepth);
498*35238bceSAndroid Build Coastguard Worker }
499*35238bceSAndroid Build Coastguard Worker
isNearestCompareResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,const int coordZ,const float cmpReference,const float result)500*35238bceSAndroid Build Coastguard Worker static bool isNearestCompareResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
501*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec2 &coord, const int coordZ,
502*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result)
503*35238bceSAndroid Build Coastguard Worker {
504*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level.getFormat());
505*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
506*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
507*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord.y(),
508*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
509*35238bceSAndroid Build Coastguard Worker
510*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
511*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x());
512*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y());
513*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x());
514*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y());
515*35238bceSAndroid Build Coastguard Worker
516*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
517*35238bceSAndroid Build Coastguard Worker {
518*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
519*35238bceSAndroid Build Coastguard Worker {
520*35238bceSAndroid Build Coastguard Worker const int x = wrap(sampler.wrapS, i, level.getWidth());
521*35238bceSAndroid Build Coastguard Worker const int y = wrap(sampler.wrapT, j, level.getHeight());
522*35238bceSAndroid Build Coastguard Worker const float depth = lookupDepth(level, sampler, x, y, coordZ);
523*35238bceSAndroid Build Coastguard Worker const CmpResultSet resSet =
524*35238bceSAndroid Build Coastguard Worker execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);
525*35238bceSAndroid Build Coastguard Worker
526*35238bceSAndroid Build Coastguard Worker if (isResultInSet(resSet, result, prec.resultBits))
527*35238bceSAndroid Build Coastguard Worker return true;
528*35238bceSAndroid Build Coastguard Worker }
529*35238bceSAndroid Build Coastguard Worker }
530*35238bceSAndroid Build Coastguard Worker
531*35238bceSAndroid Build Coastguard Worker return false;
532*35238bceSAndroid Build Coastguard Worker }
533*35238bceSAndroid Build Coastguard Worker
isLinearCompareResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,const int coordZ,const float cmpReference,const float result)534*35238bceSAndroid Build Coastguard Worker static bool isLinearCompareResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
535*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec2 &coord, const int coordZ,
536*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result)
537*35238bceSAndroid Build Coastguard Worker {
538*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level.getFormat());
539*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
540*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
541*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord.y(),
542*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
543*35238bceSAndroid Build Coastguard Worker
544*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
545*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
546*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
547*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
548*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
549*35238bceSAndroid Build Coastguard Worker
550*35238bceSAndroid Build Coastguard Worker const int w = level.getWidth();
551*35238bceSAndroid Build Coastguard Worker const int h = level.getHeight();
552*35238bceSAndroid Build Coastguard Worker
553*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
554*35238bceSAndroid Build Coastguard Worker
555*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
556*35238bceSAndroid Build Coastguard Worker {
557*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
558*35238bceSAndroid Build Coastguard Worker {
559*35238bceSAndroid Build Coastguard Worker // Wrapped coordinates
560*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i, w);
561*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i + 1, w);
562*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j, h);
563*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j + 1, h);
564*35238bceSAndroid Build Coastguard Worker
565*35238bceSAndroid Build Coastguard Worker // Bounds for filtering factors
566*35238bceSAndroid Build Coastguard Worker const float minA = de::clamp((uBounds.x() - 0.5f) - float(i), 0.0f, 1.0f);
567*35238bceSAndroid Build Coastguard Worker const float maxA = de::clamp((uBounds.y() - 0.5f) - float(i), 0.0f, 1.0f);
568*35238bceSAndroid Build Coastguard Worker const float minB = de::clamp((vBounds.x() - 0.5f) - float(j), 0.0f, 1.0f);
569*35238bceSAndroid Build Coastguard Worker const float maxB = de::clamp((vBounds.y() - 0.5f) - float(j), 0.0f, 1.0f);
570*35238bceSAndroid Build Coastguard Worker
571*35238bceSAndroid Build Coastguard Worker const Vec4 depths(lookupDepth(level, sampler, x0, y0, coordZ), lookupDepth(level, sampler, x1, y0, coordZ),
572*35238bceSAndroid Build Coastguard Worker lookupDepth(level, sampler, x0, y1, coordZ), lookupDepth(level, sampler, x1, y1, coordZ));
573*35238bceSAndroid Build Coastguard Worker
574*35238bceSAndroid Build Coastguard Worker if (isBilinearCompareValid(sampler.compare, prec, depths, Vec2(minA, maxA), Vec2(minB, maxB), cmpReference,
575*35238bceSAndroid Build Coastguard Worker result, isFixedPointDepth))
576*35238bceSAndroid Build Coastguard Worker return true;
577*35238bceSAndroid Build Coastguard Worker }
578*35238bceSAndroid Build Coastguard Worker }
579*35238bceSAndroid Build Coastguard Worker
580*35238bceSAndroid Build Coastguard Worker return false;
581*35238bceSAndroid Build Coastguard Worker }
582*35238bceSAndroid Build Coastguard Worker
isLevelCompareResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const Sampler::FilterMode filterMode,const TexComparePrecision & prec,const Vec2 & coord,const int coordZ,const float cmpReference,const float result)583*35238bceSAndroid Build Coastguard Worker static bool isLevelCompareResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
584*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode, const TexComparePrecision &prec,
585*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, const int coordZ, const float cmpReference, const float result)
586*35238bceSAndroid Build Coastguard Worker {
587*35238bceSAndroid Build Coastguard Worker if (filterMode == Sampler::LINEAR)
588*35238bceSAndroid Build Coastguard Worker return isLinearCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
589*35238bceSAndroid Build Coastguard Worker else
590*35238bceSAndroid Build Coastguard Worker return isNearestCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
591*35238bceSAndroid Build Coastguard Worker }
592*35238bceSAndroid Build Coastguard Worker
isNearestMipmapLinearCompareResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,const int coordZ,const Vec2 & fBounds,const float cmpReference,const float result)593*35238bceSAndroid Build Coastguard Worker static bool isNearestMipmapLinearCompareResultValid(const ConstPixelBufferAccess &level0,
594*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
595*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec2 &coord,
596*35238bceSAndroid Build Coastguard Worker const int coordZ, const Vec2 &fBounds, const float cmpReference,
597*35238bceSAndroid Build Coastguard Worker const float result)
598*35238bceSAndroid Build Coastguard Worker {
599*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level0.getFormat());
600*35238bceSAndroid Build Coastguard Worker
601*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
602*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
603*35238bceSAndroid Build Coastguard Worker const int h0 = level0.getHeight();
604*35238bceSAndroid Build Coastguard Worker const int h1 = level1.getHeight();
605*35238bceSAndroid Build Coastguard Worker
606*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
607*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
608*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
609*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
610*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 =
611*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
612*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 =
613*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
614*35238bceSAndroid Build Coastguard Worker
615*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
616*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x());
617*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y());
618*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x());
619*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y());
620*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x());
621*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y());
622*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x());
623*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y());
624*35238bceSAndroid Build Coastguard Worker
625*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
626*35238bceSAndroid Build Coastguard Worker {
627*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
628*35238bceSAndroid Build Coastguard Worker {
629*35238bceSAndroid Build Coastguard Worker const float depth0 =
630*35238bceSAndroid Build Coastguard Worker lookupDepth(level0, sampler, wrap(sampler.wrapS, i0, w0), wrap(sampler.wrapT, j0, h0), coordZ);
631*35238bceSAndroid Build Coastguard Worker
632*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
633*35238bceSAndroid Build Coastguard Worker {
634*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
635*35238bceSAndroid Build Coastguard Worker {
636*35238bceSAndroid Build Coastguard Worker const float depth1 =
637*35238bceSAndroid Build Coastguard Worker lookupDepth(level1, sampler, wrap(sampler.wrapS, i1, w1), wrap(sampler.wrapT, j1, h1), coordZ);
638*35238bceSAndroid Build Coastguard Worker
639*35238bceSAndroid Build Coastguard Worker if (isLinearCompareValid(sampler.compare, prec, Vec2(depth0, depth1), fBounds, cmpReference, result,
640*35238bceSAndroid Build Coastguard Worker isFixedPointDepth))
641*35238bceSAndroid Build Coastguard Worker return true;
642*35238bceSAndroid Build Coastguard Worker }
643*35238bceSAndroid Build Coastguard Worker }
644*35238bceSAndroid Build Coastguard Worker }
645*35238bceSAndroid Build Coastguard Worker }
646*35238bceSAndroid Build Coastguard Worker
647*35238bceSAndroid Build Coastguard Worker return false;
648*35238bceSAndroid Build Coastguard Worker }
649*35238bceSAndroid Build Coastguard Worker
isLinearMipmapLinearCompareResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,const int coordZ,const Vec2 & fBounds,const float cmpReference,const float result)650*35238bceSAndroid Build Coastguard Worker static bool isLinearMipmapLinearCompareResultValid(const ConstPixelBufferAccess &level0,
651*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
652*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec2 &coord, const int coordZ,
653*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const float cmpReference, const float result)
654*35238bceSAndroid Build Coastguard Worker {
655*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level0.getFormat());
656*35238bceSAndroid Build Coastguard Worker
657*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
658*35238bceSAndroid Build Coastguard Worker // Right now this allows pairing any two valid bilinear quads.
659*35238bceSAndroid Build Coastguard Worker
660*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
661*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
662*35238bceSAndroid Build Coastguard Worker const int h0 = level0.getHeight();
663*35238bceSAndroid Build Coastguard Worker const int h1 = level1.getHeight();
664*35238bceSAndroid Build Coastguard Worker
665*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
666*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
667*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
668*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
669*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 =
670*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
671*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 =
672*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
673*35238bceSAndroid Build Coastguard Worker
674*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
675*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x() - 0.5f);
676*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y() - 0.5f);
677*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x() - 0.5f);
678*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y() - 0.5f);
679*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x() - 0.5f);
680*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y() - 0.5f);
681*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x() - 0.5f);
682*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y() - 0.5f);
683*35238bceSAndroid Build Coastguard Worker
684*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
685*35238bceSAndroid Build Coastguard Worker {
686*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
687*35238bceSAndroid Build Coastguard Worker {
688*35238bceSAndroid Build Coastguard Worker const float minA0 = de::clamp((uBounds0.x() - 0.5f) - float(i0), 0.0f, 1.0f);
689*35238bceSAndroid Build Coastguard Worker const float maxA0 = de::clamp((uBounds0.y() - 0.5f) - float(i0), 0.0f, 1.0f);
690*35238bceSAndroid Build Coastguard Worker const float minB0 = de::clamp((vBounds0.x() - 0.5f) - float(j0), 0.0f, 1.0f);
691*35238bceSAndroid Build Coastguard Worker const float maxB0 = de::clamp((vBounds0.y() - 0.5f) - float(j0), 0.0f, 1.0f);
692*35238bceSAndroid Build Coastguard Worker Vec4 depths0;
693*35238bceSAndroid Build Coastguard Worker
694*35238bceSAndroid Build Coastguard Worker {
695*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i0, w0);
696*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i0 + 1, w0);
697*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j0, h0);
698*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j0 + 1, h0);
699*35238bceSAndroid Build Coastguard Worker
700*35238bceSAndroid Build Coastguard Worker depths0[0] = lookupDepth(level0, sampler, x0, y0, coordZ);
701*35238bceSAndroid Build Coastguard Worker depths0[1] = lookupDepth(level0, sampler, x1, y0, coordZ);
702*35238bceSAndroid Build Coastguard Worker depths0[2] = lookupDepth(level0, sampler, x0, y1, coordZ);
703*35238bceSAndroid Build Coastguard Worker depths0[3] = lookupDepth(level0, sampler, x1, y1, coordZ);
704*35238bceSAndroid Build Coastguard Worker }
705*35238bceSAndroid Build Coastguard Worker
706*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
707*35238bceSAndroid Build Coastguard Worker {
708*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
709*35238bceSAndroid Build Coastguard Worker {
710*35238bceSAndroid Build Coastguard Worker const float minA1 = de::clamp((uBounds1.x() - 0.5f) - float(i1), 0.0f, 1.0f);
711*35238bceSAndroid Build Coastguard Worker const float maxA1 = de::clamp((uBounds1.y() - 0.5f) - float(i1), 0.0f, 1.0f);
712*35238bceSAndroid Build Coastguard Worker const float minB1 = de::clamp((vBounds1.x() - 0.5f) - float(j1), 0.0f, 1.0f);
713*35238bceSAndroid Build Coastguard Worker const float maxB1 = de::clamp((vBounds1.y() - 0.5f) - float(j1), 0.0f, 1.0f);
714*35238bceSAndroid Build Coastguard Worker Vec4 depths1;
715*35238bceSAndroid Build Coastguard Worker
716*35238bceSAndroid Build Coastguard Worker {
717*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i1, w1);
718*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i1 + 1, w1);
719*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j1, h1);
720*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j1 + 1, h1);
721*35238bceSAndroid Build Coastguard Worker
722*35238bceSAndroid Build Coastguard Worker depths1[0] = lookupDepth(level1, sampler, x0, y0, coordZ);
723*35238bceSAndroid Build Coastguard Worker depths1[1] = lookupDepth(level1, sampler, x1, y0, coordZ);
724*35238bceSAndroid Build Coastguard Worker depths1[2] = lookupDepth(level1, sampler, x0, y1, coordZ);
725*35238bceSAndroid Build Coastguard Worker depths1[3] = lookupDepth(level1, sampler, x1, y1, coordZ);
726*35238bceSAndroid Build Coastguard Worker }
727*35238bceSAndroid Build Coastguard Worker
728*35238bceSAndroid Build Coastguard Worker if (isTrilinearCompareValid(sampler.compare, prec, depths0, depths1, Vec2(minA0, maxA0),
729*35238bceSAndroid Build Coastguard Worker Vec2(minB0, maxB0), Vec2(minA1, maxA1), Vec2(minB1, maxB1), fBounds,
730*35238bceSAndroid Build Coastguard Worker cmpReference, result, isFixedPointDepth))
731*35238bceSAndroid Build Coastguard Worker return true;
732*35238bceSAndroid Build Coastguard Worker }
733*35238bceSAndroid Build Coastguard Worker }
734*35238bceSAndroid Build Coastguard Worker }
735*35238bceSAndroid Build Coastguard Worker }
736*35238bceSAndroid Build Coastguard Worker
737*35238bceSAndroid Build Coastguard Worker return false;
738*35238bceSAndroid Build Coastguard Worker }
739*35238bceSAndroid Build Coastguard Worker
isMipmapLinearCompareResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const Sampler::FilterMode levelFilter,const TexComparePrecision & prec,const Vec2 & coord,const int coordZ,const Vec2 & fBounds,const float cmpReference,const float result)740*35238bceSAndroid Build Coastguard Worker static bool isMipmapLinearCompareResultValid(const ConstPixelBufferAccess &level0, const ConstPixelBufferAccess &level1,
741*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
742*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec2 &coord, const int coordZ,
743*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const float cmpReference, const float result)
744*35238bceSAndroid Build Coastguard Worker {
745*35238bceSAndroid Build Coastguard Worker if (levelFilter == Sampler::LINEAR)
746*35238bceSAndroid Build Coastguard Worker return isLinearMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds,
747*35238bceSAndroid Build Coastguard Worker cmpReference, result);
748*35238bceSAndroid Build Coastguard Worker else
749*35238bceSAndroid Build Coastguard Worker return isNearestMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds,
750*35238bceSAndroid Build Coastguard Worker cmpReference, result);
751*35238bceSAndroid Build Coastguard Worker }
752*35238bceSAndroid Build Coastguard Worker
isTexCompareResultValid(const Texture2DView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,const Vec2 & lodBounds,const float cmpReference,const float result)753*35238bceSAndroid Build Coastguard Worker bool isTexCompareResultValid(const Texture2DView &texture, const Sampler &sampler, const TexComparePrecision &prec,
754*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, const Vec2 &lodBounds, const float cmpReference, const float result)
755*35238bceSAndroid Build Coastguard Worker {
756*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
757*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
758*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
759*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
760*35238bceSAndroid Build Coastguard Worker
761*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
762*35238bceSAndroid Build Coastguard Worker
763*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
764*35238bceSAndroid Build Coastguard Worker {
765*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, cmpReference,
766*35238bceSAndroid Build Coastguard Worker result))
767*35238bceSAndroid Build Coastguard Worker return true;
768*35238bceSAndroid Build Coastguard Worker }
769*35238bceSAndroid Build Coastguard Worker
770*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
771*35238bceSAndroid Build Coastguard Worker {
772*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
773*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
774*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
775*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
776*35238bceSAndroid Build Coastguard Worker
777*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel < maxTexLevel);
778*35238bceSAndroid Build Coastguard Worker
779*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap)
780*35238bceSAndroid Build Coastguard Worker {
781*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
782*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
783*35238bceSAndroid Build Coastguard Worker
784*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
785*35238bceSAndroid Build Coastguard Worker
786*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
787*35238bceSAndroid Build Coastguard Worker {
788*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
789*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
790*35238bceSAndroid Build Coastguard Worker
791*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
792*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coord, 0,
793*35238bceSAndroid Build Coastguard Worker Vec2(minF, maxF), cmpReference, result))
794*35238bceSAndroid Build Coastguard Worker return true;
795*35238bceSAndroid Build Coastguard Worker }
796*35238bceSAndroid Build Coastguard Worker }
797*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
798*35238bceSAndroid Build Coastguard Worker {
799*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
800*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
801*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
802*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
803*35238bceSAndroid Build Coastguard Worker
804*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
805*35238bceSAndroid Build Coastguard Worker
806*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
807*35238bceSAndroid Build Coastguard Worker {
808*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec,
809*35238bceSAndroid Build Coastguard Worker coord, 0, cmpReference, result))
810*35238bceSAndroid Build Coastguard Worker return true;
811*35238bceSAndroid Build Coastguard Worker }
812*35238bceSAndroid Build Coastguard Worker }
813*35238bceSAndroid Build Coastguard Worker else
814*35238bceSAndroid Build Coastguard Worker {
815*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, cmpReference,
816*35238bceSAndroid Build Coastguard Worker result))
817*35238bceSAndroid Build Coastguard Worker return true;
818*35238bceSAndroid Build Coastguard Worker }
819*35238bceSAndroid Build Coastguard Worker }
820*35238bceSAndroid Build Coastguard Worker
821*35238bceSAndroid Build Coastguard Worker return false;
822*35238bceSAndroid Build Coastguard Worker }
823*35238bceSAndroid Build Coastguard Worker
isSeamplessLinearMipmapLinearCompareResultValid(const TextureCubeView & texture,const int baseLevelNdx,const Sampler & sampler,const TexComparePrecision & prec,const CubeFaceFloatCoords & coords,const Vec2 & fBounds,const float cmpReference,const float result)824*35238bceSAndroid Build Coastguard Worker static bool isSeamplessLinearMipmapLinearCompareResultValid(const TextureCubeView &texture, const int baseLevelNdx,
825*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const TexComparePrecision &prec,
826*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords &coords, const Vec2 &fBounds,
827*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result)
828*35238bceSAndroid Build Coastguard Worker {
829*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth =
830*35238bceSAndroid Build Coastguard Worker isFixedPointDepthTextureFormat(texture.getLevelFace(baseLevelNdx, CUBEFACE_NEGATIVE_X).getFormat());
831*35238bceSAndroid Build Coastguard Worker const int size0 = texture.getLevelFace(baseLevelNdx, coords.face).getWidth();
832*35238bceSAndroid Build Coastguard Worker const int size1 = texture.getLevelFace(baseLevelNdx + 1, coords.face).getWidth();
833*35238bceSAndroid Build Coastguard Worker
834*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.s, prec.coordBits.x(),
835*35238bceSAndroid Build Coastguard Worker prec.uvwBits.x());
836*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.s, prec.coordBits.x(),
837*35238bceSAndroid Build Coastguard Worker prec.uvwBits.x());
838*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.t, prec.coordBits.y(),
839*35238bceSAndroid Build Coastguard Worker prec.uvwBits.y());
840*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.t, prec.coordBits.y(),
841*35238bceSAndroid Build Coastguard Worker prec.uvwBits.y());
842*35238bceSAndroid Build Coastguard Worker
843*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
844*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x() - 0.5f);
845*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y() - 0.5f);
846*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x() - 0.5f);
847*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y() - 0.5f);
848*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x() - 0.5f);
849*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y() - 0.5f);
850*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x() - 0.5f);
851*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y() - 0.5f);
852*35238bceSAndroid Build Coastguard Worker
853*35238bceSAndroid Build Coastguard Worker tcu::ConstPixelBufferAccess faces0[CUBEFACE_LAST];
854*35238bceSAndroid Build Coastguard Worker tcu::ConstPixelBufferAccess faces1[CUBEFACE_LAST];
855*35238bceSAndroid Build Coastguard Worker
856*35238bceSAndroid Build Coastguard Worker for (int face = 0; face < CUBEFACE_LAST; face++)
857*35238bceSAndroid Build Coastguard Worker {
858*35238bceSAndroid Build Coastguard Worker faces0[face] = texture.getLevelFace(baseLevelNdx, CubeFace(face));
859*35238bceSAndroid Build Coastguard Worker faces1[face] = texture.getLevelFace(baseLevelNdx + 1, CubeFace(face));
860*35238bceSAndroid Build Coastguard Worker }
861*35238bceSAndroid Build Coastguard Worker
862*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
863*35238bceSAndroid Build Coastguard Worker {
864*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
865*35238bceSAndroid Build Coastguard Worker {
866*35238bceSAndroid Build Coastguard Worker const float minA0 = de::clamp((uBounds0.x() - 0.5f) - float(i0), 0.0f, 1.0f);
867*35238bceSAndroid Build Coastguard Worker const float maxA0 = de::clamp((uBounds0.y() - 0.5f) - float(i0), 0.0f, 1.0f);
868*35238bceSAndroid Build Coastguard Worker const float minB0 = de::clamp((vBounds0.x() - 0.5f) - float(j0), 0.0f, 1.0f);
869*35238bceSAndroid Build Coastguard Worker const float maxB0 = de::clamp((vBounds0.y() - 0.5f) - float(j0), 0.0f, 1.0f);
870*35238bceSAndroid Build Coastguard Worker Vec4 depths0;
871*35238bceSAndroid Build Coastguard Worker
872*35238bceSAndroid Build Coastguard Worker {
873*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c00 =
874*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 0, j0 + 0)), size0);
875*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c10 =
876*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 1, j0 + 0)), size0);
877*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c01 =
878*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 0, j0 + 1)), size0);
879*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c11 =
880*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 1, j0 + 1)), size0);
881*35238bceSAndroid Build Coastguard Worker
882*35238bceSAndroid Build Coastguard Worker // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
883*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
884*35238bceSAndroid Build Coastguard Worker if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST ||
885*35238bceSAndroid Build Coastguard Worker c11.face == CUBEFACE_LAST)
886*35238bceSAndroid Build Coastguard Worker return true;
887*35238bceSAndroid Build Coastguard Worker
888*35238bceSAndroid Build Coastguard Worker depths0[0] = lookupDepthNoBorder(faces0[c00.face], sampler, c00.s, c00.t);
889*35238bceSAndroid Build Coastguard Worker depths0[1] = lookupDepthNoBorder(faces0[c10.face], sampler, c10.s, c10.t);
890*35238bceSAndroid Build Coastguard Worker depths0[2] = lookupDepthNoBorder(faces0[c01.face], sampler, c01.s, c01.t);
891*35238bceSAndroid Build Coastguard Worker depths0[3] = lookupDepthNoBorder(faces0[c11.face], sampler, c11.s, c11.t);
892*35238bceSAndroid Build Coastguard Worker }
893*35238bceSAndroid Build Coastguard Worker
894*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
895*35238bceSAndroid Build Coastguard Worker {
896*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
897*35238bceSAndroid Build Coastguard Worker {
898*35238bceSAndroid Build Coastguard Worker const float minA1 = de::clamp((uBounds1.x() - 0.5f) - float(i1), 0.0f, 1.0f);
899*35238bceSAndroid Build Coastguard Worker const float maxA1 = de::clamp((uBounds1.y() - 0.5f) - float(i1), 0.0f, 1.0f);
900*35238bceSAndroid Build Coastguard Worker const float minB1 = de::clamp((vBounds1.x() - 0.5f) - float(j1), 0.0f, 1.0f);
901*35238bceSAndroid Build Coastguard Worker const float maxB1 = de::clamp((vBounds1.y() - 0.5f) - float(j1), 0.0f, 1.0f);
902*35238bceSAndroid Build Coastguard Worker Vec4 depths1;
903*35238bceSAndroid Build Coastguard Worker
904*35238bceSAndroid Build Coastguard Worker {
905*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c00 =
906*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 0, j1 + 0)), size1);
907*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c10 =
908*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 1, j1 + 0)), size1);
909*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c01 =
910*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 0, j1 + 1)), size1);
911*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c11 =
912*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 1, j1 + 1)), size1);
913*35238bceSAndroid Build Coastguard Worker
914*35238bceSAndroid Build Coastguard Worker if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST ||
915*35238bceSAndroid Build Coastguard Worker c11.face == CUBEFACE_LAST)
916*35238bceSAndroid Build Coastguard Worker return true;
917*35238bceSAndroid Build Coastguard Worker
918*35238bceSAndroid Build Coastguard Worker depths1[0] = lookupDepthNoBorder(faces1[c00.face], sampler, c00.s, c00.t);
919*35238bceSAndroid Build Coastguard Worker depths1[1] = lookupDepthNoBorder(faces1[c10.face], sampler, c10.s, c10.t);
920*35238bceSAndroid Build Coastguard Worker depths1[2] = lookupDepthNoBorder(faces1[c01.face], sampler, c01.s, c01.t);
921*35238bceSAndroid Build Coastguard Worker depths1[3] = lookupDepthNoBorder(faces1[c11.face], sampler, c11.s, c11.t);
922*35238bceSAndroid Build Coastguard Worker }
923*35238bceSAndroid Build Coastguard Worker
924*35238bceSAndroid Build Coastguard Worker if (isTrilinearCompareValid(sampler.compare, prec, depths0, depths1, Vec2(minA0, maxA0),
925*35238bceSAndroid Build Coastguard Worker Vec2(minB0, maxB0), Vec2(minA1, maxA1), Vec2(minB1, maxB1), fBounds,
926*35238bceSAndroid Build Coastguard Worker cmpReference, result, isFixedPointDepth))
927*35238bceSAndroid Build Coastguard Worker return true;
928*35238bceSAndroid Build Coastguard Worker }
929*35238bceSAndroid Build Coastguard Worker }
930*35238bceSAndroid Build Coastguard Worker }
931*35238bceSAndroid Build Coastguard Worker }
932*35238bceSAndroid Build Coastguard Worker
933*35238bceSAndroid Build Coastguard Worker return false;
934*35238bceSAndroid Build Coastguard Worker }
935*35238bceSAndroid Build Coastguard Worker
isCubeMipmapLinearCompareResultValid(const TextureCubeView & texture,const int baseLevelNdx,const Sampler & sampler,const Sampler::FilterMode levelFilter,const TexComparePrecision & prec,const CubeFaceFloatCoords & coords,const Vec2 & fBounds,const float cmpReference,const float result)936*35238bceSAndroid Build Coastguard Worker static bool isCubeMipmapLinearCompareResultValid(const TextureCubeView &texture, const int baseLevelNdx,
937*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
938*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const CubeFaceFloatCoords &coords,
939*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const float cmpReference, const float result)
940*35238bceSAndroid Build Coastguard Worker {
941*35238bceSAndroid Build Coastguard Worker if (levelFilter == Sampler::LINEAR)
942*35238bceSAndroid Build Coastguard Worker {
943*35238bceSAndroid Build Coastguard Worker if (sampler.seamlessCubeMap)
944*35238bceSAndroid Build Coastguard Worker return isSeamplessLinearMipmapLinearCompareResultValid(texture, baseLevelNdx, sampler, prec, coords,
945*35238bceSAndroid Build Coastguard Worker fBounds, cmpReference, result);
946*35238bceSAndroid Build Coastguard Worker else
947*35238bceSAndroid Build Coastguard Worker return isLinearMipmapLinearCompareResultValid(
948*35238bceSAndroid Build Coastguard Worker texture.getLevelFace(baseLevelNdx, coords.face), texture.getLevelFace(baseLevelNdx + 1, coords.face),
949*35238bceSAndroid Build Coastguard Worker sampler, prec, Vec2(coords.s, coords.t), 0, fBounds, cmpReference, result);
950*35238bceSAndroid Build Coastguard Worker }
951*35238bceSAndroid Build Coastguard Worker else
952*35238bceSAndroid Build Coastguard Worker return isNearestMipmapLinearCompareResultValid(
953*35238bceSAndroid Build Coastguard Worker texture.getLevelFace(baseLevelNdx, coords.face), texture.getLevelFace(baseLevelNdx + 1, coords.face),
954*35238bceSAndroid Build Coastguard Worker sampler, prec, Vec2(coords.s, coords.t), 0, fBounds, cmpReference, result);
955*35238bceSAndroid Build Coastguard Worker }
956*35238bceSAndroid Build Coastguard Worker
isSeamlessLinearCompareResultValid(const TextureCubeView & texture,const int levelNdx,const Sampler & sampler,const TexComparePrecision & prec,const CubeFaceFloatCoords & coords,const float cmpReference,const float result)957*35238bceSAndroid Build Coastguard Worker static bool isSeamlessLinearCompareResultValid(const TextureCubeView &texture, const int levelNdx,
958*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const TexComparePrecision &prec,
959*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords &coords, const float cmpReference,
960*35238bceSAndroid Build Coastguard Worker const float result)
961*35238bceSAndroid Build Coastguard Worker {
962*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth =
963*35238bceSAndroid Build Coastguard Worker isFixedPointDepthTextureFormat(texture.getLevelFace(levelNdx, CUBEFACE_NEGATIVE_X).getFormat());
964*35238bceSAndroid Build Coastguard Worker const int size = texture.getLevelFace(levelNdx, coords.face).getWidth();
965*35238bceSAndroid Build Coastguard Worker
966*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds =
967*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
968*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds =
969*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());
970*35238bceSAndroid Build Coastguard Worker
971*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
972*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
973*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
974*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
975*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
976*35238bceSAndroid Build Coastguard Worker
977*35238bceSAndroid Build Coastguard Worker // Face accesses
978*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
979*35238bceSAndroid Build Coastguard Worker for (int face = 0; face < CUBEFACE_LAST; face++)
980*35238bceSAndroid Build Coastguard Worker faces[face] = texture.getLevelFace(levelNdx, CubeFace(face));
981*35238bceSAndroid Build Coastguard Worker
982*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
983*35238bceSAndroid Build Coastguard Worker {
984*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
985*35238bceSAndroid Build Coastguard Worker {
986*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c00 =
987*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 0, j + 0)), size);
988*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c10 =
989*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 1, j + 0)), size);
990*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c01 =
991*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 0, j + 1)), size);
992*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c11 =
993*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 1, j + 1)), size);
994*35238bceSAndroid Build Coastguard Worker
995*35238bceSAndroid Build Coastguard Worker // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
996*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
997*35238bceSAndroid Build Coastguard Worker if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST ||
998*35238bceSAndroid Build Coastguard Worker c11.face == CUBEFACE_LAST)
999*35238bceSAndroid Build Coastguard Worker return true;
1000*35238bceSAndroid Build Coastguard Worker
1001*35238bceSAndroid Build Coastguard Worker // Bounds for filtering factors
1002*35238bceSAndroid Build Coastguard Worker const float minA = de::clamp((uBounds.x() - 0.5f) - float(i), 0.0f, 1.0f);
1003*35238bceSAndroid Build Coastguard Worker const float maxA = de::clamp((uBounds.y() - 0.5f) - float(i), 0.0f, 1.0f);
1004*35238bceSAndroid Build Coastguard Worker const float minB = de::clamp((vBounds.x() - 0.5f) - float(j), 0.0f, 1.0f);
1005*35238bceSAndroid Build Coastguard Worker const float maxB = de::clamp((vBounds.y() - 0.5f) - float(j), 0.0f, 1.0f);
1006*35238bceSAndroid Build Coastguard Worker
1007*35238bceSAndroid Build Coastguard Worker Vec4 depths;
1008*35238bceSAndroid Build Coastguard Worker depths[0] = lookupDepthNoBorder(faces[c00.face], sampler, c00.s, c00.t);
1009*35238bceSAndroid Build Coastguard Worker depths[1] = lookupDepthNoBorder(faces[c10.face], sampler, c10.s, c10.t);
1010*35238bceSAndroid Build Coastguard Worker depths[2] = lookupDepthNoBorder(faces[c01.face], sampler, c01.s, c01.t);
1011*35238bceSAndroid Build Coastguard Worker depths[3] = lookupDepthNoBorder(faces[c11.face], sampler, c11.s, c11.t);
1012*35238bceSAndroid Build Coastguard Worker
1013*35238bceSAndroid Build Coastguard Worker if (isBilinearCompareValid(sampler.compare, prec, depths, Vec2(minA, maxA), Vec2(minB, maxB), cmpReference,
1014*35238bceSAndroid Build Coastguard Worker result, isFixedPointDepth))
1015*35238bceSAndroid Build Coastguard Worker return true;
1016*35238bceSAndroid Build Coastguard Worker }
1017*35238bceSAndroid Build Coastguard Worker }
1018*35238bceSAndroid Build Coastguard Worker
1019*35238bceSAndroid Build Coastguard Worker return false;
1020*35238bceSAndroid Build Coastguard Worker }
1021*35238bceSAndroid Build Coastguard Worker
isCubeLevelCompareResultValid(const TextureCubeView & texture,const int levelNdx,const Sampler & sampler,const Sampler::FilterMode filterMode,const TexComparePrecision & prec,const CubeFaceFloatCoords & coords,const float cmpReference,const float result)1022*35238bceSAndroid Build Coastguard Worker static bool isCubeLevelCompareResultValid(const TextureCubeView &texture, const int levelNdx, const Sampler &sampler,
1023*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode, const TexComparePrecision &prec,
1024*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords &coords, const float cmpReference,
1025*35238bceSAndroid Build Coastguard Worker const float result)
1026*35238bceSAndroid Build Coastguard Worker {
1027*35238bceSAndroid Build Coastguard Worker if (filterMode == Sampler::LINEAR)
1028*35238bceSAndroid Build Coastguard Worker {
1029*35238bceSAndroid Build Coastguard Worker if (sampler.seamlessCubeMap)
1030*35238bceSAndroid Build Coastguard Worker return isSeamlessLinearCompareResultValid(texture, levelNdx, sampler, prec, coords, cmpReference, result);
1031*35238bceSAndroid Build Coastguard Worker else
1032*35238bceSAndroid Build Coastguard Worker return isLinearCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec,
1033*35238bceSAndroid Build Coastguard Worker Vec2(coords.s, coords.t), 0, cmpReference, result);
1034*35238bceSAndroid Build Coastguard Worker }
1035*35238bceSAndroid Build Coastguard Worker else
1036*35238bceSAndroid Build Coastguard Worker return isNearestCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec,
1037*35238bceSAndroid Build Coastguard Worker Vec2(coords.s, coords.t), 0, cmpReference, result);
1038*35238bceSAndroid Build Coastguard Worker }
1039*35238bceSAndroid Build Coastguard Worker
isCubeLevelCompareResultValid(const TextureCubeArrayView & texture,const int baseLevelNdx,const Sampler & sampler,const Sampler::FilterMode filterMode,const TexComparePrecision & prec,const CubeFaceFloatCoords & coords,const float depth,const float cmpReference,const float result)1040*35238bceSAndroid Build Coastguard Worker static bool isCubeLevelCompareResultValid(const TextureCubeArrayView &texture, const int baseLevelNdx,
1041*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode filterMode,
1042*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const CubeFaceFloatCoords &coords,
1043*35238bceSAndroid Build Coastguard Worker const float depth, const float cmpReference, const float result)
1044*35238bceSAndroid Build Coastguard Worker {
1045*35238bceSAndroid Build Coastguard Worker const float depthErr =
1046*35238bceSAndroid Build Coastguard Worker computeFloatingPointError(depth, prec.coordBits.z()) + computeFixedPointError(prec.uvwBits.z());
1047*35238bceSAndroid Build Coastguard Worker const float minZ = depth - depthErr;
1048*35238bceSAndroid Build Coastguard Worker const float maxZ = depth + depthErr;
1049*35238bceSAndroid Build Coastguard Worker const int minLayer = de::clamp(deFloorFloatToInt32(minZ + 0.5f), 0, texture.getNumLayers() - 1);
1050*35238bceSAndroid Build Coastguard Worker const int maxLayer = de::clamp(deFloorFloatToInt32(maxZ + 0.5f), 0, texture.getNumLayers() - 1);
1051*35238bceSAndroid Build Coastguard Worker const int numLevels = texture.getNumLevels();
1052*35238bceSAndroid Build Coastguard Worker
1053*35238bceSAndroid Build Coastguard Worker for (int layer = minLayer; layer <= maxLayer; layer++)
1054*35238bceSAndroid Build Coastguard Worker {
1055*35238bceSAndroid Build Coastguard Worker std::vector<tcu::ConstPixelBufferAccess> levelsAtLayer[CUBEFACE_LAST];
1056*35238bceSAndroid Build Coastguard Worker
1057*35238bceSAndroid Build Coastguard Worker for (int faceNdx = 0; faceNdx < CUBEFACE_LAST; faceNdx++)
1058*35238bceSAndroid Build Coastguard Worker {
1059*35238bceSAndroid Build Coastguard Worker levelsAtLayer[faceNdx].resize(numLevels);
1060*35238bceSAndroid Build Coastguard Worker
1061*35238bceSAndroid Build Coastguard Worker for (int levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1062*35238bceSAndroid Build Coastguard Worker {
1063*35238bceSAndroid Build Coastguard Worker const tcu::ConstPixelBufferAccess &level = texture.getLevel(levelNdx);
1064*35238bceSAndroid Build Coastguard Worker
1065*35238bceSAndroid Build Coastguard Worker levelsAtLayer[faceNdx][levelNdx] =
1066*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1,
1067*35238bceSAndroid Build Coastguard Worker level.getPixelPtr(0, 0, CUBEFACE_LAST * layer + faceNdx));
1068*35238bceSAndroid Build Coastguard Worker }
1069*35238bceSAndroid Build Coastguard Worker }
1070*35238bceSAndroid Build Coastguard Worker
1071*35238bceSAndroid Build Coastguard Worker const tcu::ConstPixelBufferAccess *levels[CUBEFACE_LAST]{
1072*35238bceSAndroid Build Coastguard Worker // Such a strange order due to sampleCompare TextureCubeArrayView uses getCubeArrayFaceIndex while in TextureCubeView does not
1073*35238bceSAndroid Build Coastguard Worker &levelsAtLayer[1][0], &levelsAtLayer[0][0], &levelsAtLayer[3][0],
1074*35238bceSAndroid Build Coastguard Worker &levelsAtLayer[2][0], &levelsAtLayer[5][0], &levelsAtLayer[4][0],
1075*35238bceSAndroid Build Coastguard Worker };
1076*35238bceSAndroid Build Coastguard Worker
1077*35238bceSAndroid Build Coastguard Worker if (isCubeLevelCompareResultValid(TextureCubeView(numLevels, levels), baseLevelNdx, sampler, filterMode, prec,
1078*35238bceSAndroid Build Coastguard Worker coords, cmpReference, result))
1079*35238bceSAndroid Build Coastguard Worker return true;
1080*35238bceSAndroid Build Coastguard Worker }
1081*35238bceSAndroid Build Coastguard Worker
1082*35238bceSAndroid Build Coastguard Worker return false;
1083*35238bceSAndroid Build Coastguard Worker }
1084*35238bceSAndroid Build Coastguard Worker
isCubeMipmapLinearCompareResultValid(const TextureCubeArrayView & texture,const int baseLevelNdx,const Sampler & sampler,const Sampler::FilterMode levelFilter,const TexComparePrecision & prec,const CubeFaceFloatCoords & coords,const float depth,const Vec2 & fBounds,const float cmpReference,const float result)1085*35238bceSAndroid Build Coastguard Worker static bool isCubeMipmapLinearCompareResultValid(const TextureCubeArrayView &texture, const int baseLevelNdx,
1086*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
1087*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const CubeFaceFloatCoords &coords,
1088*35238bceSAndroid Build Coastguard Worker const float depth, const Vec2 &fBounds, const float cmpReference,
1089*35238bceSAndroid Build Coastguard Worker const float result)
1090*35238bceSAndroid Build Coastguard Worker {
1091*35238bceSAndroid Build Coastguard Worker const float depthErr =
1092*35238bceSAndroid Build Coastguard Worker computeFloatingPointError(depth, prec.coordBits.z()) + computeFixedPointError(prec.uvwBits.z());
1093*35238bceSAndroid Build Coastguard Worker const float minZ = depth - depthErr;
1094*35238bceSAndroid Build Coastguard Worker const float maxZ = depth + depthErr;
1095*35238bceSAndroid Build Coastguard Worker const int minLayer = de::clamp(deFloorFloatToInt32(minZ + 0.5f), 0, texture.getNumLayers() - 1);
1096*35238bceSAndroid Build Coastguard Worker const int maxLayer = de::clamp(deFloorFloatToInt32(maxZ + 0.5f), 0, texture.getNumLayers() - 1);
1097*35238bceSAndroid Build Coastguard Worker const int numLevels = texture.getNumLevels();
1098*35238bceSAndroid Build Coastguard Worker
1099*35238bceSAndroid Build Coastguard Worker for (int layer = minLayer; layer <= maxLayer; layer++)
1100*35238bceSAndroid Build Coastguard Worker {
1101*35238bceSAndroid Build Coastguard Worker std::vector<tcu::ConstPixelBufferAccess> levelsAtLayer[CUBEFACE_LAST];
1102*35238bceSAndroid Build Coastguard Worker
1103*35238bceSAndroid Build Coastguard Worker for (int faceNdx = 0; faceNdx < CUBEFACE_LAST; faceNdx++)
1104*35238bceSAndroid Build Coastguard Worker {
1105*35238bceSAndroid Build Coastguard Worker levelsAtLayer[faceNdx].resize(numLevels);
1106*35238bceSAndroid Build Coastguard Worker
1107*35238bceSAndroid Build Coastguard Worker for (int levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1108*35238bceSAndroid Build Coastguard Worker {
1109*35238bceSAndroid Build Coastguard Worker const tcu::ConstPixelBufferAccess &level = texture.getLevel(levelNdx);
1110*35238bceSAndroid Build Coastguard Worker
1111*35238bceSAndroid Build Coastguard Worker levelsAtLayer[faceNdx][levelNdx] =
1112*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1,
1113*35238bceSAndroid Build Coastguard Worker level.getPixelPtr(0, 0, CUBEFACE_LAST * layer + faceNdx));
1114*35238bceSAndroid Build Coastguard Worker }
1115*35238bceSAndroid Build Coastguard Worker }
1116*35238bceSAndroid Build Coastguard Worker
1117*35238bceSAndroid Build Coastguard Worker const tcu::ConstPixelBufferAccess *levels[CUBEFACE_LAST]{
1118*35238bceSAndroid Build Coastguard Worker // Such a strange order due to sampleCompare TextureCubeArrayView uses getCubeArrayFaceIndex while in TextureCubeView does not
1119*35238bceSAndroid Build Coastguard Worker &levelsAtLayer[1][0], &levelsAtLayer[0][0], &levelsAtLayer[3][0],
1120*35238bceSAndroid Build Coastguard Worker &levelsAtLayer[2][0], &levelsAtLayer[5][0], &levelsAtLayer[4][0],
1121*35238bceSAndroid Build Coastguard Worker };
1122*35238bceSAndroid Build Coastguard Worker
1123*35238bceSAndroid Build Coastguard Worker if (isCubeMipmapLinearCompareResultValid(TextureCubeView(numLevels, levels), baseLevelNdx, sampler, levelFilter,
1124*35238bceSAndroid Build Coastguard Worker prec, coords, fBounds, cmpReference, result))
1125*35238bceSAndroid Build Coastguard Worker return true;
1126*35238bceSAndroid Build Coastguard Worker }
1127*35238bceSAndroid Build Coastguard Worker
1128*35238bceSAndroid Build Coastguard Worker return false;
1129*35238bceSAndroid Build Coastguard Worker }
1130*35238bceSAndroid Build Coastguard Worker
isNearestCompareResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const TexComparePrecision & prec,const Vec1 & coord,const int coordZ,const float cmpReference,const float result)1131*35238bceSAndroid Build Coastguard Worker static bool isNearestCompareResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
1132*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec1 &coord, const int coordZ,
1133*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result)
1134*35238bceSAndroid Build Coastguard Worker {
1135*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level.getFormat());
1136*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
1137*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
1138*35238bceSAndroid Build Coastguard Worker
1139*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
1140*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x());
1141*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y());
1142*35238bceSAndroid Build Coastguard Worker
1143*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
1144*35238bceSAndroid Build Coastguard Worker {
1145*35238bceSAndroid Build Coastguard Worker const int x = wrap(sampler.wrapS, i, level.getWidth());
1146*35238bceSAndroid Build Coastguard Worker const float depth = lookupDepth(level, sampler, x, coordZ, 0);
1147*35238bceSAndroid Build Coastguard Worker const CmpResultSet resSet =
1148*35238bceSAndroid Build Coastguard Worker execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);
1149*35238bceSAndroid Build Coastguard Worker
1150*35238bceSAndroid Build Coastguard Worker if (isResultInSet(resSet, result, prec.resultBits))
1151*35238bceSAndroid Build Coastguard Worker return true;
1152*35238bceSAndroid Build Coastguard Worker }
1153*35238bceSAndroid Build Coastguard Worker
1154*35238bceSAndroid Build Coastguard Worker return false;
1155*35238bceSAndroid Build Coastguard Worker }
1156*35238bceSAndroid Build Coastguard Worker
isLinearCompareResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const TexComparePrecision & prec,const Vec1 & coord,const int coordZ,const float cmpReference,const float result)1157*35238bceSAndroid Build Coastguard Worker static bool isLinearCompareResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
1158*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec1 &coord, const int coordZ,
1159*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result)
1160*35238bceSAndroid Build Coastguard Worker {
1161*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level.getFormat());
1162*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
1163*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
1164*35238bceSAndroid Build Coastguard Worker
1165*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
1166*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
1167*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
1168*35238bceSAndroid Build Coastguard Worker
1169*35238bceSAndroid Build Coastguard Worker const int w = level.getWidth();
1170*35238bceSAndroid Build Coastguard Worker
1171*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
1172*35238bceSAndroid Build Coastguard Worker
1173*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
1174*35238bceSAndroid Build Coastguard Worker {
1175*35238bceSAndroid Build Coastguard Worker // Wrapped coordinates
1176*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i, w);
1177*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i + 1, w);
1178*35238bceSAndroid Build Coastguard Worker
1179*35238bceSAndroid Build Coastguard Worker // Bounds for filtering factors
1180*35238bceSAndroid Build Coastguard Worker const float minA = de::clamp((uBounds.x() - 0.5f) - float(i), 0.0f, 1.0f);
1181*35238bceSAndroid Build Coastguard Worker const float maxA = de::clamp((uBounds.y() - 0.5f) - float(i), 0.0f, 1.0f);
1182*35238bceSAndroid Build Coastguard Worker
1183*35238bceSAndroid Build Coastguard Worker const Vec2 depths(lookupDepth(level, sampler, x0, coordZ, 0), lookupDepth(level, sampler, x1, coordZ, 0));
1184*35238bceSAndroid Build Coastguard Worker
1185*35238bceSAndroid Build Coastguard Worker if (isLinearCompareValid(sampler.compare, prec, depths, Vec2(minA, maxA), cmpReference, result,
1186*35238bceSAndroid Build Coastguard Worker isFixedPointDepth))
1187*35238bceSAndroid Build Coastguard Worker return true;
1188*35238bceSAndroid Build Coastguard Worker }
1189*35238bceSAndroid Build Coastguard Worker
1190*35238bceSAndroid Build Coastguard Worker return false;
1191*35238bceSAndroid Build Coastguard Worker }
1192*35238bceSAndroid Build Coastguard Worker
isLevelCompareResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const Sampler::FilterMode filterMode,const TexComparePrecision & prec,const Vec1 & coord,const int coordZ,const float cmpReference,const float result)1193*35238bceSAndroid Build Coastguard Worker static bool isLevelCompareResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
1194*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode, const TexComparePrecision &prec,
1195*35238bceSAndroid Build Coastguard Worker const Vec1 &coord, const int coordZ, const float cmpReference, const float result)
1196*35238bceSAndroid Build Coastguard Worker {
1197*35238bceSAndroid Build Coastguard Worker if (filterMode == Sampler::LINEAR)
1198*35238bceSAndroid Build Coastguard Worker return isLinearCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
1199*35238bceSAndroid Build Coastguard Worker else
1200*35238bceSAndroid Build Coastguard Worker return isNearestCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
1201*35238bceSAndroid Build Coastguard Worker }
1202*35238bceSAndroid Build Coastguard Worker
isNearestMipmapLinearCompareResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const TexComparePrecision & prec,const Vec1 & coord,const int coordZ,const Vec2 & fBounds,const float cmpReference,const float result)1203*35238bceSAndroid Build Coastguard Worker static bool isNearestMipmapLinearCompareResultValid(const ConstPixelBufferAccess &level0,
1204*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
1205*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec1 &coord,
1206*35238bceSAndroid Build Coastguard Worker const int coordZ, const Vec2 &fBounds, const float cmpReference,
1207*35238bceSAndroid Build Coastguard Worker const float result)
1208*35238bceSAndroid Build Coastguard Worker {
1209*35238bceSAndroid Build Coastguard Worker DE_UNREF(fBounds);
1210*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level0.getFormat());
1211*35238bceSAndroid Build Coastguard Worker
1212*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
1213*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
1214*35238bceSAndroid Build Coastguard Worker
1215*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
1216*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1217*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
1218*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1219*35238bceSAndroid Build Coastguard Worker
1220*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
1221*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x());
1222*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y());
1223*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x());
1224*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y());
1225*35238bceSAndroid Build Coastguard Worker
1226*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
1227*35238bceSAndroid Build Coastguard Worker {
1228*35238bceSAndroid Build Coastguard Worker const float depth0 = lookupDepth(level0, sampler, wrap(sampler.wrapS, i0, w0), coordZ, 0);
1229*35238bceSAndroid Build Coastguard Worker
1230*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
1231*35238bceSAndroid Build Coastguard Worker {
1232*35238bceSAndroid Build Coastguard Worker const float depth1 = lookupDepth(level1, sampler, wrap(sampler.wrapS, i1, w1), coordZ, 0);
1233*35238bceSAndroid Build Coastguard Worker
1234*35238bceSAndroid Build Coastguard Worker if (isLinearCompareValid(sampler.compare, prec, Vec2(depth0, depth1), fBounds, cmpReference, result,
1235*35238bceSAndroid Build Coastguard Worker isFixedPointDepth))
1236*35238bceSAndroid Build Coastguard Worker return true;
1237*35238bceSAndroid Build Coastguard Worker }
1238*35238bceSAndroid Build Coastguard Worker }
1239*35238bceSAndroid Build Coastguard Worker
1240*35238bceSAndroid Build Coastguard Worker return false;
1241*35238bceSAndroid Build Coastguard Worker }
1242*35238bceSAndroid Build Coastguard Worker
isLinearMipmapLinearCompareResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const TexComparePrecision & prec,const Vec1 & coord,const int coordZ,const Vec2 & fBounds,const float cmpReference,const float result)1243*35238bceSAndroid Build Coastguard Worker static bool isLinearMipmapLinearCompareResultValid(const ConstPixelBufferAccess &level0,
1244*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
1245*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec1 &coord, const int coordZ,
1246*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const float cmpReference, const float result)
1247*35238bceSAndroid Build Coastguard Worker {
1248*35238bceSAndroid Build Coastguard Worker DE_UNREF(fBounds);
1249*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(level0.getFormat());
1250*35238bceSAndroid Build Coastguard Worker
1251*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
1252*35238bceSAndroid Build Coastguard Worker // Right now this allows pairing any two valid bilinear quads.
1253*35238bceSAndroid Build Coastguard Worker
1254*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
1255*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
1256*35238bceSAndroid Build Coastguard Worker
1257*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
1258*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1259*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
1260*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1261*35238bceSAndroid Build Coastguard Worker
1262*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
1263*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x() - 0.5f);
1264*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y() - 0.5f);
1265*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x() - 0.5f);
1266*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y() - 0.5f);
1267*35238bceSAndroid Build Coastguard Worker
1268*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
1269*35238bceSAndroid Build Coastguard Worker {
1270*35238bceSAndroid Build Coastguard Worker const float minA0 = de::clamp((uBounds0.x() - 0.5f) - float(i0), 0.0f, 1.0f);
1271*35238bceSAndroid Build Coastguard Worker const float maxA0 = de::clamp((uBounds0.y() - 0.5f) - float(i0), 0.0f, 1.0f);
1272*35238bceSAndroid Build Coastguard Worker const Vec2 ptA0 = Vec2(minA0, maxA0);
1273*35238bceSAndroid Build Coastguard Worker Vec4 depths;
1274*35238bceSAndroid Build Coastguard Worker
1275*35238bceSAndroid Build Coastguard Worker {
1276*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i0, w0);
1277*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i0 + 1, w0);
1278*35238bceSAndroid Build Coastguard Worker
1279*35238bceSAndroid Build Coastguard Worker depths[0] = lookupDepth(level0, sampler, x0, coordZ, 0);
1280*35238bceSAndroid Build Coastguard Worker depths[1] = lookupDepth(level0, sampler, x1, coordZ, 0);
1281*35238bceSAndroid Build Coastguard Worker }
1282*35238bceSAndroid Build Coastguard Worker
1283*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
1284*35238bceSAndroid Build Coastguard Worker {
1285*35238bceSAndroid Build Coastguard Worker const float minA1 = de::clamp((uBounds1.x() - 0.5f) - float(i1), 0.0f, 1.0f);
1286*35238bceSAndroid Build Coastguard Worker const float maxA1 = de::clamp((uBounds1.y() - 0.5f) - float(i1), 0.0f, 1.0f);
1287*35238bceSAndroid Build Coastguard Worker const Vec2 ptA1 = Vec2(minA1, maxA1);
1288*35238bceSAndroid Build Coastguard Worker
1289*35238bceSAndroid Build Coastguard Worker {
1290*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i1, w1);
1291*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i1 + 1, w1);
1292*35238bceSAndroid Build Coastguard Worker
1293*35238bceSAndroid Build Coastguard Worker depths[2] = lookupDepth(level1, sampler, x0, coordZ, 0);
1294*35238bceSAndroid Build Coastguard Worker depths[3] = lookupDepth(level1, sampler, x1, coordZ, 0);
1295*35238bceSAndroid Build Coastguard Worker }
1296*35238bceSAndroid Build Coastguard Worker
1297*35238bceSAndroid Build Coastguard Worker if (isBilinearCompareValid(sampler.compare, prec, depths, ptA0, ptA1, cmpReference, result,
1298*35238bceSAndroid Build Coastguard Worker isFixedPointDepth))
1299*35238bceSAndroid Build Coastguard Worker return true;
1300*35238bceSAndroid Build Coastguard Worker }
1301*35238bceSAndroid Build Coastguard Worker }
1302*35238bceSAndroid Build Coastguard Worker
1303*35238bceSAndroid Build Coastguard Worker return false;
1304*35238bceSAndroid Build Coastguard Worker }
1305*35238bceSAndroid Build Coastguard Worker
isMipmapLinearCompareResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const Sampler::FilterMode levelFilter,const TexComparePrecision & prec,const Vec1 & coord,const int coordZ,const Vec2 & fBounds,const float cmpReference,const float result)1306*35238bceSAndroid Build Coastguard Worker static bool isMipmapLinearCompareResultValid(const ConstPixelBufferAccess &level0, const ConstPixelBufferAccess &level1,
1307*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
1308*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec1 &coord, const int coordZ,
1309*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const float cmpReference, const float result)
1310*35238bceSAndroid Build Coastguard Worker {
1311*35238bceSAndroid Build Coastguard Worker if (levelFilter == Sampler::LINEAR)
1312*35238bceSAndroid Build Coastguard Worker return isLinearMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds,
1313*35238bceSAndroid Build Coastguard Worker cmpReference, result);
1314*35238bceSAndroid Build Coastguard Worker else
1315*35238bceSAndroid Build Coastguard Worker return isNearestMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds,
1316*35238bceSAndroid Build Coastguard Worker cmpReference, result);
1317*35238bceSAndroid Build Coastguard Worker }
1318*35238bceSAndroid Build Coastguard Worker
isTexCompareResultValid(const TextureCubeView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec3 & coord,const Vec2 & lodBounds,const float cmpReference,const float result)1319*35238bceSAndroid Build Coastguard Worker bool isTexCompareResultValid(const TextureCubeView &texture, const Sampler &sampler, const TexComparePrecision &prec,
1320*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, const Vec2 &lodBounds, const float cmpReference, const float result)
1321*35238bceSAndroid Build Coastguard Worker {
1322*35238bceSAndroid Build Coastguard Worker int numPossibleFaces = 0;
1323*35238bceSAndroid Build Coastguard Worker CubeFace possibleFaces[CUBEFACE_LAST];
1324*35238bceSAndroid Build Coastguard Worker
1325*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1326*35238bceSAndroid Build Coastguard Worker
1327*35238bceSAndroid Build Coastguard Worker getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);
1328*35238bceSAndroid Build Coastguard Worker
1329*35238bceSAndroid Build Coastguard Worker if (numPossibleFaces == 0)
1330*35238bceSAndroid Build Coastguard Worker return true; // Result is undefined.
1331*35238bceSAndroid Build Coastguard Worker
1332*35238bceSAndroid Build Coastguard Worker for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
1333*35238bceSAndroid Build Coastguard Worker {
1334*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx],
1335*35238bceSAndroid Build Coastguard Worker projectToFace(possibleFaces[tryFaceNdx], coord));
1336*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1337*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1338*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1339*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1340*35238bceSAndroid Build Coastguard Worker
1341*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1342*35238bceSAndroid Build Coastguard Worker {
1343*35238bceSAndroid Build Coastguard Worker if (isCubeLevelCompareResultValid(texture, 0, sampler, sampler.magFilter, prec, faceCoords, cmpReference,
1344*35238bceSAndroid Build Coastguard Worker result))
1345*35238bceSAndroid Build Coastguard Worker return true;
1346*35238bceSAndroid Build Coastguard Worker }
1347*35238bceSAndroid Build Coastguard Worker
1348*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1349*35238bceSAndroid Build Coastguard Worker {
1350*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1351*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1352*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1353*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1354*35238bceSAndroid Build Coastguard Worker
1355*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel < maxTexLevel);
1356*35238bceSAndroid Build Coastguard Worker
1357*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap)
1358*35238bceSAndroid Build Coastguard Worker {
1359*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1360*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1361*35238bceSAndroid Build Coastguard Worker
1362*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1363*35238bceSAndroid Build Coastguard Worker
1364*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1365*35238bceSAndroid Build Coastguard Worker {
1366*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1367*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1368*35238bceSAndroid Build Coastguard Worker
1369*35238bceSAndroid Build Coastguard Worker if (isCubeMipmapLinearCompareResultValid(texture, level, sampler, getLevelFilter(sampler.minFilter),
1370*35238bceSAndroid Build Coastguard Worker prec, faceCoords, Vec2(minF, maxF), cmpReference, result))
1371*35238bceSAndroid Build Coastguard Worker return true;
1372*35238bceSAndroid Build Coastguard Worker }
1373*35238bceSAndroid Build Coastguard Worker }
1374*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1375*35238bceSAndroid Build Coastguard Worker {
1376*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1377*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1378*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1379*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1380*35238bceSAndroid Build Coastguard Worker
1381*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1382*35238bceSAndroid Build Coastguard Worker
1383*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1384*35238bceSAndroid Build Coastguard Worker {
1385*35238bceSAndroid Build Coastguard Worker if (isCubeLevelCompareResultValid(texture, level, sampler, getLevelFilter(sampler.minFilter), prec,
1386*35238bceSAndroid Build Coastguard Worker faceCoords, cmpReference, result))
1387*35238bceSAndroid Build Coastguard Worker return true;
1388*35238bceSAndroid Build Coastguard Worker }
1389*35238bceSAndroid Build Coastguard Worker }
1390*35238bceSAndroid Build Coastguard Worker else
1391*35238bceSAndroid Build Coastguard Worker {
1392*35238bceSAndroid Build Coastguard Worker if (isCubeLevelCompareResultValid(texture, 0, sampler, sampler.minFilter, prec, faceCoords,
1393*35238bceSAndroid Build Coastguard Worker cmpReference, result))
1394*35238bceSAndroid Build Coastguard Worker return true;
1395*35238bceSAndroid Build Coastguard Worker }
1396*35238bceSAndroid Build Coastguard Worker }
1397*35238bceSAndroid Build Coastguard Worker }
1398*35238bceSAndroid Build Coastguard Worker
1399*35238bceSAndroid Build Coastguard Worker return false;
1400*35238bceSAndroid Build Coastguard Worker }
1401*35238bceSAndroid Build Coastguard Worker
isTexCompareResultValid(const Texture2DArrayView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec3 & coord,const Vec2 & lodBounds,const float cmpReference,const float result)1402*35238bceSAndroid Build Coastguard Worker bool isTexCompareResultValid(const Texture2DArrayView &texture, const Sampler &sampler, const TexComparePrecision &prec,
1403*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, const Vec2 &lodBounds, const float cmpReference, const float result)
1404*35238bceSAndroid Build Coastguard Worker {
1405*35238bceSAndroid Build Coastguard Worker const float depthErr =
1406*35238bceSAndroid Build Coastguard Worker computeFloatingPointError(coord.z(), prec.coordBits.z()) + computeFixedPointError(prec.uvwBits.z());
1407*35238bceSAndroid Build Coastguard Worker const float minZ = coord.z() - depthErr;
1408*35238bceSAndroid Build Coastguard Worker const float maxZ = coord.z() + depthErr;
1409*35238bceSAndroid Build Coastguard Worker const int minLayer = de::clamp(deFloorFloatToInt32(minZ + 0.5f), 0, texture.getNumLayers() - 1);
1410*35238bceSAndroid Build Coastguard Worker const int maxLayer = de::clamp(deFloorFloatToInt32(maxZ + 0.5f), 0, texture.getNumLayers() - 1);
1411*35238bceSAndroid Build Coastguard Worker
1412*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1413*35238bceSAndroid Build Coastguard Worker
1414*35238bceSAndroid Build Coastguard Worker for (int layer = minLayer; layer <= maxLayer; layer++)
1415*35238bceSAndroid Build Coastguard Worker {
1416*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1417*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1418*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1419*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1420*35238bceSAndroid Build Coastguard Worker
1421*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1422*35238bceSAndroid Build Coastguard Worker {
1423*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord.swizzle(0, 1),
1424*35238bceSAndroid Build Coastguard Worker layer, cmpReference, result))
1425*35238bceSAndroid Build Coastguard Worker return true;
1426*35238bceSAndroid Build Coastguard Worker }
1427*35238bceSAndroid Build Coastguard Worker
1428*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1429*35238bceSAndroid Build Coastguard Worker {
1430*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1431*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1432*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1433*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1434*35238bceSAndroid Build Coastguard Worker
1435*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel < maxTexLevel);
1436*35238bceSAndroid Build Coastguard Worker
1437*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap)
1438*35238bceSAndroid Build Coastguard Worker {
1439*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1440*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1441*35238bceSAndroid Build Coastguard Worker
1442*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1443*35238bceSAndroid Build Coastguard Worker
1444*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1445*35238bceSAndroid Build Coastguard Worker {
1446*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1447*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1448*35238bceSAndroid Build Coastguard Worker
1449*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
1450*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coord.swizzle(0, 1),
1451*35238bceSAndroid Build Coastguard Worker layer, Vec2(minF, maxF), cmpReference, result))
1452*35238bceSAndroid Build Coastguard Worker return true;
1453*35238bceSAndroid Build Coastguard Worker }
1454*35238bceSAndroid Build Coastguard Worker }
1455*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1456*35238bceSAndroid Build Coastguard Worker {
1457*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1458*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1459*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1460*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1461*35238bceSAndroid Build Coastguard Worker
1462*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1463*35238bceSAndroid Build Coastguard Worker
1464*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1465*35238bceSAndroid Build Coastguard Worker {
1466*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter),
1467*35238bceSAndroid Build Coastguard Worker prec, coord.swizzle(0, 1), layer, cmpReference, result))
1468*35238bceSAndroid Build Coastguard Worker return true;
1469*35238bceSAndroid Build Coastguard Worker }
1470*35238bceSAndroid Build Coastguard Worker }
1471*35238bceSAndroid Build Coastguard Worker else
1472*35238bceSAndroid Build Coastguard Worker {
1473*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec,
1474*35238bceSAndroid Build Coastguard Worker coord.swizzle(0, 1), layer, cmpReference, result))
1475*35238bceSAndroid Build Coastguard Worker return true;
1476*35238bceSAndroid Build Coastguard Worker }
1477*35238bceSAndroid Build Coastguard Worker }
1478*35238bceSAndroid Build Coastguard Worker }
1479*35238bceSAndroid Build Coastguard Worker
1480*35238bceSAndroid Build Coastguard Worker return false;
1481*35238bceSAndroid Build Coastguard Worker }
1482*35238bceSAndroid Build Coastguard Worker
isTexCompareResultValid(const Texture1DView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec1 & coord,const Vec2 & lodBounds,const float cmpReference,const float result)1483*35238bceSAndroid Build Coastguard Worker bool isTexCompareResultValid(const Texture1DView &texture, const Sampler &sampler, const TexComparePrecision &prec,
1484*35238bceSAndroid Build Coastguard Worker const Vec1 &coord, const Vec2 &lodBounds, const float cmpReference, const float result)
1485*35238bceSAndroid Build Coastguard Worker {
1486*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1487*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1488*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1489*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1490*35238bceSAndroid Build Coastguard Worker
1491*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1492*35238bceSAndroid Build Coastguard Worker
1493*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1494*35238bceSAndroid Build Coastguard Worker {
1495*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, cmpReference,
1496*35238bceSAndroid Build Coastguard Worker result))
1497*35238bceSAndroid Build Coastguard Worker return true;
1498*35238bceSAndroid Build Coastguard Worker }
1499*35238bceSAndroid Build Coastguard Worker
1500*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1501*35238bceSAndroid Build Coastguard Worker {
1502*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1503*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1504*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1505*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1506*35238bceSAndroid Build Coastguard Worker
1507*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel < maxTexLevel);
1508*35238bceSAndroid Build Coastguard Worker
1509*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap)
1510*35238bceSAndroid Build Coastguard Worker {
1511*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1512*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1513*35238bceSAndroid Build Coastguard Worker
1514*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1515*35238bceSAndroid Build Coastguard Worker
1516*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1517*35238bceSAndroid Build Coastguard Worker {
1518*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1519*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1520*35238bceSAndroid Build Coastguard Worker
1521*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
1522*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coord, 0,
1523*35238bceSAndroid Build Coastguard Worker Vec2(minF, maxF), cmpReference, result))
1524*35238bceSAndroid Build Coastguard Worker return true;
1525*35238bceSAndroid Build Coastguard Worker }
1526*35238bceSAndroid Build Coastguard Worker }
1527*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1528*35238bceSAndroid Build Coastguard Worker {
1529*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1530*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1531*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1532*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1533*35238bceSAndroid Build Coastguard Worker
1534*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1535*35238bceSAndroid Build Coastguard Worker
1536*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1537*35238bceSAndroid Build Coastguard Worker {
1538*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec,
1539*35238bceSAndroid Build Coastguard Worker coord, 0, cmpReference, result))
1540*35238bceSAndroid Build Coastguard Worker return true;
1541*35238bceSAndroid Build Coastguard Worker }
1542*35238bceSAndroid Build Coastguard Worker }
1543*35238bceSAndroid Build Coastguard Worker else
1544*35238bceSAndroid Build Coastguard Worker {
1545*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, cmpReference,
1546*35238bceSAndroid Build Coastguard Worker result))
1547*35238bceSAndroid Build Coastguard Worker return true;
1548*35238bceSAndroid Build Coastguard Worker }
1549*35238bceSAndroid Build Coastguard Worker }
1550*35238bceSAndroid Build Coastguard Worker
1551*35238bceSAndroid Build Coastguard Worker return false;
1552*35238bceSAndroid Build Coastguard Worker }
1553*35238bceSAndroid Build Coastguard Worker
isTexCompareResultValid(const Texture1DArrayView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,const Vec2 & lodBounds,const float cmpReference,const float result)1554*35238bceSAndroid Build Coastguard Worker bool isTexCompareResultValid(const Texture1DArrayView &texture, const Sampler &sampler, const TexComparePrecision &prec,
1555*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, const Vec2 &lodBounds, const float cmpReference, const float result)
1556*35238bceSAndroid Build Coastguard Worker {
1557*35238bceSAndroid Build Coastguard Worker const float depthErr = computeFloatingPointError(coord.y(), prec.coordBits.y()) +
1558*35238bceSAndroid Build Coastguard Worker computeFixedPointError(prec.uvwBits.y()); //\todo: should we go with y in prec?
1559*35238bceSAndroid Build Coastguard Worker const float minZ = coord.y() - depthErr;
1560*35238bceSAndroid Build Coastguard Worker const float maxZ = coord.y() + depthErr;
1561*35238bceSAndroid Build Coastguard Worker const int minLayer = de::clamp(deFloorFloatToInt32(minZ + 0.5f), 0, texture.getNumLayers() - 1);
1562*35238bceSAndroid Build Coastguard Worker const int maxLayer = de::clamp(deFloorFloatToInt32(maxZ + 0.5f), 0, texture.getNumLayers() - 1);
1563*35238bceSAndroid Build Coastguard Worker
1564*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1565*35238bceSAndroid Build Coastguard Worker
1566*35238bceSAndroid Build Coastguard Worker for (int layer = minLayer; layer <= maxLayer; layer++)
1567*35238bceSAndroid Build Coastguard Worker {
1568*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1569*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1570*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1571*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1572*35238bceSAndroid Build Coastguard Worker
1573*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1574*35238bceSAndroid Build Coastguard Worker {
1575*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, Vec1(coord.x()), layer,
1576*35238bceSAndroid Build Coastguard Worker cmpReference, result))
1577*35238bceSAndroid Build Coastguard Worker return true;
1578*35238bceSAndroid Build Coastguard Worker }
1579*35238bceSAndroid Build Coastguard Worker
1580*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1581*35238bceSAndroid Build Coastguard Worker {
1582*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1583*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1584*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1585*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1586*35238bceSAndroid Build Coastguard Worker
1587*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel < maxTexLevel);
1588*35238bceSAndroid Build Coastguard Worker
1589*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap)
1590*35238bceSAndroid Build Coastguard Worker {
1591*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1592*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1593*35238bceSAndroid Build Coastguard Worker
1594*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1595*35238bceSAndroid Build Coastguard Worker
1596*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1597*35238bceSAndroid Build Coastguard Worker {
1598*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1599*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1600*35238bceSAndroid Build Coastguard Worker
1601*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
1602*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, Vec1(coord.x()),
1603*35238bceSAndroid Build Coastguard Worker layer, Vec2(minF, maxF), cmpReference, result))
1604*35238bceSAndroid Build Coastguard Worker return true;
1605*35238bceSAndroid Build Coastguard Worker }
1606*35238bceSAndroid Build Coastguard Worker }
1607*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1608*35238bceSAndroid Build Coastguard Worker {
1609*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1610*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1611*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1612*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1613*35238bceSAndroid Build Coastguard Worker
1614*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1615*35238bceSAndroid Build Coastguard Worker
1616*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1617*35238bceSAndroid Build Coastguard Worker {
1618*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter),
1619*35238bceSAndroid Build Coastguard Worker prec, Vec1(coord.x()), layer, cmpReference, result))
1620*35238bceSAndroid Build Coastguard Worker return true;
1621*35238bceSAndroid Build Coastguard Worker }
1622*35238bceSAndroid Build Coastguard Worker }
1623*35238bceSAndroid Build Coastguard Worker else
1624*35238bceSAndroid Build Coastguard Worker {
1625*35238bceSAndroid Build Coastguard Worker if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, Vec1(coord.x()),
1626*35238bceSAndroid Build Coastguard Worker layer, cmpReference, result))
1627*35238bceSAndroid Build Coastguard Worker return true;
1628*35238bceSAndroid Build Coastguard Worker }
1629*35238bceSAndroid Build Coastguard Worker }
1630*35238bceSAndroid Build Coastguard Worker }
1631*35238bceSAndroid Build Coastguard Worker
1632*35238bceSAndroid Build Coastguard Worker return false;
1633*35238bceSAndroid Build Coastguard Worker }
1634*35238bceSAndroid Build Coastguard Worker
isTexCompareResultValid(const TextureCubeArrayView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec4 & coord,const Vec2 & lodBounds,const float cmpReference,const float result)1635*35238bceSAndroid Build Coastguard Worker bool isTexCompareResultValid(const TextureCubeArrayView &texture, const Sampler &sampler,
1636*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec4 &coord, const Vec2 &lodBounds,
1637*35238bceSAndroid Build Coastguard Worker const float cmpReference, const float result)
1638*35238bceSAndroid Build Coastguard Worker {
1639*35238bceSAndroid Build Coastguard Worker const Vec3 coord3 = coord.swizzle(0, 1, 2);
1640*35238bceSAndroid Build Coastguard Worker int numPossibleFaces = 0;
1641*35238bceSAndroid Build Coastguard Worker CubeFace possibleFaces[CUBEFACE_LAST];
1642*35238bceSAndroid Build Coastguard Worker
1643*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1644*35238bceSAndroid Build Coastguard Worker
1645*35238bceSAndroid Build Coastguard Worker getPossibleCubeFaces(coord3, prec.coordBits, &possibleFaces[0], numPossibleFaces);
1646*35238bceSAndroid Build Coastguard Worker
1647*35238bceSAndroid Build Coastguard Worker if (numPossibleFaces == 0)
1648*35238bceSAndroid Build Coastguard Worker return true; // Result is undefined.
1649*35238bceSAndroid Build Coastguard Worker
1650*35238bceSAndroid Build Coastguard Worker for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
1651*35238bceSAndroid Build Coastguard Worker {
1652*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx],
1653*35238bceSAndroid Build Coastguard Worker projectToFace(possibleFaces[tryFaceNdx], coord3));
1654*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1655*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1656*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1657*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1658*35238bceSAndroid Build Coastguard Worker
1659*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1660*35238bceSAndroid Build Coastguard Worker {
1661*35238bceSAndroid Build Coastguard Worker if (isCubeLevelCompareResultValid(texture, 0, sampler, sampler.magFilter, prec, faceCoords, coord.w(),
1662*35238bceSAndroid Build Coastguard Worker cmpReference, result))
1663*35238bceSAndroid Build Coastguard Worker return true;
1664*35238bceSAndroid Build Coastguard Worker }
1665*35238bceSAndroid Build Coastguard Worker
1666*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1667*35238bceSAndroid Build Coastguard Worker {
1668*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1669*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1670*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1671*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1672*35238bceSAndroid Build Coastguard Worker
1673*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel < maxTexLevel);
1674*35238bceSAndroid Build Coastguard Worker
1675*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap)
1676*35238bceSAndroid Build Coastguard Worker {
1677*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1678*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1679*35238bceSAndroid Build Coastguard Worker
1680*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1681*35238bceSAndroid Build Coastguard Worker
1682*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1683*35238bceSAndroid Build Coastguard Worker {
1684*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1685*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1686*35238bceSAndroid Build Coastguard Worker
1687*35238bceSAndroid Build Coastguard Worker if (isCubeMipmapLinearCompareResultValid(texture, level, sampler, getLevelFilter(sampler.minFilter),
1688*35238bceSAndroid Build Coastguard Worker prec, faceCoords, coord.w(), Vec2(minF, maxF),
1689*35238bceSAndroid Build Coastguard Worker cmpReference, result))
1690*35238bceSAndroid Build Coastguard Worker return true;
1691*35238bceSAndroid Build Coastguard Worker }
1692*35238bceSAndroid Build Coastguard Worker }
1693*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1694*35238bceSAndroid Build Coastguard Worker {
1695*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1696*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1697*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1698*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1699*35238bceSAndroid Build Coastguard Worker
1700*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1701*35238bceSAndroid Build Coastguard Worker
1702*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1703*35238bceSAndroid Build Coastguard Worker {
1704*35238bceSAndroid Build Coastguard Worker if (isCubeLevelCompareResultValid(texture, level, sampler, getLevelFilter(sampler.minFilter), prec,
1705*35238bceSAndroid Build Coastguard Worker faceCoords, coord.w(), cmpReference, result))
1706*35238bceSAndroid Build Coastguard Worker return true;
1707*35238bceSAndroid Build Coastguard Worker }
1708*35238bceSAndroid Build Coastguard Worker }
1709*35238bceSAndroid Build Coastguard Worker else
1710*35238bceSAndroid Build Coastguard Worker {
1711*35238bceSAndroid Build Coastguard Worker if (isCubeLevelCompareResultValid(texture, 0, sampler, sampler.minFilter, prec, faceCoords, coord.w(),
1712*35238bceSAndroid Build Coastguard Worker cmpReference, result))
1713*35238bceSAndroid Build Coastguard Worker return true;
1714*35238bceSAndroid Build Coastguard Worker }
1715*35238bceSAndroid Build Coastguard Worker }
1716*35238bceSAndroid Build Coastguard Worker }
1717*35238bceSAndroid Build Coastguard Worker
1718*35238bceSAndroid Build Coastguard Worker return false;
1719*35238bceSAndroid Build Coastguard Worker }
1720*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsCompareResultValid(const ConstPixelBufferAccess & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,int coordZ,const IVec2 (& offsets)[4],float cmpReference,const Vec4 & result)1721*35238bceSAndroid Build Coastguard Worker static bool isGatherOffsetsCompareResultValid(const ConstPixelBufferAccess &texture, const Sampler &sampler,
1722*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec2 &coord, int coordZ,
1723*35238bceSAndroid Build Coastguard Worker const IVec2 (&offsets)[4], float cmpReference, const Vec4 &result)
1724*35238bceSAndroid Build Coastguard Worker {
1725*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(texture.getFormat());
1726*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, texture.getWidth(), coord.x(),
1727*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
1728*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, texture.getHeight(), coord.y(),
1729*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
1730*35238bceSAndroid Build Coastguard Worker
1731*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0, y0) - without wrap mode
1732*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
1733*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
1734*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
1735*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
1736*35238bceSAndroid Build Coastguard Worker
1737*35238bceSAndroid Build Coastguard Worker const int w = texture.getWidth();
1738*35238bceSAndroid Build Coastguard Worker const int h = texture.getHeight();
1739*35238bceSAndroid Build Coastguard Worker
1740*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
1741*35238bceSAndroid Build Coastguard Worker {
1742*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
1743*35238bceSAndroid Build Coastguard Worker {
1744*35238bceSAndroid Build Coastguard Worker bool isCurrentPixelValid = true;
1745*35238bceSAndroid Build Coastguard Worker
1746*35238bceSAndroid Build Coastguard Worker for (int offNdx = 0; offNdx < 4 && isCurrentPixelValid; offNdx++)
1747*35238bceSAndroid Build Coastguard Worker {
1748*35238bceSAndroid Build Coastguard Worker // offNdx-th coordinate offset and then wrapped.
1749*35238bceSAndroid Build Coastguard Worker const int x = wrap(sampler.wrapS, i + offsets[offNdx].x(), w);
1750*35238bceSAndroid Build Coastguard Worker const int y = wrap(sampler.wrapT, j + offsets[offNdx].y(), h);
1751*35238bceSAndroid Build Coastguard Worker const float depth = lookupDepth(texture, sampler, x, y, coordZ);
1752*35238bceSAndroid Build Coastguard Worker const CmpResultSet resSet =
1753*35238bceSAndroid Build Coastguard Worker execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);
1754*35238bceSAndroid Build Coastguard Worker
1755*35238bceSAndroid Build Coastguard Worker if (!isResultInSet(resSet, result[offNdx], prec.resultBits))
1756*35238bceSAndroid Build Coastguard Worker isCurrentPixelValid = false;
1757*35238bceSAndroid Build Coastguard Worker }
1758*35238bceSAndroid Build Coastguard Worker
1759*35238bceSAndroid Build Coastguard Worker if (isCurrentPixelValid)
1760*35238bceSAndroid Build Coastguard Worker return true;
1761*35238bceSAndroid Build Coastguard Worker }
1762*35238bceSAndroid Build Coastguard Worker }
1763*35238bceSAndroid Build Coastguard Worker
1764*35238bceSAndroid Build Coastguard Worker return false;
1765*35238bceSAndroid Build Coastguard Worker }
1766*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsCompareResultValid(const Texture2DView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec2 & coord,const IVec2 (& offsets)[4],float cmpReference,const Vec4 & result)1767*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsCompareResultValid(const Texture2DView &texture, const Sampler &sampler,
1768*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec2 &coord, const IVec2 (&offsets)[4],
1769*35238bceSAndroid Build Coastguard Worker float cmpReference, const Vec4 &result)
1770*35238bceSAndroid Build Coastguard Worker {
1771*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1772*35238bceSAndroid Build Coastguard Worker
1773*35238bceSAndroid Build Coastguard Worker return isGatherOffsetsCompareResultValid(texture.getLevel(0), sampler, prec, coord, 0, offsets, cmpReference,
1774*35238bceSAndroid Build Coastguard Worker result);
1775*35238bceSAndroid Build Coastguard Worker }
1776*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsCompareResultValid(const Texture2DArrayView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec3 & coord,const IVec2 (& offsets)[4],float cmpReference,const Vec4 & result)1777*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsCompareResultValid(const Texture2DArrayView &texture, const Sampler &sampler,
1778*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const Vec3 &coord, const IVec2 (&offsets)[4],
1779*35238bceSAndroid Build Coastguard Worker float cmpReference, const Vec4 &result)
1780*35238bceSAndroid Build Coastguard Worker {
1781*35238bceSAndroid Build Coastguard Worker const float depthErr =
1782*35238bceSAndroid Build Coastguard Worker computeFloatingPointError(coord.z(), prec.coordBits.z()) + computeFixedPointError(prec.uvwBits.z());
1783*35238bceSAndroid Build Coastguard Worker const float minZ = coord.z() - depthErr;
1784*35238bceSAndroid Build Coastguard Worker const float maxZ = coord.z() + depthErr;
1785*35238bceSAndroid Build Coastguard Worker const int minLayer = de::clamp(deFloorFloatToInt32(minZ + 0.5f), 0, texture.getNumLayers() - 1);
1786*35238bceSAndroid Build Coastguard Worker const int maxLayer = de::clamp(deFloorFloatToInt32(maxZ + 0.5f), 0, texture.getNumLayers() - 1);
1787*35238bceSAndroid Build Coastguard Worker
1788*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1789*35238bceSAndroid Build Coastguard Worker
1790*35238bceSAndroid Build Coastguard Worker for (int layer = minLayer; layer <= maxLayer; layer++)
1791*35238bceSAndroid Build Coastguard Worker {
1792*35238bceSAndroid Build Coastguard Worker if (isGatherOffsetsCompareResultValid(texture.getLevel(0), sampler, prec, coord.swizzle(0, 1), layer, offsets,
1793*35238bceSAndroid Build Coastguard Worker cmpReference, result))
1794*35238bceSAndroid Build Coastguard Worker return true;
1795*35238bceSAndroid Build Coastguard Worker }
1796*35238bceSAndroid Build Coastguard Worker return false;
1797*35238bceSAndroid Build Coastguard Worker }
1798*35238bceSAndroid Build Coastguard Worker
isGatherCompareResultValid(const TextureCubeView & texture,const Sampler & sampler,const TexComparePrecision & prec,const CubeFaceFloatCoords & coords,float cmpReference,const Vec4 & result)1799*35238bceSAndroid Build Coastguard Worker static bool isGatherCompareResultValid(const TextureCubeView &texture, const Sampler &sampler,
1800*35238bceSAndroid Build Coastguard Worker const TexComparePrecision &prec, const CubeFaceFloatCoords &coords,
1801*35238bceSAndroid Build Coastguard Worker float cmpReference, const Vec4 &result)
1802*35238bceSAndroid Build Coastguard Worker {
1803*35238bceSAndroid Build Coastguard Worker const bool isFixedPointDepth = isFixedPointDepthTextureFormat(texture.getLevelFace(0, coords.face).getFormat());
1804*35238bceSAndroid Build Coastguard Worker const int size = texture.getLevelFace(0, coords.face).getWidth();
1805*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds =
1806*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
1807*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds =
1808*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());
1809*35238bceSAndroid Build Coastguard Worker
1810*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
1811*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
1812*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
1813*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
1814*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
1815*35238bceSAndroid Build Coastguard Worker
1816*35238bceSAndroid Build Coastguard Worker // Face accesses
1817*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
1818*35238bceSAndroid Build Coastguard Worker for (int face = 0; face < CUBEFACE_LAST; face++)
1819*35238bceSAndroid Build Coastguard Worker faces[face] = texture.getLevelFace(0, CubeFace(face));
1820*35238bceSAndroid Build Coastguard Worker
1821*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
1822*35238bceSAndroid Build Coastguard Worker {
1823*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
1824*35238bceSAndroid Build Coastguard Worker {
1825*35238bceSAndroid Build Coastguard Worker static const IVec2 offsets[4] = {IVec2(0, 1), IVec2(1, 1), IVec2(1, 0), IVec2(0, 0)};
1826*35238bceSAndroid Build Coastguard Worker
1827*35238bceSAndroid Build Coastguard Worker bool isCurrentPixelValid = true;
1828*35238bceSAndroid Build Coastguard Worker
1829*35238bceSAndroid Build Coastguard Worker for (int offNdx = 0; offNdx < 4 && isCurrentPixelValid; offNdx++)
1830*35238bceSAndroid Build Coastguard Worker {
1831*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c = remapCubeEdgeCoords(
1832*35238bceSAndroid Build Coastguard Worker CubeFaceIntCoords(coords.face, i + offsets[offNdx].x(), j + offsets[offNdx].y()), size);
1833*35238bceSAndroid Build Coastguard Worker // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
1834*35238bceSAndroid Build Coastguard Worker // \todo [2014-06-05 nuutti] Test the special case where all corner pixels have exactly the same color.
1835*35238bceSAndroid Build Coastguard Worker // See also isSeamlessLinearCompareResultValid and similar.
1836*35238bceSAndroid Build Coastguard Worker if (c.face == CUBEFACE_LAST)
1837*35238bceSAndroid Build Coastguard Worker return true;
1838*35238bceSAndroid Build Coastguard Worker
1839*35238bceSAndroid Build Coastguard Worker const float depth = lookupDepthNoBorder(faces[c.face], sampler, c.s, c.t);
1840*35238bceSAndroid Build Coastguard Worker const CmpResultSet resSet =
1841*35238bceSAndroid Build Coastguard Worker execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);
1842*35238bceSAndroid Build Coastguard Worker
1843*35238bceSAndroid Build Coastguard Worker if (!isResultInSet(resSet, result[offNdx], prec.resultBits))
1844*35238bceSAndroid Build Coastguard Worker isCurrentPixelValid = false;
1845*35238bceSAndroid Build Coastguard Worker }
1846*35238bceSAndroid Build Coastguard Worker
1847*35238bceSAndroid Build Coastguard Worker if (isCurrentPixelValid)
1848*35238bceSAndroid Build Coastguard Worker return true;
1849*35238bceSAndroid Build Coastguard Worker }
1850*35238bceSAndroid Build Coastguard Worker }
1851*35238bceSAndroid Build Coastguard Worker
1852*35238bceSAndroid Build Coastguard Worker return false;
1853*35238bceSAndroid Build Coastguard Worker }
1854*35238bceSAndroid Build Coastguard Worker
isGatherCompareResultValid(const TextureCubeView & texture,const Sampler & sampler,const TexComparePrecision & prec,const Vec3 & coord,float cmpReference,const Vec4 & result)1855*35238bceSAndroid Build Coastguard Worker bool isGatherCompareResultValid(const TextureCubeView &texture, const Sampler &sampler, const TexComparePrecision &prec,
1856*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, float cmpReference, const Vec4 &result)
1857*35238bceSAndroid Build Coastguard Worker {
1858*35238bceSAndroid Build Coastguard Worker int numPossibleFaces = 0;
1859*35238bceSAndroid Build Coastguard Worker CubeFace possibleFaces[CUBEFACE_LAST];
1860*35238bceSAndroid Build Coastguard Worker
1861*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1862*35238bceSAndroid Build Coastguard Worker
1863*35238bceSAndroid Build Coastguard Worker getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);
1864*35238bceSAndroid Build Coastguard Worker
1865*35238bceSAndroid Build Coastguard Worker if (numPossibleFaces == 0)
1866*35238bceSAndroid Build Coastguard Worker return true; // Result is undefined.
1867*35238bceSAndroid Build Coastguard Worker
1868*35238bceSAndroid Build Coastguard Worker for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
1869*35238bceSAndroid Build Coastguard Worker {
1870*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx],
1871*35238bceSAndroid Build Coastguard Worker projectToFace(possibleFaces[tryFaceNdx], coord));
1872*35238bceSAndroid Build Coastguard Worker
1873*35238bceSAndroid Build Coastguard Worker if (isGatherCompareResultValid(texture, sampler, prec, faceCoords, cmpReference, result))
1874*35238bceSAndroid Build Coastguard Worker return true;
1875*35238bceSAndroid Build Coastguard Worker }
1876*35238bceSAndroid Build Coastguard Worker
1877*35238bceSAndroid Build Coastguard Worker return false;
1878*35238bceSAndroid Build Coastguard Worker }
1879*35238bceSAndroid Build Coastguard Worker
1880*35238bceSAndroid Build Coastguard Worker } // namespace tcu
1881