You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.0 KiB
134 lines
4.0 KiB
// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
|
|
//
|
|
// 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.
|
|
|
|
#include "System/Half.hpp"
|
|
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <cstdlib>
|
|
|
|
using namespace sw;
|
|
|
|
TEST(MathTest, UnsignedFloat11_10)
|
|
{
|
|
// Test the largest value which causes underflow to 0, and the smallest value
|
|
// which produces a denormalized result.
|
|
|
|
EXPECT_EQ(R11G11B10F::float32ToFloat11(bit_cast<float>(0x3500007F)), 0x0000);
|
|
EXPECT_EQ(R11G11B10F::float32ToFloat11(bit_cast<float>(0x35000080)), 0x0001);
|
|
|
|
EXPECT_EQ(R11G11B10F::float32ToFloat10(bit_cast<float>(0x3580003F)), 0x0000);
|
|
EXPECT_EQ(R11G11B10F::float32ToFloat10(bit_cast<float>(0x35800040)), 0x0001);
|
|
}
|
|
|
|
// Clamps to the [0, hi] range. NaN input produces 0, hi must be non-NaN.
|
|
float clamp0hi(float x, float hi)
|
|
{
|
|
// If x=NaN, x > 0 will compare false and we return 0.
|
|
if(!(x > 0))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// x is non-NaN at this point, so std::min() is safe for non-NaN hi.
|
|
return std::min(x, hi);
|
|
}
|
|
|
|
unsigned int RGB9E5_reference(float r, float g, float b)
|
|
{
|
|
// Vulkan 1.1.117 section 15.2.1 RGB to Shared Exponent Conversion
|
|
|
|
// B is the exponent bias (15)
|
|
constexpr int g_sharedexp_bias = 15;
|
|
|
|
// N is the number of mantissa bits per component (9)
|
|
constexpr int g_sharedexp_mantissabits = 9;
|
|
|
|
// Emax is the maximum allowed biased exponent value (31)
|
|
constexpr int g_sharedexp_maxexponent = 31;
|
|
|
|
constexpr float g_sharedexp_max =
|
|
((static_cast<float>(1 << g_sharedexp_mantissabits) - 1) /
|
|
static_cast<float>(1 << g_sharedexp_mantissabits)) *
|
|
static_cast<float>(1 << (g_sharedexp_maxexponent - g_sharedexp_bias));
|
|
|
|
const float red_c = clamp0hi(r, g_sharedexp_max);
|
|
const float green_c = clamp0hi(g, g_sharedexp_max);
|
|
const float blue_c = clamp0hi(b, g_sharedexp_max);
|
|
|
|
const float max_c = fmax(fmax(red_c, green_c), blue_c);
|
|
const float exp_p = fmax(-g_sharedexp_bias - 1, floor(log2(max_c))) + 1 + g_sharedexp_bias;
|
|
const int max_s = static_cast<int>(floor((max_c / exp2(exp_p - g_sharedexp_bias - g_sharedexp_mantissabits)) + 0.5f));
|
|
const int exp_s = static_cast<int>((max_s < exp2(g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
|
|
|
|
unsigned int R = static_cast<unsigned int>(floor((red_c / exp2(exp_s - g_sharedexp_bias - g_sharedexp_mantissabits)) + 0.5f));
|
|
unsigned int G = static_cast<unsigned int>(floor((green_c / exp2(exp_s - g_sharedexp_bias - g_sharedexp_mantissabits)) + 0.5f));
|
|
unsigned int B = static_cast<unsigned int>(floor((blue_c / exp2(exp_s - g_sharedexp_bias - g_sharedexp_mantissabits)) + 0.5f));
|
|
unsigned int E = exp_s;
|
|
|
|
return (E << 27) | (B << 18) | (G << 9) | R;
|
|
}
|
|
|
|
TEST(MathTest, SharedExponentSparse)
|
|
{
|
|
for(uint64_t i = 0; i < 0x0000000100000000; i += 0x400)
|
|
{
|
|
float f = bit_cast<float>(i);
|
|
|
|
unsigned int ref = RGB9E5_reference(f, 0.0f, 0.0f);
|
|
unsigned int val = RGB9E5(f, 0.0f, 0.0f);
|
|
|
|
EXPECT_EQ(ref, val);
|
|
}
|
|
}
|
|
|
|
TEST(MathTest, SharedExponentRandom)
|
|
{
|
|
srand(0);
|
|
|
|
unsigned int x = 0;
|
|
unsigned int y = 0;
|
|
unsigned int z = 0;
|
|
|
|
for(int i = 0; i < 10000000; i++)
|
|
{
|
|
float r = bit_cast<float>(x);
|
|
float g = bit_cast<float>(y);
|
|
float b = bit_cast<float>(z);
|
|
|
|
unsigned int ref = RGB9E5_reference(r, g, b);
|
|
unsigned int val = RGB9E5(r, g, b);
|
|
|
|
EXPECT_EQ(ref, val);
|
|
|
|
x += rand();
|
|
y += rand();
|
|
z += rand();
|
|
}
|
|
}
|
|
|
|
TEST(MathTest, SharedExponentExhaustive)
|
|
{
|
|
for(uint64_t i = 0; i < 0x0000000100000000; i += 1)
|
|
{
|
|
float f = bit_cast<float>(i);
|
|
|
|
unsigned int ref = RGB9E5_reference(f, 0.0f, 0.0f);
|
|
unsigned int val = RGB9E5(f, 0.0f, 0.0f);
|
|
|
|
EXPECT_EQ(ref, val);
|
|
}
|
|
}
|