Commit 679d1187 by Carl Woffenden Committed by Commit Bot

Fix to build with VS2019

When building with VS2019 (using is_clang=false) multiples of the following error are given: ../../src/common/mathutil.cpp(75): error C4244: '=': conversion from 'double' to 'float', possible loss of data (This is due to pow(), when passed an int for the second param, widens the first param to a double then returns a double). Since the code was being changed the opportunity was taken to: - add missing unit tests for the two 999E5 conversions - optimise out the common pow() functions The unit tests were written against the original implementation, then the optimisations added and verified against the original results. Bug: angleproject:5521, dawn:602 Change-Id: Ic9e5eaedbe3fc7ceeed697898823b76dffcd989a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2624888 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 68ac4e43
...@@ -36,6 +36,7 @@ Arm Ltd. ...@@ -36,6 +36,7 @@ Arm Ltd.
Broadcom Inc. Broadcom Inc.
Facebook, Inc. Facebook, Inc.
The Khronos Group, Inc. The Khronos Group, Inc.
Numfum GmbH
Jacek Caban Jacek Caban
Mark Callow Mark Callow
......
...@@ -197,3 +197,6 @@ The Khronos Group, Inc. ...@@ -197,3 +197,6 @@ The Khronos Group, Inc.
Igalia, S.L. Igalia, S.L.
Jose Dapena Paz Jose Dapena Paz
Numfum GmbH
Carl Woffenden
...@@ -31,6 +31,9 @@ constexpr int g_sharedexp_bias = 15; ...@@ -31,6 +31,9 @@ constexpr int g_sharedexp_bias = 15;
// N is the number of mantissa bits per component (9) // N is the number of mantissa bits per component (9)
constexpr int g_sharedexp_mantissabits = 9; constexpr int g_sharedexp_mantissabits = 9;
// number of mantissa bits per component pre-biased
constexpr int g_sharedexp_biased_mantissabits = g_sharedexp_bias + g_sharedexp_mantissabits;
// Emax is the maximum allowed biased exponent value (31) // Emax is the maximum allowed biased exponent value (31)
constexpr int g_sharedexp_maxexponent = 31; constexpr int g_sharedexp_maxexponent = 31;
...@@ -51,17 +54,15 @@ unsigned int convertRGBFloatsTo999E5(float red, float green, float blue) ...@@ -51,17 +54,15 @@ unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
const float exp_p = const float exp_p =
std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias; std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias;
const int max_s = static_cast<int>( const int max_s = static_cast<int>(
floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f)); floor((max_c / (pow(2.0f, exp_p - g_sharedexp_biased_mantissabits))) + 0.5f));
const int exp_s = const int exp_s =
static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1); static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
const float pow2_exp = pow(2.0f, static_cast<float>(exp_s) - g_sharedexp_biased_mantissabits);
RGB9E5Data output; RGB9E5Data output;
output.R = static_cast<unsigned int>( output.R = static_cast<unsigned int>(floor((red_c / pow2_exp) + 0.5f));
floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f)); output.G = static_cast<unsigned int>(floor((green_c / pow2_exp) + 0.5f));
output.G = static_cast<unsigned int>( output.B = static_cast<unsigned int>(floor((blue_c / pow2_exp) + 0.5f));
floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
output.B = static_cast<unsigned int>(
floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
output.E = exp_s; output.E = exp_s;
return bitCast<unsigned int>(output); return bitCast<unsigned int>(output);
...@@ -71,12 +72,12 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float ...@@ -71,12 +72,12 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float
{ {
const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data *>(&input); const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data *>(&input);
*red = const float pow2_exp =
inputData->R * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits); pow(2.0f, static_cast<float>(inputData->E) - g_sharedexp_biased_mantissabits);
*green =
inputData->G * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits); *red = inputData->R * pow2_exp;
*blue = *green = inputData->G * pow2_exp;
inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits); *blue = inputData->B * pow2_exp;
} }
} // namespace gl } // namespace gl
...@@ -379,4 +379,90 @@ TEST(MathUtilTest, Float32ToFloat16) ...@@ -379,4 +379,90 @@ TEST(MathUtilTest, Float32ToFloat16)
ASSERT_EQ(float32ToFloat16(1.0f), 0x3C00); ASSERT_EQ(float32ToFloat16(1.0f), 0x3C00);
} }
// Tests the RGB float to 999E5 conversion
TEST(MathUtilTest, convertRGBFloatsTo999E5)
{
const int numTests = 18;
const float input[numTests][3] = {// The basics
{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 1.0f},
{1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 1.0f},
{1.0f, 1.0f, 0.0f},
{1.0f, 1.0f, 1.0f},
// Extended range
{0.0f, 0.0f, 1.5f},
{0.0f, 2.0f, 0.0f},
{0.0f, 2.5f, 3.0f},
{3.5f, 0.0f, 0.0f},
{4.0f, 0.0f, 4.5f},
{5.0f, 5.5f, 0.0f},
{6.0f, 6.5f, 7.0f},
// Random
{0.1f, 9.6f, 3.2f},
{2.0f, 1.7f, 8.6f},
{0.7f, 4.2f, 9.1f}};
const unsigned int result[numTests] = {// The basics
0x00000000, 0x84000000, 0x80020000, 0x84020000,
0x80000100, 0x84000100, 0x80020100, 0x84020100,
// Extended range
0x86000000, 0x88020000, 0x8E028000, 0x880001C0,
0x94800100, 0x9002C140, 0x97034180,
// Random
0x999A6603, 0x9C4C6C40, 0x9C8D0C16};
for (int i = 0; i < numTests; i++)
{
EXPECT_EQ(convertRGBFloatsTo999E5(input[i][0], input[i][1], input[i][2]), result[i]);
}
}
// Tests the 999E5 to RGB float conversion
TEST(MathUtilTest, convert999E5toRGBFloats)
{
const int numTests = 18;
const float result[numTests][3] = {// The basics
{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 1.0f},
{1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 1.0f},
{1.0f, 1.0f, 0.0f},
{1.0f, 1.0f, 1.0f},
// Extended range
{0.0f, 0.0f, 1.5f},
{0.0f, 2.0f, 0.0f},
{0.0f, 2.5f, 3.0f},
{3.5f, 0.0f, 0.0f},
{4.0f, 0.0f, 4.5f},
{5.0f, 5.5f, 0.0f},
{6.0f, 6.5f, 7.0f},
// Random
{0.1f, 9.6f, 3.2f},
{2.0f, 1.7f, 8.6f},
{0.7f, 4.2f, 9.1f}};
const unsigned int input[numTests] = {// The basics
0x00000000, 0x84000000, 0x80020000, 0x84020000,
0x80000100, 0x84000100, 0x80020100, 0x84020100,
// Extended range
0x86000000, 0x88020000, 0x8E028000, 0x880001C0,
0x94800100, 0x9002C140, 0x97034180,
// Random
0x999A6603, 0x9C4C6C40, 0x9C8D0C16};
// Note: quite a low tolerance is required
const float floatFaultTolerance = 0.05f;
float outR, outG, outB;
for (int i = 0; i < numTests; i++)
{
convert999E5toRGBFloats(input[i], &outR, &outG, &outB);
EXPECT_NEAR(result[i][0], outR, floatFaultTolerance);
EXPECT_NEAR(result[i][1], outG, floatFaultTolerance);
EXPECT_NEAR(result[i][2], outB, floatFaultTolerance);
}
}
} // anonymous namespace } // anonymous namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment