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;
|
inline operator float() const noexcept;
|
||||||
#endif
|
#endif
|
||||||
template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> && !std::is_same_v<T, NearestFloat>>>
|
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}:
|
// Support for qIs{Inf,NaN,Finite}:
|
||||||
bool isInf() const noexcept { return (b16 & 0x7fff) == 0x7c00; }
|
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);
|
static_assert(std::is_same<F, qfloat16>::value || std::is_same<F, float>::value);
|
||||||
public:
|
public:
|
||||||
using Type = F;
|
using Type = F;
|
||||||
|
#if defined(__AVX512FP16__) && QFLOAT16_IS_NATIVE
|
||||||
|
// AVX512FP16 has multiplication instructions
|
||||||
|
using FastType = F;
|
||||||
|
#else
|
||||||
|
// use FP32 for multiplications
|
||||||
using FastType = float;
|
using FastType = float;
|
||||||
|
#endif
|
||||||
F r;
|
F r;
|
||||||
F g;
|
F g;
|
||||||
F b;
|
F b;
|
||||||
@ -28,7 +34,7 @@ public:
|
|||||||
static constexpr
|
static constexpr
|
||||||
QRgbaFloat fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
|
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{
|
return QRgbaFloat{
|
||||||
F(red * scale),
|
F(red * scale),
|
||||||
F(green * scale),
|
F(green * scale),
|
||||||
@ -39,7 +45,7 @@ public:
|
|||||||
static constexpr
|
static constexpr
|
||||||
QRgbaFloat fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
|
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{
|
return QRgbaFloat{
|
||||||
F(red * scale),
|
F(red * scale),
|
||||||
F(green * scale),
|
F(green * scale),
|
||||||
@ -52,8 +58,8 @@ public:
|
|||||||
return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24));
|
return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool isOpaque() const { return a >= 1.0f; }
|
constexpr bool isOpaque() const { return a >= FastType(1.0f); }
|
||||||
constexpr bool isTransparent() const { return a <= 0.0f; }
|
constexpr bool isTransparent() const { return a <= FastType(0.0f); }
|
||||||
|
|
||||||
constexpr FastType red() const { return r; }
|
constexpr FastType red() const { return r; }
|
||||||
constexpr FastType green() const { return g; }
|
constexpr FastType green() const { return g; }
|
||||||
@ -64,24 +70,24 @@ public:
|
|||||||
void setBlue(FastType _blue) { b = F(_blue); }
|
void setBlue(FastType _blue) { b = F(_blue); }
|
||||||
void setAlpha(FastType _alpha) { a = F(_alpha); }
|
void setAlpha(FastType _alpha) { a = F(_alpha); }
|
||||||
|
|
||||||
constexpr FastType redNormalized() const { return std::clamp(static_cast<FastType>(r), 0.0f, 1.0f); }
|
constexpr FastType redNormalized() const { return clamp01(r); }
|
||||||
constexpr FastType greenNormalized() const { return std::clamp(static_cast<FastType>(g), 0.0f, 1.0f); }
|
constexpr FastType greenNormalized() const { return clamp01(g); }
|
||||||
constexpr FastType blueNormalized() const { return std::clamp(static_cast<FastType>(b), 0.0f, 1.0f); }
|
constexpr FastType blueNormalized() const { return clamp01(b); }
|
||||||
constexpr FastType alphaNormalized() const { return std::clamp(static_cast<FastType>(a), 0.0f, 1.0f); }
|
constexpr FastType alphaNormalized() const { return clamp01(a); }
|
||||||
|
|
||||||
constexpr quint8 red8() const { return std::lround(redNormalized() * 255.0f); }
|
constexpr quint8 red8() const { return qRound(redNormalized() * FastType(255.0f)); }
|
||||||
constexpr quint8 green8() const { return std::lround(greenNormalized() * 255.0f); }
|
constexpr quint8 green8() const { return qRound(greenNormalized() * FastType(255.0f)); }
|
||||||
constexpr quint8 blue8() const { return std::lround(blueNormalized() * 255.0f); }
|
constexpr quint8 blue8() const { return qRound(blueNormalized() * FastType(255.0f)); }
|
||||||
constexpr quint8 alpha8() const { return std::lround(alphaNormalized() * 255.0f); }
|
constexpr quint8 alpha8() const { return qRound(alphaNormalized() * FastType(255.0f)); }
|
||||||
constexpr uint toArgb32() const
|
constexpr uint toArgb32() const
|
||||||
{
|
{
|
||||||
return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
|
return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr quint16 red16() const { return std::lround(redNormalized() * 65535.0f); }
|
constexpr quint16 red16() const { return qRound(redNormalized() * FastType(65535.0f)); }
|
||||||
constexpr quint16 green16() const { return std::lround(greenNormalized() * 65535.0f); }
|
constexpr quint16 green16() const { return qRound(greenNormalized() * FastType(65535.0f)); }
|
||||||
constexpr quint16 blue16() const { return std::lround(blueNormalized() * 65535.0f); }
|
constexpr quint16 blue16() const { return qRound(blueNormalized() * FastType(65535.0f)); }
|
||||||
constexpr quint16 alpha16() const { return std::lround(alphaNormalized() * 65535.0f); }
|
constexpr quint16 alpha16() const { return qRound(alphaNormalized() * FastType(65535.0f)); }
|
||||||
|
|
||||||
constexpr Q_ALWAYS_INLINE QRgbaFloat premultiplied() const
|
constexpr Q_ALWAYS_INLINE QRgbaFloat premultiplied() const
|
||||||
{
|
{
|
||||||
@ -104,6 +110,12 @@ public:
|
|||||||
{
|
{
|
||||||
return !(*this == f);
|
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;
|
typedef QRgbaFloat<qfloat16> QRgbaFloat16;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user