-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] support half precision uniforms and half precision samplers #40590
Changes from 1 commit
02ccd58
3c00839
43ff491
68b1009
b6e6f81
d739b58
f1919b4
a98fa07
7dca490
9599b62
4bdc197
a8b80ed
8e9892b
1bce547
22a0bd1
c802c7c
251564b
51d7bb7
9001fe1
11f0c9f
6998f76
205db32
736a3e5
0af6ab9
31cf48a
c9ffbc5
b2996a8
2f1f5c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #include "scalar.h" | ||
|
|
||
| namespace impeller { | ||
|
|
||
| uint16_t ScalarToHalf(Scalar f) { | ||
| uint32_t x = *reinterpret_cast<const uint32_t*>(&f); | ||
| uint32_t sign = (unsigned short)(x >> 31); | ||
| uint32_t mantissa; | ||
| uint32_t exp; | ||
| uint16_t hf; | ||
|
|
||
| mantissa = x & ((1 << 23) - 1); | ||
| exp = x & (0xFF << 23); | ||
| if (exp >= 0x47800000) { | ||
| // check if the original number is a NaN | ||
| if (mantissa && (exp == (0xFF << 23))) { | ||
| // single precision NaN | ||
| mantissa = (1 << 23) - 1; | ||
| } else { | ||
| // half-float will be Inf | ||
| mantissa = 0; | ||
| } | ||
| hf = (((uint16_t)sign) << 15) | (uint16_t)((0x1F << 10)) | | ||
| (uint16_t)(mantissa >> 13); | ||
| } | ||
| // check if exponent is <= -15 | ||
| else if (exp <= 0x38000000) { | ||
| hf = 0; // too small to be represented | ||
| } else { | ||
| hf = (((uint16_t)sign) << 15) | (uint16_t)((exp - 0x38000000) >> 13) | | ||
| (uint16_t)(mantissa >> 13); | ||
| } | ||
| return hf; | ||
| } | ||
|
|
||
| } // namespace impeller |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |
| #pragma once | ||
|
|
||
| #include <cfloat> | ||
| #include <cstdint> | ||
| #include <type_traits> | ||
| #include <valarray> | ||
|
|
||
|
|
@@ -13,6 +14,7 @@ | |
| namespace impeller { | ||
|
|
||
| using Scalar = float; | ||
| using Half = uint16_t; | ||
|
||
|
|
||
| template <class T, class = std::enable_if_t<std::is_arithmetic_v<T>>> | ||
| constexpr T Absolute(const T& val) { | ||
|
|
@@ -52,4 +54,10 @@ struct Degrees { | |
| }; | ||
| }; | ||
|
|
||
| /// @brief Convert a scalar to a half precision float. | ||
| /// | ||
| /// Adapted from | ||
| /// https://developer.android.com/games/optimize/vertex-data-management . | ||
|
||
| uint16_t ScalarToHalf(Scalar f); | ||
|
|
||
| } // namespace impeller | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -288,6 +288,43 @@ struct Vector4 { | |
| static_assert(sizeof(Vector3) == 3 * sizeof(Scalar)); | ||
| static_assert(sizeof(Vector4) == 4 * sizeof(Scalar)); | ||
|
|
||
| struct HalfVector4 { | ||
|
||
| union { | ||
| struct { | ||
| Half x = 0.0; | ||
| Half y = 0.0; | ||
| Half z = 0.0; | ||
| Half w = 1.0; | ||
| }; | ||
| Half e[4]; | ||
| }; | ||
|
|
||
| constexpr HalfVector4() {} | ||
|
|
||
| constexpr HalfVector4(const Color& c) | ||
| : x(ScalarToHalf(c.red)), | ||
| y(ScalarToHalf(c.green)), | ||
| z(ScalarToHalf(c.blue)), | ||
| w(ScalarToHalf(c.alpha)) {} | ||
|
|
||
| constexpr HalfVector4(Half x, Half y, Half z, Half w) | ||
| : x(x), y(y), z(z), w(w) {} | ||
|
|
||
| constexpr HalfVector4(const HalfVector2& p) : x(p.x), y(p.y) {} | ||
|
|
||
| constexpr bool operator==(const HalfVector4& v) const { | ||
| return (x == v.x) && (y == v.y) && (z == v.z) && (w == v.w); | ||
| } | ||
|
|
||
| constexpr bool operator!=(const HalfVector4& v) const { | ||
| return (x != v.x) || (y != v.y) || (z != v.z) || (w != v.w); | ||
| } | ||
|
|
||
| std::string ToString() const; | ||
| }; | ||
|
|
||
| static_assert(sizeof(HalfVector4) == 4 * sizeof(Half)); | ||
|
|
||
| } // namespace impeller | ||
|
|
||
| namespace std { | ||
|
|
@@ -302,4 +339,10 @@ inline std::ostream& operator<<(std::ostream& out, const impeller::Vector4& p) { | |
| return out; | ||
| } | ||
|
|
||
| inline std::ostream& operator<<(std::ostream& out, | ||
| const impeller::HalfVector4& p) { | ||
| out << "(" << p.x << ", " << p.y << ", " << p.z << ", " << p.w << ")"; | ||
| return out; | ||
| } | ||
|
|
||
| } // namespace std | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this require
#extension GL_EXT_shader_16bit_storage : requireup top?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not, I'm not actually using a f16vec4 on glsl, here is the compiled shader:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh - but this is all in types.glsl too