174 lines
5.2 KiB
C++
174 lines
5.2 KiB
C++
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program Tester Core
|
|
* ----------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Internal utilities shared between TexLookup and TexCompare verifiers.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "tcuTexVerifierUtil.hpp"
|
|
#include "tcuFloat.hpp"
|
|
|
|
namespace tcu
|
|
{
|
|
namespace TexVerifierUtil
|
|
{
|
|
|
|
float computeFloatingPointError (const float value, const int numAccurateBits)
|
|
{
|
|
DE_ASSERT(numAccurateBits >= 0);
|
|
DE_ASSERT(numAccurateBits <= 23);
|
|
|
|
const int numGarbageBits = 23-numAccurateBits;
|
|
const deUint32 mask = (1u<<numGarbageBits)-1u;
|
|
const int exp = tcu::Float32(value).exponent();
|
|
|
|
return Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - Float32::construct(+1, exp, 1u<<23).asFloat();
|
|
}
|
|
|
|
float computeFixedPointError (const int numAccurateBits)
|
|
{
|
|
return computeFloatingPointError(1.0f, numAccurateBits);
|
|
}
|
|
|
|
float computeColorBitsError(const int bits, const int numAccurateBits)
|
|
{
|
|
// Color bits error is not a generic function, it just for compute the error value that cannot be accurately shown in integer data format.
|
|
//
|
|
// "bits" is color bit width, "numAccurateBits" is the number of accurate bits in color bits, "1 << (bits - numAccurateBits)" is the threshold in integer.
|
|
// "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.
|
|
return (float(1 << (bits - numAccurateBits)) + 1.0f / 256.0f) / float((1 << bits) - 1);
|
|
}
|
|
|
|
Vec2 computeNonNormalizedCoordBounds (const bool normalizedCoords, const int dim, const float coord, const int coordBits, const int uvBits)
|
|
{
|
|
const float coordErr = computeFloatingPointError(coord, coordBits);
|
|
const float minN = coord - coordErr;
|
|
const float maxN = coord + coordErr;
|
|
const float minA = normalizedCoords ? minN*float(dim) : minN;
|
|
const float maxA = normalizedCoords ? maxN*float(dim) : maxN;
|
|
const float minC = minA - computeFixedPointError(uvBits);
|
|
const float maxC = maxA + computeFixedPointError(uvBits);
|
|
|
|
DE_ASSERT(minC <= maxC);
|
|
|
|
return Vec2(minC, maxC);
|
|
}
|
|
|
|
void getPossibleCubeFaces (const Vec3& coord, const IVec3& bits, CubeFace* faces, int& numFaces)
|
|
{
|
|
const float x = coord.x();
|
|
const float y = coord.y();
|
|
const float z = coord.z();
|
|
const float ax = de::abs(x);
|
|
const float ay = de::abs(y);
|
|
const float az = de::abs(z);
|
|
const float ex = computeFloatingPointError(x, bits.x());
|
|
const float ey = computeFloatingPointError(y, bits.y());
|
|
const float ez = computeFloatingPointError(z, bits.z());
|
|
|
|
numFaces = 0;
|
|
|
|
if (ay+ey < ax-ex && az+ez < ax-ex)
|
|
{
|
|
if (x >= ex) faces[numFaces++] = CUBEFACE_POSITIVE_X;
|
|
if (x <= ex) faces[numFaces++] = CUBEFACE_NEGATIVE_X;
|
|
}
|
|
else if (ax+ex < ay-ey && az+ez < ay-ey)
|
|
{
|
|
if (y >= ey) faces[numFaces++] = CUBEFACE_POSITIVE_Y;
|
|
if (y <= ey) faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
|
|
}
|
|
else if (ax+ex < az-ez && ay+ey < az-ez)
|
|
{
|
|
if (z >= ez) faces[numFaces++] = CUBEFACE_POSITIVE_Z;
|
|
if (z <= ez) faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
|
|
}
|
|
else
|
|
{
|
|
// One or more components are equal (or within error bounds). Allow all faces where major axis is not zero.
|
|
if (ax > ex)
|
|
{
|
|
faces[numFaces++] = CUBEFACE_NEGATIVE_X;
|
|
faces[numFaces++] = CUBEFACE_POSITIVE_X;
|
|
}
|
|
|
|
if (ay > ey)
|
|
{
|
|
faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
|
|
faces[numFaces++] = CUBEFACE_POSITIVE_Y;
|
|
}
|
|
|
|
if (az > ez)
|
|
{
|
|
faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
|
|
faces[numFaces++] = CUBEFACE_POSITIVE_Z;
|
|
}
|
|
}
|
|
}
|
|
|
|
Sampler getUnnormalizedCoordSampler (const Sampler& sampler)
|
|
{
|
|
Sampler copy = sampler;
|
|
copy.normalizedCoords = false;
|
|
return copy;
|
|
}
|
|
|
|
static inline int imod (int a, int b)
|
|
{
|
|
int m = a % b;
|
|
return m < 0 ? m + b : m;
|
|
}
|
|
|
|
static inline int mirror (int a)
|
|
{
|
|
return a >= 0 ? a : -(1 + a);
|
|
}
|
|
|
|
int wrap (Sampler::WrapMode mode, int c, int size)
|
|
{
|
|
switch (mode)
|
|
{
|
|
// \note CL and GL modes are handled identically here, as verification process accounts for
|
|
// accuracy differences caused by different methods (wrapping vs. denormalizing first).
|
|
case tcu::Sampler::CLAMP_TO_BORDER:
|
|
return deClamp32(c, -1, size);
|
|
|
|
case tcu::Sampler::CLAMP_TO_EDGE:
|
|
return deClamp32(c, 0, size-1);
|
|
|
|
case tcu::Sampler::REPEAT_GL:
|
|
case tcu::Sampler::REPEAT_CL:
|
|
return imod(c, size);
|
|
|
|
case tcu::Sampler::MIRRORED_ONCE:
|
|
c = deClamp32(c, -size, size);
|
|
// Fall-through
|
|
|
|
case tcu::Sampler::MIRRORED_REPEAT_GL:
|
|
case tcu::Sampler::MIRRORED_REPEAT_CL:
|
|
return (size - 1) - mirror(imod(c, 2*size) - size);
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
return 0;
|
|
}
|
|
}
|
|
} // TexVerifierUtil
|
|
} // tcu
|