1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Internal utilities shared between TexLookup and TexCompare verifiers.
22 *//*--------------------------------------------------------------------*/
23
24 #include "tcuTexVerifierUtil.hpp"
25 #include "tcuFloat.hpp"
26
27 namespace tcu
28 {
29 namespace TexVerifierUtil
30 {
31
computeFloatingPointError(const float value,const int numAccurateBits)32 float computeFloatingPointError(const float value, const int numAccurateBits)
33 {
34 DE_ASSERT(numAccurateBits >= 0);
35 DE_ASSERT(numAccurateBits <= 23);
36
37 const int numGarbageBits = 23 - numAccurateBits;
38 const uint32_t mask = (1u << numGarbageBits) - 1u;
39 const int exp = tcu::Float32(value).exponent();
40
41 return Float32::construct(+1, exp, (1u << 23) | mask).asFloat() - Float32::construct(+1, exp, 1u << 23).asFloat();
42 }
43
computeFixedPointError(const int numAccurateBits)44 float computeFixedPointError(const int numAccurateBits)
45 {
46 return computeFloatingPointError(1.0f, numAccurateBits);
47 }
48
computeColorBitsError(const int bits,const int numAccurateBits)49 float computeColorBitsError(const int bits, const int numAccurateBits)
50 {
51 // Color bits error is not a generic function, it just for compute the error value that cannot be accurately shown in integer data format.
52 //
53 // "bits" is color bit width, "numAccurateBits" is the number of accurate bits in color bits, "1 << (bits - numAccurateBits)" is the threshold in integer.
54 // "1.0f / 256.0f" is epsilon value, to make sure the threshold use to calculate in float can be a little bigger than the real value.
55 return (float(1 << (bits - numAccurateBits)) + 1.0f / 256.0f) / float((1 << bits) - 1);
56 }
57
computeNonNormalizedCoordBounds(const bool normalizedCoords,const int dim,const float coord,const int coordBits,const int uvBits)58 Vec2 computeNonNormalizedCoordBounds(const bool normalizedCoords, const int dim, const float coord, const int coordBits,
59 const int uvBits)
60 {
61 const float coordErr = computeFloatingPointError(coord, coordBits);
62 const float minN = coord - coordErr;
63 const float maxN = coord + coordErr;
64 const float minA = normalizedCoords ? minN * float(dim) : minN;
65 const float maxA = normalizedCoords ? maxN * float(dim) : maxN;
66 const float minC = minA - computeFixedPointError(uvBits);
67 const float maxC = maxA + computeFixedPointError(uvBits);
68
69 DE_ASSERT(minC <= maxC);
70
71 return Vec2(minC, maxC);
72 }
73
getPossibleCubeFaces(const Vec3 & coord,const IVec3 & bits,CubeFace * faces,int & numFaces)74 void getPossibleCubeFaces(const Vec3 &coord, const IVec3 &bits, CubeFace *faces, int &numFaces)
75 {
76 const float x = coord.x();
77 const float y = coord.y();
78 const float z = coord.z();
79 const float ax = de::abs(x);
80 const float ay = de::abs(y);
81 const float az = de::abs(z);
82 const float ex = computeFloatingPointError(x, bits.x());
83 const float ey = computeFloatingPointError(y, bits.y());
84 const float ez = computeFloatingPointError(z, bits.z());
85
86 numFaces = 0;
87
88 if (ay + ey < ax - ex && az + ez < ax - ex)
89 {
90 if (x >= ex)
91 faces[numFaces++] = CUBEFACE_POSITIVE_X;
92 if (x <= ex)
93 faces[numFaces++] = CUBEFACE_NEGATIVE_X;
94 }
95 else if (ax + ex < ay - ey && az + ez < ay - ey)
96 {
97 if (y >= ey)
98 faces[numFaces++] = CUBEFACE_POSITIVE_Y;
99 if (y <= ey)
100 faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
101 }
102 else if (ax + ex < az - ez && ay + ey < az - ez)
103 {
104 if (z >= ez)
105 faces[numFaces++] = CUBEFACE_POSITIVE_Z;
106 if (z <= ez)
107 faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
108 }
109 else
110 {
111 // One or more components are equal (or within error bounds). Allow all faces where major axis is not zero.
112 if (ax > ex)
113 {
114 faces[numFaces++] = CUBEFACE_NEGATIVE_X;
115 faces[numFaces++] = CUBEFACE_POSITIVE_X;
116 }
117
118 if (ay > ey)
119 {
120 faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
121 faces[numFaces++] = CUBEFACE_POSITIVE_Y;
122 }
123
124 if (az > ez)
125 {
126 faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
127 faces[numFaces++] = CUBEFACE_POSITIVE_Z;
128 }
129 }
130 }
131
getUnnormalizedCoordSampler(const Sampler & sampler)132 Sampler getUnnormalizedCoordSampler(const Sampler &sampler)
133 {
134 Sampler copy = sampler;
135 copy.normalizedCoords = false;
136 return copy;
137 }
138
imod(int a,int b)139 static inline int imod(int a, int b)
140 {
141 int m = a % b;
142 return m < 0 ? m + b : m;
143 }
144
mirror(int a)145 static inline int mirror(int a)
146 {
147 return a >= 0 ? a : -(1 + a);
148 }
149
wrap(Sampler::WrapMode mode,int c,int size)150 int wrap(Sampler::WrapMode mode, int c, int size)
151 {
152 switch (mode)
153 {
154 // \note CL and GL modes are handled identically here, as verification process accounts for
155 // accuracy differences caused by different methods (wrapping vs. denormalizing first).
156 case tcu::Sampler::CLAMP_TO_BORDER:
157 return deClamp32(c, -1, size);
158
159 case tcu::Sampler::CLAMP_TO_EDGE:
160 return deClamp32(c, 0, size - 1);
161
162 case tcu::Sampler::REPEAT_GL:
163 case tcu::Sampler::REPEAT_CL:
164 return imod(c, size);
165
166 case tcu::Sampler::MIRRORED_ONCE:
167 c = deClamp32(c, -size, size);
168 // Fall-through
169
170 case tcu::Sampler::MIRRORED_REPEAT_GL:
171 case tcu::Sampler::MIRRORED_REPEAT_CL:
172 return (size - 1) - mirror(imod(c, 2 * size) - size);
173
174 default:
175 DE_ASSERT(false);
176 return 0;
177 }
178 }
179 } // namespace TexVerifierUtil
180 } // namespace tcu
181