diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-01-10 14:35:12 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-01-11 17:38:06 -0800 |
commit | 272d0789265fcb13523cc5b25ceef18c6306305d (patch) | |
tree | 3316b4f79afae3803c755bd18f5afed04cda5b94 /src/gui/painting | |
parent | 59d5a52c2278f2e8c1d715509dfbacc4a29a492d (diff) |
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>
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qrgbafloat.h | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/src/gui/painting/qrgbafloat.h b/src/gui/painting/qrgbafloat.h index d5ca4cd8c9..160623eb1e 100644 --- a/src/gui/painting/qrgbafloat.h +++ b/src/gui/painting/qrgbafloat.h @@ -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; |