QRgbaFloat: add support for multiplying & comparing as FP16
AVX512FP16 expanded FP16 support on x86 to all operations (addition, multiplication, comparison, etc.), so make use of them. Each operation takes just as many cycles as an FP32 operation, but we avoid converting between FP16 and PF32 for those operations. Change-Id: Ide4dbd0777a44ed0870efffd17391370e1638c7a Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
parent
59d5a52c22
commit
272d078926
@ -85,7 +85,7 @@ public:
|
||||
inline operator float() const noexcept;
|
||||
#endif
|
||||
template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> && !std::is_same_v<T, NearestFloat>>>
|
||||
explicit qfloat16(T value) noexcept : qfloat16(NearestFloat(value)) {}
|
||||
constexpr explicit qfloat16(T value) noexcept : qfloat16(NearestFloat(value)) {}
|
||||
|
||||
// Support for qIs{Inf,NaN,Finite}:
|
||||
bool isInf() const noexcept { return (b16 & 0x7fff) == 0x7c00; }
|
||||
|
@ -19,7 +19,13 @@ class alignas(sizeof(F) * 4) QRgbaFloat
|
||||
static_assert(std::is_same<F, qfloat16>::value || std::is_same<F, float>::value);
|
||||
public:
|
||||
using Type = F;
|
||||
#if defined(__AVX512FP16__) && QFLOAT16_IS_NATIVE
|
||||
// AVX512FP16 has multiplication instructions
|
||||
using FastType = F;
|
||||
#else
|
||||
// use FP32 for multiplications
|
||||
using FastType = float;
|
||||
#endif
|
||||
F r;
|
||||
F g;
|
||||
F b;
|
||||
@ -28,7 +34,7 @@ public:
|
||||
static constexpr
|
||||
QRgbaFloat fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
|
||||
{
|
||||
constexpr FastType scale = 1.0f / 65535.0f;
|
||||
constexpr FastType scale = FastType(1.0f / 65535.0f);
|
||||
return QRgbaFloat{
|
||||
F(red * scale),
|
||||
F(green * scale),
|
||||
@ -39,7 +45,7 @@ public:
|
||||
static constexpr
|
||||
QRgbaFloat fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
|
||||
{
|
||||
constexpr FastType scale = 1.0f / 255.0f;
|
||||
constexpr FastType scale = FastType(1.0f / 255.0f);
|
||||
return QRgbaFloat{
|
||||
F(red * scale),
|
||||
F(green * scale),
|
||||
@ -52,8 +58,8 @@ public:
|
||||
return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24));
|
||||
}
|
||||
|
||||
constexpr bool isOpaque() const { return a >= 1.0f; }
|
||||
constexpr bool isTransparent() const { return a <= 0.0f; }
|
||||
constexpr bool isOpaque() const { return a >= FastType(1.0f); }
|
||||
constexpr bool isTransparent() const { return a <= FastType(0.0f); }
|
||||
|
||||
constexpr FastType red() const { return r; }
|
||||
constexpr FastType green() const { return g; }
|
||||
@ -64,24 +70,24 @@ public:
|
||||
void setBlue(FastType _blue) { b = F(_blue); }
|
||||
void setAlpha(FastType _alpha) { a = F(_alpha); }
|
||||
|
||||
constexpr FastType redNormalized() const { return std::clamp(static_cast<FastType>(r), 0.0f, 1.0f); }
|
||||
constexpr FastType greenNormalized() const { return std::clamp(static_cast<FastType>(g), 0.0f, 1.0f); }
|
||||
constexpr FastType blueNormalized() const { return std::clamp(static_cast<FastType>(b), 0.0f, 1.0f); }
|
||||
constexpr FastType alphaNormalized() const { return std::clamp(static_cast<FastType>(a), 0.0f, 1.0f); }
|
||||
constexpr FastType redNormalized() const { return clamp01(r); }
|
||||
constexpr FastType greenNormalized() const { return clamp01(g); }
|
||||
constexpr FastType blueNormalized() const { return clamp01(b); }
|
||||
constexpr FastType alphaNormalized() const { return clamp01(a); }
|
||||
|
||||
constexpr quint8 red8() const { return std::lround(redNormalized() * 255.0f); }
|
||||
constexpr quint8 green8() const { return std::lround(greenNormalized() * 255.0f); }
|
||||
constexpr quint8 blue8() const { return std::lround(blueNormalized() * 255.0f); }
|
||||
constexpr quint8 alpha8() const { return std::lround(alphaNormalized() * 255.0f); }
|
||||
constexpr quint8 red8() const { return qRound(redNormalized() * FastType(255.0f)); }
|
||||
constexpr quint8 green8() const { return qRound(greenNormalized() * FastType(255.0f)); }
|
||||
constexpr quint8 blue8() const { return qRound(blueNormalized() * FastType(255.0f)); }
|
||||
constexpr quint8 alpha8() const { return qRound(alphaNormalized() * FastType(255.0f)); }
|
||||
constexpr uint toArgb32() const
|
||||
{
|
||||
return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
|
||||
}
|
||||
|
||||
constexpr quint16 red16() const { return std::lround(redNormalized() * 65535.0f); }
|
||||
constexpr quint16 green16() const { return std::lround(greenNormalized() * 65535.0f); }
|
||||
constexpr quint16 blue16() const { return std::lround(blueNormalized() * 65535.0f); }
|
||||
constexpr quint16 alpha16() const { return std::lround(alphaNormalized() * 65535.0f); }
|
||||
constexpr quint16 red16() const { return qRound(redNormalized() * FastType(65535.0f)); }
|
||||
constexpr quint16 green16() const { return qRound(greenNormalized() * FastType(65535.0f)); }
|
||||
constexpr quint16 blue16() const { return qRound(blueNormalized() * FastType(65535.0f)); }
|
||||
constexpr quint16 alpha16() const { return qRound(alphaNormalized() * FastType(65535.0f)); }
|
||||
|
||||
constexpr Q_ALWAYS_INLINE QRgbaFloat premultiplied() const
|
||||
{
|
||||
@ -104,6 +110,12 @@ public:
|
||||
{
|
||||
return !(*this == f);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr static FastType clamp01(Type f)
|
||||
{
|
||||
return std::clamp(FastType(f), FastType(0.0f), FastType(1.0f));
|
||||
}
|
||||
};
|
||||
|
||||
typedef QRgbaFloat<qfloat16> QRgbaFloat16;
|
||||
|
Loading…
x
Reference in New Issue
Block a user