xref: /aosp_15_r20/external/deqp/framework/common/tcuTexVerifierUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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