From 02ccd58626c6cb5e98beafbd071ae308fed86b2f Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 23 Mar 2023 22:07:04 -0700 Subject: [PATCH 01/22] [Impeller] support f16vec4 in shaders and use in solid color uniform --- impeller/compiler/reflector.cc | 23 +++++++++++++ impeller/entity/shaders/solid_fill.frag | 4 +-- impeller/geometry/BUILD.gn | 1 + impeller/geometry/point.h | 1 + impeller/geometry/scalar.cc | 40 +++++++++++++++++++++++ impeller/geometry/scalar.h | 8 +++++ impeller/geometry/vector.cc | 6 ++++ impeller/geometry/vector.h | 43 +++++++++++++++++++++++++ 8 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 impeller/geometry/scalar.cc diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index 09ad507111f9d..e357c66080cda 100644 --- a/impeller/compiler/reflector.cc +++ b/impeller/compiler/reflector.cc @@ -767,6 +767,29 @@ std::vector Reflector::ReadStructMembers( continue; } + // Tightly packed Half Float Vector. + if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // + member.width == sizeof(float) * 4 && // + member.columns == 1 && // + member.vecsize == 4 // + ) { + uint32_t stride = + GetArrayStride(struct_type, member, i); + uint32_t element_padding = stride - sizeof(HalfVector4); + result.emplace_back(StructMember{ + "HalfVector4", // type + BaseTypeToString(member.basetype), // basetype + GetMemberNameAtIndex(struct_type, i), // name + struct_member_offset, // offset + sizeof(HalfVector4), // size + stride * array_elements.value_or(1), // byte_length + array_elements, // array_elements + element_padding, // element_padding + }); + current_byte_offset += stride * array_elements.value_or(1); + continue; + } + // Other isolated scalars (like bool, int, float/Scalar, etc..). { auto maybe_known_type = ReadKnownScalarType(member.basetype); diff --git a/impeller/entity/shaders/solid_fill.frag b/impeller/entity/shaders/solid_fill.frag index 28c7776da9e1d..4714def3aacf8 100644 --- a/impeller/entity/shaders/solid_fill.frag +++ b/impeller/entity/shaders/solid_fill.frag @@ -5,11 +5,11 @@ #include uniform FragInfo { - vec4 color; + f16vec4 color; } frag_info; -out vec4 frag_color; +out f16vec4 frag_color; void main() { frag_color = frag_info.color; diff --git a/impeller/geometry/BUILD.gn b/impeller/geometry/BUILD.gn index a1b511ce9f41b..42fe21bb1e410 100644 --- a/impeller/geometry/BUILD.gn +++ b/impeller/geometry/BUILD.gn @@ -28,6 +28,7 @@ impeller_component("geometry") { "quaternion.h", "rect.cc", "rect.h", + "scalar.cc", "scalar.h", "shear.cc", "shear.h", diff --git a/impeller/geometry/point.h b/impeller/geometry/point.h index 6434fe5a285a5..18fed3351d8cc 100644 --- a/impeller/geometry/point.h +++ b/impeller/geometry/point.h @@ -308,6 +308,7 @@ using IPoint = TPoint; using IPoint32 = TPoint; using UintPoint32 = TPoint; using Vector2 = Point; +using HalfVector2 = TPoint; } // namespace impeller diff --git a/impeller/geometry/scalar.cc b/impeller/geometry/scalar.cc new file mode 100644 index 0000000000000..d8490859f4cfb --- /dev/null +++ b/impeller/geometry/scalar.cc @@ -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(&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 diff --git a/impeller/geometry/scalar.h b/impeller/geometry/scalar.h index 8a080e18b52a9..4335397d7e36d 100644 --- a/impeller/geometry/scalar.h +++ b/impeller/geometry/scalar.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include @@ -13,6 +14,7 @@ namespace impeller { using Scalar = float; +using Half = uint16_t; template >> 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 diff --git a/impeller/geometry/vector.cc b/impeller/geometry/vector.cc index fecc8476d3f3f..2ebf1ea201627 100644 --- a/impeller/geometry/vector.cc +++ b/impeller/geometry/vector.cc @@ -19,4 +19,10 @@ std::string Vector4::ToString() const { return stream.str(); } +std::string HalfVector4::ToString() const { + std::stringstream stream; + stream << "{" << x << ", " << y << ", " << z << ", " << w << "}"; + return stream.str(); +} + } // namespace impeller diff --git a/impeller/geometry/vector.h b/impeller/geometry/vector.h index 705a88ca056b5..00455fca5f0dc 100644 --- a/impeller/geometry/vector.h +++ b/impeller/geometry/vector.h @@ -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 From 3c008391b1dca3ca0314969e79ae33c574f02072 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 24 Mar 2023 11:11:34 -0700 Subject: [PATCH 02/22] use compiler intrinsic --- impeller/geometry/scalar.cc | 32 +++----------------------------- impeller/geometry/scalar.h | 6 +++--- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/impeller/geometry/scalar.cc b/impeller/geometry/scalar.cc index d8490859f4cfb..be1b53a6d4a01 100644 --- a/impeller/geometry/scalar.cc +++ b/impeller/geometry/scalar.cc @@ -6,35 +6,9 @@ namespace impeller { -uint16_t ScalarToHalf(Scalar f) { - uint32_t x = *reinterpret_cast(&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; +Half ScalarToHalf(Scalar f) { + __fp16 storage = f; + return storage; } } // namespace impeller diff --git a/impeller/geometry/scalar.h b/impeller/geometry/scalar.h index 4335397d7e36d..8456e9565dbf7 100644 --- a/impeller/geometry/scalar.h +++ b/impeller/geometry/scalar.h @@ -56,8 +56,8 @@ 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); +/// Can express numbers in the range of 2^-14 to 65504. +/// See also: https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Half-Precision.html#:~:text=The%20__fp16%20type%20is,parameters%20of%20type%20__fp16%20. +Half ScalarToHalf(Scalar f); } // namespace impeller From 43ff49165fcea65499be207e95a7803271e61156 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 24 Mar 2023 13:05:57 -0700 Subject: [PATCH 03/22] ++ --- impeller/compiler/reflector.cc | 53 ++- .../compiler/shader_lib/impeller/types.glsl | 3 + impeller/entity/contents/scene_contents.cc | 2 +- impeller/geometry/color.h | 4 +- impeller/geometry/point.h | 1 + impeller/geometry/scalar.cc | 35 +- impeller/geometry/scalar.h | 3 +- impeller/geometry/vector.cc | 22 +- impeller/geometry/vector.h | 304 ++++++++++-------- 9 files changed, 274 insertions(+), 153 deletions(-) diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index e357c66080cda..184a72e347eed 100644 --- a/impeller/compiler/reflector.cc +++ b/impeller/compiler/reflector.cc @@ -534,6 +534,11 @@ static std::optional ReadKnownScalarType( .name = "Scalar", .byte_size = sizeof(Scalar), }; + case spirv_cross::SPIRType::BaseType::Half: + return KnownType{ + .name = "Half", + .byte_size = sizeof(Half), + }; case spirv_cross::SPIRType::BaseType::UInt: return KnownType{ .name = "uint32_t", @@ -767,7 +772,53 @@ std::vector Reflector::ReadStructMembers( continue; } - // Tightly packed Half Float Vector. + // Tightly packed half Point (vec2). + if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // + member.width == sizeof(float) * 4 && // + member.columns == 1 && // + member.vecsize == 2 // + ) { + uint32_t stride = + GetArrayStride(struct_type, member, i); + uint32_t element_padding = stride - sizeof(HalfPoint); + result.emplace_back(StructMember{ + "HalfPoint", // type + BaseTypeToString(member.basetype), // basetype + GetMemberNameAtIndex(struct_type, i), // name + struct_member_offset, // offset + sizeof(HalfPoint), // size + stride * array_elements.value_or(1), // byte_length + array_elements, // array_elements + element_padding, // element_padding + }); + current_byte_offset += stride * array_elements.value_or(1); + continue; + } + + // Tightly packed Half Float Vector3. + if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // + member.width == sizeof(float) * 4 && // + member.columns == 1 && // + member.vecsize == 3 // + ) { + uint32_t stride = + GetArrayStride(struct_type, member, i); + uint32_t element_padding = stride - sizeof(HalfVector3); + result.emplace_back(StructMember{ + "HalfVector3", // type + BaseTypeToString(member.basetype), // basetype + GetMemberNameAtIndex(struct_type, i), // name + struct_member_offset, // offset + sizeof(HalfVector3), // size + stride * array_elements.value_or(1), // byte_length + array_elements, // array_elements + element_padding, // element_padding + }); + current_byte_offset += stride * array_elements.value_or(1); + continue; + } + + // Tightly packed Half Float Vector4. if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // member.width == sizeof(float) * 4 && // member.columns == 1 && // diff --git a/impeller/compiler/shader_lib/impeller/types.glsl b/impeller/compiler/shader_lib/impeller/types.glsl index 87c7eee666c69..d6de42a47e937 100644 --- a/impeller/compiler/shader_lib/impeller/types.glsl +++ b/impeller/compiler/shader_lib/impeller/types.glsl @@ -6,6 +6,8 @@ #define TYPES_GLSL_ #extension GL_AMD_gpu_shader_half_float : enable +#extension GL_AMD_gpu_shader_half_float_fetch : enable +#extension GL_EXT_shader_explicit_arithmetic_types_float16: enable #ifndef IMPELLER_TARGET_METAL @@ -17,6 +19,7 @@ precision mediump float; #define f16vec3 vec3 #define f16vec4 vec4 #define f16mat4 mat4 +#define f16sampler2D sampler2D #endif // IMPELLER_TARGET_METAL diff --git a/impeller/entity/contents/scene_contents.cc b/impeller/entity/contents/scene_contents.cc index 37dbb702c7355..560de0a2cd9c5 100644 --- a/impeller/entity/contents/scene_contents.cc +++ b/impeller/entity/contents/scene_contents.cc @@ -76,7 +76,7 @@ bool SceneContents::Render(const ContentContext& renderer, contents.SetGeometry(GetGeometry()); contents.SetTexture(subpass_target.GetRenderTargetTexture()); contents.SetEffectTransform( - Matrix::MakeScale(1 / entity.GetTransformation().GetScale())); + Matrix::MakeScale(1.0f / entity.GetTransformation().GetScale())); return contents.Render(renderer, entity, pass); } diff --git a/impeller/geometry/color.h b/impeller/geometry/color.h index 90a9c49f745c7..f99e21c100827 100644 --- a/impeller/geometry/color.h +++ b/impeller/geometry/color.h @@ -13,7 +13,9 @@ namespace impeller { struct ColorHSB; -struct Vector4; + +template struct TVector4; +using Vector4 = TVector4; enum class YUVColorSpace { kBT601LimitedRange, kBT601FullRange }; diff --git a/impeller/geometry/point.h b/impeller/geometry/point.h index 18fed3351d8cc..920b609e05e3b 100644 --- a/impeller/geometry/point.h +++ b/impeller/geometry/point.h @@ -308,6 +308,7 @@ using IPoint = TPoint; using IPoint32 = TPoint; using UintPoint32 = TPoint; using Vector2 = Point; +using HalfPoint = TPoint; using HalfVector2 = TPoint; } // namespace impeller diff --git a/impeller/geometry/scalar.cc b/impeller/geometry/scalar.cc index be1b53a6d4a01..4b16786794ba0 100644 --- a/impeller/geometry/scalar.cc +++ b/impeller/geometry/scalar.cc @@ -6,9 +6,38 @@ namespace impeller { -Half ScalarToHalf(Scalar f) { - __fp16 storage = f; - return storage; +uint16_t ScalarToHalf(Scalar f) { + // __fp16 foo = f; + // return foo; + + uint32_t x = *reinterpret_cast(&f); + uint32_t sign = (uint16_t)(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 diff --git a/impeller/geometry/scalar.h b/impeller/geometry/scalar.h index 8456e9565dbf7..657b0fcf0dfc6 100644 --- a/impeller/geometry/scalar.h +++ b/impeller/geometry/scalar.h @@ -57,7 +57,8 @@ struct Degrees { /// @brief Convert a scalar to a half precision float. /// /// Can express numbers in the range of 2^-14 to 65504. -/// See also: https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Half-Precision.html#:~:text=The%20__fp16%20type%20is,parameters%20of%20type%20__fp16%20. +/// Adapted from +/// https://developer.android.com/games/optimize/vertex-data-management . Half ScalarToHalf(Scalar f); } // namespace impeller diff --git a/impeller/geometry/vector.cc b/impeller/geometry/vector.cc index 2ebf1ea201627..cde0b3c05cddd 100644 --- a/impeller/geometry/vector.cc +++ b/impeller/geometry/vector.cc @@ -3,26 +3,22 @@ // found in the LICENSE file. #include "vector.h" -#include namespace impeller { -std::string Vector3::ToString() const { - std::stringstream stream; - stream << "{" << x << ", " << y << ", " << z << "}"; - return stream.str(); +template <> +Half Cast(const Scalar& s) { + return ScalarToHalf(s); } -std::string Vector4::ToString() const { - std::stringstream stream; - stream << "{" << x << ", " << y << ", " << z << ", " << w << "}"; - return stream.str(); +template <> +Half Cast(const Half& s) { + return s; } -std::string HalfVector4::ToString() const { - std::stringstream stream; - stream << "{" << x << ", " << y << ", " << z << ", " << w << "}"; - return stream.str(); +template <> +Scalar Cast(const Scalar& s) { + return s; } } // namespace impeller diff --git a/impeller/geometry/vector.h b/impeller/geometry/vector.h index 00455fca5f0dc..d68aef1e4a540 100644 --- a/impeller/geometry/vector.h +++ b/impeller/geometry/vector.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include "impeller/geometry/color.h" @@ -14,27 +15,46 @@ namespace impeller { -struct Vector3 { +template +T Cast(const U& u); + +template <> +Half Cast(const Scalar& s); + +template <> +Half Cast(const Half& s); + +template <> +Scalar Cast(const Scalar& s); + +template +struct TVector3 { + using Type = T; + union { struct { - Scalar x = 0.0; - Scalar y = 0.0; - Scalar z = 0.0; + Type x = 0.0; + Type y = 0.0; + Type z = 0.0; }; - Scalar e[3]; + Type e[3]; }; - constexpr Vector3(){}; + constexpr TVector3(){}; + + constexpr TVector3(const Color& c) : x(c.red), y(c.green), z(c.blue) {} - constexpr Vector3(const Color& c) : x(c.red), y(c.green), z(c.blue) {} + constexpr TVector3(const Point& p) : x(p.x), y(p.y) {} - constexpr Vector3(const Point& p) : x(p.x), y(p.y) {} + constexpr TVector3(const Size& s) : x(s.width), y(s.height) {} - constexpr Vector3(const Size& s) : x(s.width), y(s.height) {} + constexpr TVector3(Type x, Type y) : x(x), y(y) {} - constexpr Vector3(Scalar x, Scalar y) : x(x), y(y) {} + constexpr TVector3(Type x, Type y, Type z) : x(x), y(y), z(z) {} - constexpr Vector3(Scalar x, Scalar y, Scalar z) : x(x), y(y), z(z) {} + template + constexpr TVector3(const TVector3& v) + : x(Cast(v.x)), y(Cast(v.y)), z(Cast(v.z)) {} /** * The length (or magnitude of the vector). @@ -43,124 +63,142 @@ struct Vector3 { */ constexpr Scalar Length() const { return sqrt(x * x + y * y + z * z); } - constexpr Vector3 Normalize() const { + constexpr TVector3 Normalize() const { const auto len = Length(); return {x / len, y / len, z / len}; } - constexpr Scalar Dot(const Vector3& other) const { + template + constexpr Scalar Dot(const TVector3& other) const { return ((x * other.x) + (y * other.y) + (z * other.z)); } - constexpr Vector3 Cross(const Vector3& other) const { + template + constexpr TVector3 Cross(const TVector3& other) const { return { - (y * other.z) - (z * other.y), // - (z * other.x) - (x * other.z), // - (x * other.y) - (y * other.x) // + static_cast((y * other.z) - (z * other.y)), // + static_cast((z * other.x) - (x * other.z)), // + static_cast((x * other.y) - (y * other.x)) // }; } - constexpr Vector3 Min(const Vector3& p) const { + constexpr TVector3 Min(const TVector3& p) const { return {std::min(x, p.x), std::min(y, p.y), std::min(z, p.z)}; } - constexpr Vector3 Max(const Vector3& p) const { + constexpr TVector3 Max(const TVector3& p) const { return {std::max(x, p.x), std::max(y, p.y), std::max(z, p.z)}; } - constexpr Vector3 Floor() const { + constexpr TVector3 Floor() const { return {std::floor(x), std::floor(y), std::floor(z)}; } - constexpr Vector3 Ceil() const { + constexpr TVector3 Ceil() const { return {std::ceil(x), std::ceil(y), std::ceil(z)}; } - constexpr Vector3 Round() const { + constexpr TVector3 Round() const { return {std::round(x), std::round(y), std::round(z)}; } - constexpr bool operator==(const Vector3& v) const { + template + constexpr bool operator==(const TVector3& v) const { return v.x == x && v.y == y && v.z == z; } - constexpr bool operator!=(const Vector3& v) const { + template + constexpr bool operator!=(const TVector3& v) const { return v.x != x || v.y != y || v.z != z; } - constexpr Vector3 operator+=(const Vector3& p) { - x += p.x; - y += p.y; - z += p.z; + template + constexpr TVector3 operator+=(const TVector3& p) { + x += static_cast(p.x); + y += static_cast(p.y); + z += static_cast(p.z); return *this; } - constexpr Vector3 operator-=(const Vector3& p) { - x -= p.x; - y -= p.y; - z -= p.z; + template + constexpr TVector3 operator-=(const TVector3& p) { + x -= static_cast(p.x); + y -= static_cast(p.y); + z -= static_cast(p.z); return *this; } - constexpr Vector3 operator*=(const Vector3& p) { - x *= p.x; - y *= p.y; - z *= p.z; + template + constexpr TVector3 operator*=(const TVector3& p) { + x *= static_cast(p.x); + y *= static_cast(p.y); + z *= static_cast(p.z); return *this; } template >> - constexpr Vector3 operator*=(U scale) { + constexpr TVector3 operator*=(U scale) { x *= scale; y *= scale; z *= scale; return *this; } - constexpr Vector3 operator/=(const Vector3& p) { - x /= p.x; - y /= p.y; - z /= p.z; + template + constexpr TVector3 operator/=(const TVector3& p) { + x /= static_cast(p.x); + y /= static_cast(p.y); + z /= static_cast(p.z); return *this; } template >> - constexpr Vector3 operator/=(U scale) { + constexpr TVector3 operator/=(U scale) { x /= scale; y /= scale; z /= scale; return *this; } - constexpr Vector3 operator-() const { return Vector3(-x, -y, -z); } + constexpr TVector3 operator-() const { return TVector3(-x, -y, -z); } - constexpr Vector3 operator+(const Vector3& v) const { - return Vector3(x + v.x, y + v.y, z + v.z); + template + constexpr TVector3 operator+(const TVector3& v) const { + return TVector3(x + static_cast(v.x), y + static_cast(v.y), + z + static_cast(v.z)); } - constexpr Vector3 operator-(const Vector3& v) const { - return Vector3(x - v.x, y - v.y, z - v.z); + template + constexpr TVector3 operator-(const TVector3& v) const { + return TVector3(x - static_cast(v.x), y - static_cast(v.y), + z - static_cast(v.z)); } - constexpr Vector3 operator*(const Vector3& v) const { - return Vector3(x * v.x, y * v.y, z * v.z); + template + constexpr TVector3 operator*(const TVector3& v) const { + return TVector3(x * static_cast(v.x), y * static_cast(v.y), + z * static_cast(v.z)); } template >> - constexpr Vector3 operator*(U scale) const { - return Vector3(x * scale, y * scale, z * scale); + constexpr TVector3 operator*(U scale) const { + return TVector3(x * static_cast(scale), y * static_cast(scale), + z * static_cast(scale)); } - constexpr Vector3 operator/(const Vector3& v) const { - return Vector3(x / v.x, y / v.y, z / v.z); + template + constexpr TVector3 operator/(const TVector3& v) const { + return TVector3(x / static_cast(v.x), y / static_cast(v.y), + z / static_cast(v.z)); } template >> - constexpr Vector3 operator/(U scale) const { - return Vector3(x / scale, y / scale, z / scale); + constexpr TVector3 operator/(U scale) const { + return TVector3(x / static_cast(scale), y / static_cast(scale), + z / static_cast(scale)); } - constexpr Vector3 Lerp(const Vector3& v, Scalar t) const { + constexpr TVector3 Lerp(const TVector3& v, Scalar t) const { return *this + (v - *this) * t; } @@ -174,10 +212,11 @@ struct Vector3 { * * @return the combined vector. */ - static constexpr Vector3 Combine(const Vector3& a, - Scalar aScale, - const Vector3& b, - Scalar bScale) { + template >> + static constexpr TVector3 Combine(const TVector3& a, + Scalar aScale, + const TVector3& b, + Scalar bScale) { return { aScale * a.x + bScale * b.x, // aScale * a.y + bScale * b.y, // @@ -185,144 +224,143 @@ struct Vector3 { }; } - std::string ToString() const; + std::string ToString() const { + std::stringstream stream; + stream << "{" << x << ", " << y << ", " << z << "}"; + return stream.str(); + } }; // RHS algebraic operations with arithmetic types. template >> -constexpr Vector3 operator*(U s, const Vector3& p) { +constexpr TVector3 operator*(U s, const TVector3& p) { return p * s; } template >> -constexpr Vector3 operator/(U s, const Vector3& p) { +constexpr TVector3 operator/(U s, const TVector3& p) { return { - static_cast(s) / p.x, - static_cast(s) / p.y, - static_cast(s) / p.z, + s / p.x, + s / p.y, + s / p.z, }; } -struct Vector4 { +template +struct TVector4 { + using Type = T; union { struct { - Scalar x = 0.0; - Scalar y = 0.0; - Scalar z = 0.0; - Scalar w = 1.0; + Type x = 0.0; + Type y = 0.0; + Type z = 0.0; + Type w = 1.0; }; - Scalar e[4]; + Type e[4]; }; - constexpr Vector4() {} + constexpr TVector4() {} - constexpr Vector4(const Color& c) - : x(c.red), y(c.green), z(c.blue), w(c.alpha) {} + template + constexpr TVector4(const Color& c) + : x(Cast(c.red)), + y(Cast(c.green)), + z(Cast(c.blue)), + w(Cast(c.alpha)) {} - constexpr Vector4(Scalar x, Scalar y, Scalar z, Scalar w) - : x(x), y(y), z(z), w(w) {} + constexpr TVector4(Type x, Type y, Type z, Type w) : x(x), y(y), z(z), w(w) {} - constexpr Vector4(const Vector3& v) : x(v.x), y(v.y), z(v.z) {} + template + constexpr TVector4(const TVector4& v) + : x(Cast(v.x)), + y(Cast(v.y)), + z(Cast(v.z)), + w(Cast(v.w)) {} - constexpr Vector4(const Point& p) : x(p.x), y(p.y) {} + template + constexpr TVector4(const TVector3& v) + : x(Cast(v.x)), + y(Cast(v.y)), + z(Cast(v.z)) {} - Vector4 Normalize() const { + constexpr TVector4(const Point& p) : x(p.x), y(p.y) {} + + TVector4 Normalize() const { const Scalar inverse = 1.0 / sqrt(x * x + y * y + z * z + w * w); - return Vector4(x * inverse, y * inverse, z * inverse, w * inverse); + return TVector4(x * inverse, y * inverse, z * inverse, w * inverse); } - constexpr bool operator==(const Vector4& v) const { + template + constexpr bool operator==(const TVector4& v) const { return (x == v.x) && (y == v.y) && (z == v.z) && (w == v.w); } - constexpr bool operator!=(const Vector4& v) const { + template + constexpr bool operator!=(const TVector4& v) const { return (x != v.x) || (y != v.y) || (z != v.z) || (w != v.w); } - constexpr Vector4 operator+(const Vector4& v) const { - return Vector4(x + v.x, y + v.y, z + v.z, w + v.w); + template + constexpr TVector4 operator+(const TVector4& v) const { + return TVector4(x + v.x, y + v.y, z + v.z, w + v.w); } - constexpr Vector4 operator-(const Vector4& v) const { - return Vector4(x - v.x, y - v.y, z - v.z, w - v.w); + template + constexpr TVector4 operator-(const TVector4& v) const { + return TVector4(x - v.x, y - v.y, z - v.z, w - v.w); } - constexpr Vector4 operator*(Scalar f) const { - return Vector4(x * f, y * f, z * f, w * f); + template >> + constexpr TVector4 operator*(U f) const { + return TVector4(x * f, y * f, z * f, w * f); } - constexpr Vector4 operator*(const Vector4& v) const { + template + constexpr TVector4 operator*(const TVector4& v) const { return Vector4(x * v.x, y * v.y, z * v.z, w * v.w); } - constexpr Vector4 Min(const Vector4& p) const { + constexpr TVector4 Min(const TVector4& p) const { return {std::min(x, p.x), std::min(y, p.y), std::min(z, p.z), std::min(w, p.w)}; } - constexpr Vector4 Max(const Vector4& p) const { + constexpr TVector4 Max(const TVector4& p) const { return {std::max(x, p.x), std::max(y, p.y), std::max(z, p.z), std::max(w, p.w)}; } - constexpr Vector4 Floor() const { + constexpr TVector4 Floor() const { return {std::floor(x), std::floor(y), std::floor(z), std::floor(w)}; } - constexpr Vector4 Ceil() const { + constexpr TVector4 Ceil() const { return {std::ceil(x), std::ceil(y), std::ceil(z), std::ceil(w)}; } - constexpr Vector4 Round() const { + constexpr TVector4 Round() const { return {std::round(x), std::round(y), std::round(z), std::round(w)}; } - constexpr Vector4 Lerp(const Vector4& v, Scalar t) const { + constexpr TVector4 Lerp(const TVector4& v, Scalar t) const { return *this + (v - *this) * t; } - std::string ToString() const; + std::string ToString() const { + std::stringstream stream; + stream << "{" << x << ", " << y << ", " << z << ", " << w << "}"; + return stream.str(); + } }; +using Vector3 = TVector3; +using HalfVector3 = TVector3; +using Vector4 = TVector4; +using HalfVector4 = TVector4; + 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 From 68b1009e51f9313b8280e4e7e24cc4c3a5779e3b Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 24 Mar 2023 13:06:33 -0700 Subject: [PATCH 04/22] ++ --- impeller/compiler/shader_lib/impeller/types.glsl | 2 +- impeller/geometry/color.h | 3 ++- impeller/geometry/vector.h | 4 +--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/impeller/compiler/shader_lib/impeller/types.glsl b/impeller/compiler/shader_lib/impeller/types.glsl index d6de42a47e937..a2d9dbf668c41 100644 --- a/impeller/compiler/shader_lib/impeller/types.glsl +++ b/impeller/compiler/shader_lib/impeller/types.glsl @@ -7,7 +7,7 @@ #extension GL_AMD_gpu_shader_half_float : enable #extension GL_AMD_gpu_shader_half_float_fetch : enable -#extension GL_EXT_shader_explicit_arithmetic_types_float16: enable +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable #ifndef IMPELLER_TARGET_METAL diff --git a/impeller/geometry/color.h b/impeller/geometry/color.h index f99e21c100827..37325bab5fb0c 100644 --- a/impeller/geometry/color.h +++ b/impeller/geometry/color.h @@ -14,7 +14,8 @@ namespace impeller { struct ColorHSB; -template struct TVector4; +template +struct TVector4; using Vector4 = TVector4; enum class YUVColorSpace { kBT601LimitedRange, kBT601FullRange }; diff --git a/impeller/geometry/vector.h b/impeller/geometry/vector.h index d68aef1e4a540..3c92af2117669 100644 --- a/impeller/geometry/vector.h +++ b/impeller/geometry/vector.h @@ -280,9 +280,7 @@ struct TVector4 { template constexpr TVector4(const TVector3& v) - : x(Cast(v.x)), - y(Cast(v.y)), - z(Cast(v.z)) {} + : x(Cast(v.x)), y(Cast(v.y)), z(Cast(v.z)) {} constexpr TVector4(const Point& p) : x(p.x), y(p.y) {} From b6e6f81ce88421904770ffa2e77cdd082a9ce07e Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 24 Mar 2023 13:57:45 -0700 Subject: [PATCH 05/22] ++ --- impeller/compiler/reflector.cc | 9 +- impeller/geometry/BUILD.gn | 3 +- impeller/geometry/color.h | 5 +- impeller/geometry/{scalar.cc => half.cc} | 14 +- impeller/geometry/half.h | 87 ++++++++ impeller/geometry/point.h | 2 - impeller/geometry/scalar.h | 8 - impeller/geometry/vector.cc | 20 +- impeller/geometry/vector.h | 273 ++++++++--------------- impeller/renderer/shader_types.h | 1 + 10 files changed, 214 insertions(+), 208 deletions(-) rename impeller/geometry/{scalar.cc => half.cc} (86%) create mode 100644 impeller/geometry/half.h diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index 184a72e347eed..a9bc08d521169 100644 --- a/impeller/compiler/reflector.cc +++ b/impeller/compiler/reflector.cc @@ -18,6 +18,7 @@ #include "impeller/compiler/code_gen_template.h" #include "impeller/compiler/uniform_sorter.h" #include "impeller/compiler/utilities.h" +#include "impeller/geometry/half.h" #include "impeller/geometry/matrix.h" #include "impeller/geometry/scalar.h" @@ -779,14 +780,14 @@ std::vector Reflector::ReadStructMembers( member.vecsize == 2 // ) { uint32_t stride = - GetArrayStride(struct_type, member, i); - uint32_t element_padding = stride - sizeof(HalfPoint); + GetArrayStride(struct_type, member, i); + uint32_t element_padding = stride - sizeof(HalfVector2); result.emplace_back(StructMember{ - "HalfPoint", // type + "HalfVector2", // type BaseTypeToString(member.basetype), // basetype GetMemberNameAtIndex(struct_type, i), // name struct_member_offset, // offset - sizeof(HalfPoint), // size + sizeof(HalfVector2), // size stride * array_elements.value_or(1), // byte_length array_elements, // array_elements element_padding, // element_padding diff --git a/impeller/geometry/BUILD.gn b/impeller/geometry/BUILD.gn index 42fe21bb1e410..7a970f09a7a5e 100644 --- a/impeller/geometry/BUILD.gn +++ b/impeller/geometry/BUILD.gn @@ -12,6 +12,8 @@ impeller_component("geometry") { "constants.h", "gradient.cc", "gradient.h", + "half.cc", + "half.h", "matrix.cc", "matrix.h", "matrix_decomposition.cc", @@ -28,7 +30,6 @@ impeller_component("geometry") { "quaternion.h", "rect.cc", "rect.h", - "scalar.cc", "scalar.h", "shear.cc", "shear.h", diff --git a/impeller/geometry/color.h b/impeller/geometry/color.h index 37325bab5fb0c..90a9c49f745c7 100644 --- a/impeller/geometry/color.h +++ b/impeller/geometry/color.h @@ -13,10 +13,7 @@ namespace impeller { struct ColorHSB; - -template -struct TVector4; -using Vector4 = TVector4; +struct Vector4; enum class YUVColorSpace { kBT601LimitedRange, kBT601FullRange }; diff --git a/impeller/geometry/scalar.cc b/impeller/geometry/half.cc similarity index 86% rename from impeller/geometry/scalar.cc rename to impeller/geometry/half.cc index 4b16786794ba0..3b4f3c9b16e41 100644 --- a/impeller/geometry/scalar.cc +++ b/impeller/geometry/half.cc @@ -2,14 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "scalar.h" +#include "half.h" namespace impeller { +template <> +Half Cast(const Scalar& s) { + return ScalarToHalf(s); +} + +template <> +Scalar Cast(const Scalar& s) { + return s; +} + uint16_t ScalarToHalf(Scalar f) { // __fp16 foo = f; // return foo; - uint32_t x = *reinterpret_cast(&f); uint32_t sign = (uint16_t)(x >> 31); uint32_t mantissa; @@ -30,6 +39,7 @@ uint16_t ScalarToHalf(Scalar f) { 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 diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h new file mode 100644 index 0000000000000..d687ce75c28b0 --- /dev/null +++ b/impeller/geometry/half.h @@ -0,0 +1,87 @@ +// 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 "color.h" +#include "point.h" +#include "scalar.h" +#include "vector.h" + +namespace impeller { + +using Half = uint16_t; + +/// @brief Convert a scalar to a half precision float. +/// +/// Can express numbers in the range of 2^-14 to 65504. +/// Adapted from +/// https://developer.android.com/games/optimize/vertex-data-management . +Half ScalarToHalf(Scalar f); + +template +T Cast(const U& u); + +template <> +Half Cast(const Scalar& s); + +template <> +Scalar Cast(const Scalar& s); + +struct HalfVector4 { + union { + struct { + Half x = 0; + Half y = 0; + Half z = 0; + Half w = 0; + }; + Half e[4]; + }; + + constexpr HalfVector4() {} + + constexpr HalfVector4(const Color& a) + : x(ScalarToHalf(a.red)), + y(ScalarToHalf(a.green)), + z(ScalarToHalf(a.green)), + w(ScalarToHalf(a.alpha)){}; + + constexpr HalfVector4(const Vector4& a) + : x(ScalarToHalf(a.x)), + y(ScalarToHalf(a.y)), + z(ScalarToHalf(a.z)), + w(ScalarToHalf(a.w)){}; +}; + +struct HalfVector3 { + union { + struct { + Half x = 0; + Half y = 0; + Half z = 0; + }; + Half e[3]; + }; + + constexpr HalfVector3(){}; + + constexpr HalfVector3(const Vector3& a) + : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)){}; +}; + +struct HalfVector2 { + union { + struct { + Half x = 0; + Half y = 0; + }; + Half e[2]; + }; + + constexpr HalfVector2(){}; + + constexpr HalfVector2(const Vector2& a) + : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)){}; +}; + +} // namespace impeller diff --git a/impeller/geometry/point.h b/impeller/geometry/point.h index 920b609e05e3b..6434fe5a285a5 100644 --- a/impeller/geometry/point.h +++ b/impeller/geometry/point.h @@ -308,8 +308,6 @@ using IPoint = TPoint; using IPoint32 = TPoint; using UintPoint32 = TPoint; using Vector2 = Point; -using HalfPoint = TPoint; -using HalfVector2 = TPoint; } // namespace impeller diff --git a/impeller/geometry/scalar.h b/impeller/geometry/scalar.h index 657b0fcf0dfc6..b3ed3c59169a1 100644 --- a/impeller/geometry/scalar.h +++ b/impeller/geometry/scalar.h @@ -14,7 +14,6 @@ namespace impeller { using Scalar = float; -using Half = uint16_t; template >> constexpr T Absolute(const T& val) { @@ -54,11 +53,4 @@ struct Degrees { }; }; -/// @brief Convert a scalar to a half precision float. -/// -/// Can express numbers in the range of 2^-14 to 65504. -/// Adapted from -/// https://developer.android.com/games/optimize/vertex-data-management . -Half ScalarToHalf(Scalar f); - } // namespace impeller diff --git a/impeller/geometry/vector.cc b/impeller/geometry/vector.cc index cde0b3c05cddd..fecc8476d3f3f 100644 --- a/impeller/geometry/vector.cc +++ b/impeller/geometry/vector.cc @@ -3,22 +3,20 @@ // found in the LICENSE file. #include "vector.h" +#include namespace impeller { -template <> -Half Cast(const Scalar& s) { - return ScalarToHalf(s); +std::string Vector3::ToString() const { + std::stringstream stream; + stream << "{" << x << ", " << y << ", " << z << "}"; + return stream.str(); } -template <> -Half Cast(const Half& s) { - return s; -} - -template <> -Scalar Cast(const Scalar& s) { - return s; +std::string Vector4::ToString() const { + std::stringstream stream; + stream << "{" << x << ", " << y << ", " << z << ", " << w << "}"; + return stream.str(); } } // namespace impeller diff --git a/impeller/geometry/vector.h b/impeller/geometry/vector.h index 3c92af2117669..705a88ca056b5 100644 --- a/impeller/geometry/vector.h +++ b/impeller/geometry/vector.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include "impeller/geometry/color.h" @@ -15,46 +14,27 @@ namespace impeller { -template -T Cast(const U& u); - -template <> -Half Cast(const Scalar& s); - -template <> -Half Cast(const Half& s); - -template <> -Scalar Cast(const Scalar& s); - -template -struct TVector3 { - using Type = T; - +struct Vector3 { union { struct { - Type x = 0.0; - Type y = 0.0; - Type z = 0.0; + Scalar x = 0.0; + Scalar y = 0.0; + Scalar z = 0.0; }; - Type e[3]; + Scalar e[3]; }; - constexpr TVector3(){}; - - constexpr TVector3(const Color& c) : x(c.red), y(c.green), z(c.blue) {} + constexpr Vector3(){}; - constexpr TVector3(const Point& p) : x(p.x), y(p.y) {} + constexpr Vector3(const Color& c) : x(c.red), y(c.green), z(c.blue) {} - constexpr TVector3(const Size& s) : x(s.width), y(s.height) {} + constexpr Vector3(const Point& p) : x(p.x), y(p.y) {} - constexpr TVector3(Type x, Type y) : x(x), y(y) {} + constexpr Vector3(const Size& s) : x(s.width), y(s.height) {} - constexpr TVector3(Type x, Type y, Type z) : x(x), y(y), z(z) {} + constexpr Vector3(Scalar x, Scalar y) : x(x), y(y) {} - template - constexpr TVector3(const TVector3& v) - : x(Cast(v.x)), y(Cast(v.y)), z(Cast(v.z)) {} + constexpr Vector3(Scalar x, Scalar y, Scalar z) : x(x), y(y), z(z) {} /** * The length (or magnitude of the vector). @@ -63,142 +43,124 @@ struct TVector3 { */ constexpr Scalar Length() const { return sqrt(x * x + y * y + z * z); } - constexpr TVector3 Normalize() const { + constexpr Vector3 Normalize() const { const auto len = Length(); return {x / len, y / len, z / len}; } - template - constexpr Scalar Dot(const TVector3& other) const { + constexpr Scalar Dot(const Vector3& other) const { return ((x * other.x) + (y * other.y) + (z * other.z)); } - template - constexpr TVector3 Cross(const TVector3& other) const { + constexpr Vector3 Cross(const Vector3& other) const { return { - static_cast((y * other.z) - (z * other.y)), // - static_cast((z * other.x) - (x * other.z)), // - static_cast((x * other.y) - (y * other.x)) // + (y * other.z) - (z * other.y), // + (z * other.x) - (x * other.z), // + (x * other.y) - (y * other.x) // }; } - constexpr TVector3 Min(const TVector3& p) const { + constexpr Vector3 Min(const Vector3& p) const { return {std::min(x, p.x), std::min(y, p.y), std::min(z, p.z)}; } - constexpr TVector3 Max(const TVector3& p) const { + constexpr Vector3 Max(const Vector3& p) const { return {std::max(x, p.x), std::max(y, p.y), std::max(z, p.z)}; } - constexpr TVector3 Floor() const { + constexpr Vector3 Floor() const { return {std::floor(x), std::floor(y), std::floor(z)}; } - constexpr TVector3 Ceil() const { + constexpr Vector3 Ceil() const { return {std::ceil(x), std::ceil(y), std::ceil(z)}; } - constexpr TVector3 Round() const { + constexpr Vector3 Round() const { return {std::round(x), std::round(y), std::round(z)}; } - template - constexpr bool operator==(const TVector3& v) const { + constexpr bool operator==(const Vector3& v) const { return v.x == x && v.y == y && v.z == z; } - template - constexpr bool operator!=(const TVector3& v) const { + constexpr bool operator!=(const Vector3& v) const { return v.x != x || v.y != y || v.z != z; } - template - constexpr TVector3 operator+=(const TVector3& p) { - x += static_cast(p.x); - y += static_cast(p.y); - z += static_cast(p.z); + constexpr Vector3 operator+=(const Vector3& p) { + x += p.x; + y += p.y; + z += p.z; return *this; } - template - constexpr TVector3 operator-=(const TVector3& p) { - x -= static_cast(p.x); - y -= static_cast(p.y); - z -= static_cast(p.z); + constexpr Vector3 operator-=(const Vector3& p) { + x -= p.x; + y -= p.y; + z -= p.z; return *this; } - template - constexpr TVector3 operator*=(const TVector3& p) { - x *= static_cast(p.x); - y *= static_cast(p.y); - z *= static_cast(p.z); + constexpr Vector3 operator*=(const Vector3& p) { + x *= p.x; + y *= p.y; + z *= p.z; return *this; } template >> - constexpr TVector3 operator*=(U scale) { + constexpr Vector3 operator*=(U scale) { x *= scale; y *= scale; z *= scale; return *this; } - template - constexpr TVector3 operator/=(const TVector3& p) { - x /= static_cast(p.x); - y /= static_cast(p.y); - z /= static_cast(p.z); + constexpr Vector3 operator/=(const Vector3& p) { + x /= p.x; + y /= p.y; + z /= p.z; return *this; } template >> - constexpr TVector3 operator/=(U scale) { + constexpr Vector3 operator/=(U scale) { x /= scale; y /= scale; z /= scale; return *this; } - constexpr TVector3 operator-() const { return TVector3(-x, -y, -z); } + constexpr Vector3 operator-() const { return Vector3(-x, -y, -z); } - template - constexpr TVector3 operator+(const TVector3& v) const { - return TVector3(x + static_cast(v.x), y + static_cast(v.y), - z + static_cast(v.z)); + constexpr Vector3 operator+(const Vector3& v) const { + return Vector3(x + v.x, y + v.y, z + v.z); } - template - constexpr TVector3 operator-(const TVector3& v) const { - return TVector3(x - static_cast(v.x), y - static_cast(v.y), - z - static_cast(v.z)); + constexpr Vector3 operator-(const Vector3& v) const { + return Vector3(x - v.x, y - v.y, z - v.z); } - template - constexpr TVector3 operator*(const TVector3& v) const { - return TVector3(x * static_cast(v.x), y * static_cast(v.y), - z * static_cast(v.z)); + constexpr Vector3 operator*(const Vector3& v) const { + return Vector3(x * v.x, y * v.y, z * v.z); } template >> - constexpr TVector3 operator*(U scale) const { - return TVector3(x * static_cast(scale), y * static_cast(scale), - z * static_cast(scale)); + constexpr Vector3 operator*(U scale) const { + return Vector3(x * scale, y * scale, z * scale); } - template - constexpr TVector3 operator/(const TVector3& v) const { - return TVector3(x / static_cast(v.x), y / static_cast(v.y), - z / static_cast(v.z)); + constexpr Vector3 operator/(const Vector3& v) const { + return Vector3(x / v.x, y / v.y, z / v.z); } template >> - constexpr TVector3 operator/(U scale) const { - return TVector3(x / static_cast(scale), y / static_cast(scale), - z / static_cast(scale)); + constexpr Vector3 operator/(U scale) const { + return Vector3(x / scale, y / scale, z / scale); } - constexpr TVector3 Lerp(const TVector3& v, Scalar t) const { + constexpr Vector3 Lerp(const Vector3& v, Scalar t) const { return *this + (v - *this) * t; } @@ -212,11 +174,10 @@ struct TVector3 { * * @return the combined vector. */ - template >> - static constexpr TVector3 Combine(const TVector3& a, - Scalar aScale, - const TVector3& b, - Scalar bScale) { + static constexpr Vector3 Combine(const Vector3& a, + Scalar aScale, + const Vector3& b, + Scalar bScale) { return { aScale * a.x + bScale * b.x, // aScale * a.y + bScale * b.y, // @@ -224,142 +185,108 @@ struct TVector3 { }; } - std::string ToString() const { - std::stringstream stream; - stream << "{" << x << ", " << y << ", " << z << "}"; - return stream.str(); - } + std::string ToString() const; }; // RHS algebraic operations with arithmetic types. template >> -constexpr TVector3 operator*(U s, const TVector3& p) { +constexpr Vector3 operator*(U s, const Vector3& p) { return p * s; } template >> -constexpr TVector3 operator/(U s, const TVector3& p) { +constexpr Vector3 operator/(U s, const Vector3& p) { return { - s / p.x, - s / p.y, - s / p.z, + static_cast(s) / p.x, + static_cast(s) / p.y, + static_cast(s) / p.z, }; } -template -struct TVector4 { - using Type = T; +struct Vector4 { union { struct { - Type x = 0.0; - Type y = 0.0; - Type z = 0.0; - Type w = 1.0; + Scalar x = 0.0; + Scalar y = 0.0; + Scalar z = 0.0; + Scalar w = 1.0; }; - Type e[4]; + Scalar e[4]; }; - constexpr TVector4() {} + constexpr Vector4() {} - template - constexpr TVector4(const Color& c) - : x(Cast(c.red)), - y(Cast(c.green)), - z(Cast(c.blue)), - w(Cast(c.alpha)) {} + constexpr Vector4(const Color& c) + : x(c.red), y(c.green), z(c.blue), w(c.alpha) {} - constexpr TVector4(Type x, Type y, Type z, Type w) : x(x), y(y), z(z), w(w) {} + constexpr Vector4(Scalar x, Scalar y, Scalar z, Scalar w) + : x(x), y(y), z(z), w(w) {} - template - constexpr TVector4(const TVector4& v) - : x(Cast(v.x)), - y(Cast(v.y)), - z(Cast(v.z)), - w(Cast(v.w)) {} + constexpr Vector4(const Vector3& v) : x(v.x), y(v.y), z(v.z) {} - template - constexpr TVector4(const TVector3& v) - : x(Cast(v.x)), y(Cast(v.y)), z(Cast(v.z)) {} + constexpr Vector4(const Point& p) : x(p.x), y(p.y) {} - constexpr TVector4(const Point& p) : x(p.x), y(p.y) {} - - TVector4 Normalize() const { + Vector4 Normalize() const { const Scalar inverse = 1.0 / sqrt(x * x + y * y + z * z + w * w); - return TVector4(x * inverse, y * inverse, z * inverse, w * inverse); + return Vector4(x * inverse, y * inverse, z * inverse, w * inverse); } - template - constexpr bool operator==(const TVector4& v) const { + constexpr bool operator==(const Vector4& v) const { return (x == v.x) && (y == v.y) && (z == v.z) && (w == v.w); } - template - constexpr bool operator!=(const TVector4& v) const { + constexpr bool operator!=(const Vector4& v) const { return (x != v.x) || (y != v.y) || (z != v.z) || (w != v.w); } - template - constexpr TVector4 operator+(const TVector4& v) const { - return TVector4(x + v.x, y + v.y, z + v.z, w + v.w); + constexpr Vector4 operator+(const Vector4& v) const { + return Vector4(x + v.x, y + v.y, z + v.z, w + v.w); } - template - constexpr TVector4 operator-(const TVector4& v) const { - return TVector4(x - v.x, y - v.y, z - v.z, w - v.w); + constexpr Vector4 operator-(const Vector4& v) const { + return Vector4(x - v.x, y - v.y, z - v.z, w - v.w); } - template >> - constexpr TVector4 operator*(U f) const { - return TVector4(x * f, y * f, z * f, w * f); + constexpr Vector4 operator*(Scalar f) const { + return Vector4(x * f, y * f, z * f, w * f); } - template - constexpr TVector4 operator*(const TVector4& v) const { + constexpr Vector4 operator*(const Vector4& v) const { return Vector4(x * v.x, y * v.y, z * v.z, w * v.w); } - constexpr TVector4 Min(const TVector4& p) const { + constexpr Vector4 Min(const Vector4& p) const { return {std::min(x, p.x), std::min(y, p.y), std::min(z, p.z), std::min(w, p.w)}; } - constexpr TVector4 Max(const TVector4& p) const { + constexpr Vector4 Max(const Vector4& p) const { return {std::max(x, p.x), std::max(y, p.y), std::max(z, p.z), std::max(w, p.w)}; } - constexpr TVector4 Floor() const { + constexpr Vector4 Floor() const { return {std::floor(x), std::floor(y), std::floor(z), std::floor(w)}; } - constexpr TVector4 Ceil() const { + constexpr Vector4 Ceil() const { return {std::ceil(x), std::ceil(y), std::ceil(z), std::ceil(w)}; } - constexpr TVector4 Round() const { + constexpr Vector4 Round() const { return {std::round(x), std::round(y), std::round(z), std::round(w)}; } - constexpr TVector4 Lerp(const TVector4& v, Scalar t) const { + constexpr Vector4 Lerp(const Vector4& v, Scalar t) const { return *this + (v - *this) * t; } - std::string ToString() const { - std::stringstream stream; - stream << "{" << x << ", " << y << ", " << z << ", " << w << "}"; - return stream.str(); - } + std::string ToString() const; }; -using Vector3 = TVector3; -using HalfVector3 = TVector3; -using Vector4 = TVector4; -using HalfVector4 = TVector4; - static_assert(sizeof(Vector3) == 3 * sizeof(Scalar)); static_assert(sizeof(Vector4) == 4 * sizeof(Scalar)); -static_assert(sizeof(HalfVector4) == 4 * sizeof(Half)); } // namespace impeller @@ -375,10 +302,4 @@ 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 diff --git a/impeller/renderer/shader_types.h b/impeller/renderer/shader_types.h index 400607c1f55f6..da0c6e3e2a1ff 100644 --- a/impeller/renderer/shader_types.h +++ b/impeller/renderer/shader_types.h @@ -11,6 +11,7 @@ #include "flutter/fml/hash_combine.h" #include "flutter/fml/logging.h" +#include "impeller/geometry/half.h" #include "impeller/geometry/matrix.h" #include "impeller/runtime_stage/runtime_types.h" From f1919b4cf3f011e5369bc5b92118cccf3828ca09 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 24 Mar 2023 14:12:09 -0700 Subject: [PATCH 06/22] ++ --- impeller/entity/contents/scene_contents.cc | 2 +- impeller/geometry/half.h | 2 ++ impeller/geometry/scalar.h | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/impeller/entity/contents/scene_contents.cc b/impeller/entity/contents/scene_contents.cc index 560de0a2cd9c5..37dbb702c7355 100644 --- a/impeller/entity/contents/scene_contents.cc +++ b/impeller/entity/contents/scene_contents.cc @@ -76,7 +76,7 @@ bool SceneContents::Render(const ContentContext& renderer, contents.SetGeometry(GetGeometry()); contents.SetTexture(subpass_target.GetRenderTargetTexture()); contents.SetEffectTransform( - Matrix::MakeScale(1.0f / entity.GetTransformation().GetScale())); + Matrix::MakeScale(1 / entity.GetTransformation().GetScale())); return contents.Render(renderer, entity, pass); } diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index d687ce75c28b0..c062d357d274d 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "color.h" #include "point.h" #include "scalar.h" diff --git a/impeller/geometry/scalar.h b/impeller/geometry/scalar.h index b3ed3c59169a1..8a080e18b52a9 100644 --- a/impeller/geometry/scalar.h +++ b/impeller/geometry/scalar.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include From a98fa07aad98119b6ea5614cbca84afe963e220c Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 24 Mar 2023 14:33:27 -0700 Subject: [PATCH 07/22] fix licenses --- ci/licenses_golden/licenses_flutter | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 06a15477f6de0..109a1e579dc00 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1288,6 +1288,8 @@ ORIGIN: ../../../flutter/impeller/geometry/constants.h + ../../../flutter/LICENS ORIGIN: ../../../flutter/impeller/geometry/geometry_benchmarks.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/gradient.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/gradient.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/geometry/half.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/geometry/half.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/matrix.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/matrix.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/matrix_decomposition.cc + ../../../flutter/LICENSE @@ -3828,6 +3830,8 @@ FILE: ../../../flutter/impeller/geometry/constants.h FILE: ../../../flutter/impeller/geometry/geometry_benchmarks.cc FILE: ../../../flutter/impeller/geometry/gradient.cc FILE: ../../../flutter/impeller/geometry/gradient.h +FILE: ../../../flutter/impeller/geometry/half.cc +FILE: ../../../flutter/impeller/geometry/half.h FILE: ../../../flutter/impeller/geometry/matrix.cc FILE: ../../../flutter/impeller/geometry/matrix.h FILE: ../../../flutter/impeller/geometry/matrix_decomposition.cc From 7dca49008e01792c04d8e821f6d72fcb48a9444e Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sat, 25 Mar 2023 10:44:20 -0700 Subject: [PATCH 08/22] make half a wrapper type --- impeller/geometry/geometry_unittests.cc | 9 +++++ impeller/geometry/half.cc | 10 ----- impeller/geometry/half.h | 49 ++++++++++++++----------- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 191d944952d79..cf4a8d7df4941 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -16,6 +16,7 @@ #include "impeller/geometry/point.h" #include "impeller/geometry/rect.h" #include "impeller/geometry/scalar.h" +#include "impeller/geometry/half.h" #include "impeller/geometry/size.h" namespace impeller { @@ -2086,5 +2087,13 @@ TEST(GeometryTest, Gradient) { } } +TEST(GeometryTest, Half) { + ASSERT_EQ(ScalarToHalf(0.0), 0); + + // 65504 is the largest possible half. + ASSERT_EQ(ScalarToHalf(65504.0f), 31743); + ASSERT_EQ(ScalarToHalf(65504.0f + 1), 31743); +} + } // namespace testing } // namespace impeller diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index 3b4f3c9b16e41..03d24fc7fc098 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -6,16 +6,6 @@ namespace impeller { -template <> -Half Cast(const Scalar& s) { - return ScalarToHalf(s); -} - -template <> -Scalar Cast(const Scalar& s) { - return s; -} - uint16_t ScalarToHalf(Scalar f) { // __fp16 foo = f; // return foo; diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index c062d357d274d..289673648faca 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -11,33 +11,33 @@ namespace impeller { -using Half = uint16_t; - /// @brief Convert a scalar to a half precision float. /// /// Can express numbers in the range of 2^-14 to 65504. /// Adapted from /// https://developer.android.com/games/optimize/vertex-data-management . -Half ScalarToHalf(Scalar f); +uint16_t ScalarToHalf(Scalar f); + -template -T Cast(const U& u); +/// @brief A storage only class for half precision floating point. +struct Half { + uint16_t x = 0; -template <> -Half Cast(const Scalar& s); + Half() = default; -template <> -Scalar Cast(const Scalar& s); + Half(Scalar value) : x(ScalarToHalf(value)) {} +}; +/// @brief A storage only class for half precision floating point vector 4. struct HalfVector4 { union { struct { - Half x = 0; - Half y = 0; - Half z = 0; - Half w = 0; + uint16_t x = 0; + uint16_t y = 0; + uint16_t z = 0; + uint16_t w = 0; }; - Half e[4]; + uint16_t e[4]; }; constexpr HalfVector4() {} @@ -55,14 +55,15 @@ struct HalfVector4 { w(ScalarToHalf(a.w)){}; }; +/// @brief A storage only class for half precision floating point vector 3. struct HalfVector3 { union { struct { - Half x = 0; - Half y = 0; - Half z = 0; + uint16_t x = 0; + uint16_t y = 0; + uint16_t z = 0; }; - Half e[3]; + uint16_t e[3]; }; constexpr HalfVector3(){}; @@ -71,13 +72,14 @@ struct HalfVector3 { : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)){}; }; +/// @brief A storage only class for half precision floating point vector 2. struct HalfVector2 { union { struct { - Half x = 0; - Half y = 0; + uint16_t x = 0; + uint16_t y = 0; }; - Half e[2]; + uint16_t e[2]; }; constexpr HalfVector2(){}; @@ -86,4 +88,9 @@ struct HalfVector2 { : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)){}; }; +static_assert(sizeof(Half) == sizeof(uint16_t)); +static_assert(sizeof(HalfVector2) == 2 * sizeof(Half)); +static_assert(sizeof(HalfVector3) == 3 * sizeof(Half)); +static_assert(sizeof(HalfVector4) == 4 * sizeof(Half)); + } // namespace impeller From 9599b6280eed8be1876073e52fa3db9e988c5e12 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sat, 25 Mar 2023 11:05:54 -0700 Subject: [PATCH 09/22] use hardware supported conversion --- impeller/geometry/geometry_unittests.cc | 11 +++++--- impeller/geometry/half.cc | 34 ++----------------------- impeller/geometry/half.h | 33 +++++++++++------------- 3 files changed, 24 insertions(+), 54 deletions(-) diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index cf4a8d7df4941..89658c64ec997 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -10,13 +10,13 @@ #include "flutter/testing/testing.h" #include "impeller/geometry/constants.h" #include "impeller/geometry/gradient.h" +#include "impeller/geometry/half.h" #include "impeller/geometry/path.h" #include "impeller/geometry/path_builder.h" #include "impeller/geometry/path_component.h" #include "impeller/geometry/point.h" #include "impeller/geometry/rect.h" #include "impeller/geometry/scalar.h" -#include "impeller/geometry/half.h" #include "impeller/geometry/size.h" namespace impeller { @@ -2088,11 +2088,14 @@ TEST(GeometryTest, Gradient) { } TEST(GeometryTest, Half) { - ASSERT_EQ(ScalarToHalf(0.0), 0); + ASSERT_EQ(ScalarToHalf(0.0), 0.0f16); + ASSERT_EQ(ScalarToHalf(0.05), 0.05f16); + ASSERT_EQ(ScalarToHalf(2.43), 2.43f16); + ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16); // 65504 is the largest possible half. - ASSERT_EQ(ScalarToHalf(65504.0f), 31743); - ASSERT_EQ(ScalarToHalf(65504.0f + 1), 31743); + ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16); + ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16); } } // namespace testing diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index 03d24fc7fc098..42f99ccc5f978 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -6,38 +6,8 @@ namespace impeller { -uint16_t ScalarToHalf(Scalar f) { - // __fp16 foo = f; - // return foo; - uint32_t x = *reinterpret_cast(&f); - uint32_t sign = (uint16_t)(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; +_Float16 ScalarToHalf(Scalar f) { + return static_cast<_Float16>(f); } } // namespace impeller diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index 289673648faca..e2c702eb47037 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -13,15 +13,12 @@ namespace impeller { /// @brief Convert a scalar to a half precision float. /// -/// Can express numbers in the range of 2^-14 to 65504. -/// Adapted from -/// https://developer.android.com/games/optimize/vertex-data-management . -uint16_t ScalarToHalf(Scalar f); - +/// See also: https://clang.llvm.org/docs/LanguageExtensions.html +_Float16 ScalarToHalf(Scalar f); /// @brief A storage only class for half precision floating point. struct Half { - uint16_t x = 0; + _Float16 x = 0; Half() = default; @@ -32,12 +29,12 @@ struct Half { struct HalfVector4 { union { struct { - uint16_t x = 0; - uint16_t y = 0; - uint16_t z = 0; - uint16_t w = 0; + _Float16 x = 0; + _Float16 y = 0; + _Float16 z = 0; + _Float16 w = 0; }; - uint16_t e[4]; + _Float16 e[4]; }; constexpr HalfVector4() {} @@ -59,11 +56,11 @@ struct HalfVector4 { struct HalfVector3 { union { struct { - uint16_t x = 0; - uint16_t y = 0; - uint16_t z = 0; + _Float16 x = 0; + _Float16 y = 0; + _Float16 z = 0; }; - uint16_t e[3]; + _Float16 e[3]; }; constexpr HalfVector3(){}; @@ -76,10 +73,10 @@ struct HalfVector3 { struct HalfVector2 { union { struct { - uint16_t x = 0; - uint16_t y = 0; + _Float16 x = 0; + _Float16 y = 0; }; - uint16_t e[2]; + _Float16 e[2]; }; constexpr HalfVector2(){}; From 4bdc197c166832676b8e79219f60d5b8147ef25d Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sun, 26 Mar 2023 11:58:49 -0700 Subject: [PATCH 10/22] disable for windows and add more conversion tests --- impeller/geometry/geometry_unittests.cc | 23 ++++- impeller/geometry/half.cc | 7 +- impeller/geometry/half.h | 129 +++++++++++++++++++----- 3 files changed, 133 insertions(+), 26 deletions(-) diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 89658c64ec997..30f0ab61265a3 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -7,6 +7,7 @@ #include #include +#include "flutter/fml/build_config.h" #include "flutter/testing/testing.h" #include "impeller/geometry/constants.h" #include "impeller/geometry/gradient.h" @@ -2087,7 +2088,8 @@ TEST(GeometryTest, Gradient) { } } -TEST(GeometryTest, Half) { +TEST(GeometryTest, HalfConversions) { +#ifndef FML_OS_WIN ASSERT_EQ(ScalarToHalf(0.0), 0.0f16); ASSERT_EQ(ScalarToHalf(0.05), 0.05f16); ASSERT_EQ(ScalarToHalf(2.43), 2.43f16); @@ -2096,6 +2098,25 @@ TEST(GeometryTest, Half) { // 65504 is the largest possible half. ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16); ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16); + + // Colors + ASSERT_EQ(HalfVector4(Color::Red()), + HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16)); + ASSERT_EQ(HalfVector4(Color::Green()), + HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16)); + ASSERT_EQ(HalfVector4(Color::Blue()), + HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16)); + ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)), + HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16)); + + ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)), + HalfVector3(4.0f16, 6.0f16, -1.0f16)); + ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16)); + + ASSERT_EQ(Half(0.5f), Half(0.5f16)); + ASSERT_EQ(Half(0.5), Half(0.5f16)); + ASSERT_EQ(Half(5), Half(5.0f16)); +#endif // FML_OS_WIN } } // namespace testing diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index 42f99ccc5f978..0fc7f52f543a9 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -6,8 +6,11 @@ namespace impeller { -_Float16 ScalarToHalf(Scalar f) { - return static_cast<_Float16>(f); +_Half ScalarToHalf(Scalar f) { +#ifdef FML_OS_WIN + FML_LOG(ERROR) << "ScalarToHalf conversion on unsupported platform."; +#endif + return static_cast<_Half>(f); } } // namespace impeller diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index e2c702eb47037..c3aa904a79002 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -4,37 +4,56 @@ #include +#include "flutter/fml/build_config.h" + #include "color.h" #include "point.h" #include "scalar.h" #include "vector.h" +#ifdef FML_OS_WIN +using _Half = uint16_t; +#else +using _Half = _Float16; +#endif + namespace impeller { /// @brief Convert a scalar to a half precision float. /// /// See also: https://clang.llvm.org/docs/LanguageExtensions.html -_Float16 ScalarToHalf(Scalar f); +/// This is not currently supported on windows toolchains. +_Half ScalarToHalf(Scalar f); /// @brief A storage only class for half precision floating point. struct Half { - _Float16 x = 0; + _Half x = 0; + + constexpr Half() {} + + constexpr Half(double value) : x(ScalarToHalf(static_cast(value))) {} + + constexpr Half(Scalar value) : x(ScalarToHalf(value)) {} - Half() = default; + constexpr Half(int value) : x(ScalarToHalf(static_cast(value))) {} - Half(Scalar value) : x(ScalarToHalf(value)) {} + constexpr Half(_Half x) : x(x) {} + + constexpr bool operator==(const Half& v) const { return v.x == x; } + + constexpr bool operator!=(const Half& v) const { return v.x != x; } }; /// @brief A storage only class for half precision floating point vector 4. struct HalfVector4 { union { struct { - _Float16 x = 0; - _Float16 y = 0; - _Float16 z = 0; - _Float16 w = 0; + _Half x = 0; + _Half y = 0; + _Half z = 0; + _Half w = 0; }; - _Float16 e[4]; + _Half e[4]; }; constexpr HalfVector4() {} @@ -42,47 +61,78 @@ struct HalfVector4 { constexpr HalfVector4(const Color& a) : x(ScalarToHalf(a.red)), y(ScalarToHalf(a.green)), - z(ScalarToHalf(a.green)), - w(ScalarToHalf(a.alpha)){}; + z(ScalarToHalf(a.blue)), + w(ScalarToHalf(a.alpha)) {} constexpr HalfVector4(const Vector4& a) : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)), - w(ScalarToHalf(a.w)){}; + w(ScalarToHalf(a.w)) {} + + constexpr HalfVector4(_Half x, _Half y, _Half z, _Half w) + : x(x), y(y), z(z), w(w) {} + + constexpr bool operator==(const HalfVector4& v) const { + return v.x == x && v.y == y && v.z == z && v.w == w; + } + + constexpr bool operator!=(const HalfVector4& v) const { + return v.x != x || v.y != y || v.z != z || v.w != w; + } }; /// @brief A storage only class for half precision floating point vector 3. struct HalfVector3 { union { struct { - _Float16 x = 0; - _Float16 y = 0; - _Float16 z = 0; + _Half x = 0; + _Half y = 0; + _Half z = 0; }; - _Float16 e[3]; + _Half e[3]; }; - constexpr HalfVector3(){}; + constexpr HalfVector3() {} constexpr HalfVector3(const Vector3& a) - : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)){}; + : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)) {} + + constexpr HalfVector3(_Half x, _Half y, _Half z) : x(x), y(y), z(z) {} + + constexpr bool operator==(const HalfVector3& v) const { + return v.x == x && v.y == y && v.z == z; + } + + constexpr bool operator!=(const HalfVector3& v) const { + return v.x != x || v.y != y || v.z != z; + } }; /// @brief A storage only class for half precision floating point vector 2. struct HalfVector2 { union { struct { - _Float16 x = 0; - _Float16 y = 0; + _Half x = 0; + _Half y = 0; }; - _Float16 e[2]; + _Half e[2]; }; - constexpr HalfVector2(){}; + constexpr HalfVector2() {} constexpr HalfVector2(const Vector2& a) - : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)){}; + : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)) {} + + constexpr HalfVector2(_Half x, _Half y) : x(x), y(y){}; + + constexpr bool operator==(const HalfVector2& v) const { + return v.x == x && v.y == y; + } + + constexpr bool operator!=(const HalfVector2& v) const { + return v.x != x || v.y != y; + } }; static_assert(sizeof(Half) == sizeof(uint16_t)); @@ -91,3 +141,36 @@ static_assert(sizeof(HalfVector3) == 3 * sizeof(Half)); static_assert(sizeof(HalfVector4) == 4 * sizeof(Half)); } // namespace impeller + +namespace std { + +inline std::ostream& operator<<(std::ostream& out, const impeller::Half& p) { + out << "(" << static_cast(p.x) << ")"; + return out; +} + +inline std::ostream& operator<<(std::ostream& out, + const impeller::HalfVector2& p) { + out << "(" << static_cast(p.x) << ", " + << static_cast(p.y) << ")"; + return out; +} + +inline std::ostream& operator<<(std::ostream& out, + const impeller::HalfVector3& p) { + out << "(" << static_cast(p.x) << ", " + << static_cast(p.y) << ", " + << static_cast(p.z) << ")"; + return out; +} + +inline std::ostream& operator<<(std::ostream& out, + const impeller::HalfVector4& p) { + out << "(" << static_cast(p.x) << ", " + << static_cast(p.y) << ", " + << static_cast(p.z) << ", " + << static_cast(p.w) << ")"; + return out; +} + +} // namespace std From a8b80ed8d610f96f7aba3d30c009d9ba279a8516 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sun, 26 Mar 2023 12:08:55 -0700 Subject: [PATCH 11/22] compile --- impeller/geometry/half.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index 0fc7f52f543a9..aadffde0948df 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -4,6 +4,8 @@ #include "half.h" +#include "flutter/fml/trace_event.h" + namespace impeller { _Half ScalarToHalf(Scalar f) { From 8e9892bcfd66de5e38f5bcd91b070e4c2d544a4e Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sun, 26 Mar 2023 13:07:03 -0700 Subject: [PATCH 12/22] ++ --- impeller/geometry/half.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index aadffde0948df..e05a8307e6d19 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -4,7 +4,7 @@ #include "half.h" -#include "flutter/fml/trace_event.h" +#include "flutter/fml/logging.h" namespace impeller { From 22a0bd1d8bfb4c329ff6c504130bfdd72c49557b Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 27 Mar 2023 13:51:37 -0700 Subject: [PATCH 13/22] test --- impeller/fixtures/BUILD.gn | 5 +++ impeller/fixtures/half.frag | 21 ++++++++++ impeller/geometry/geometry_unittests.cc | 5 ++- impeller/geometry/half.cc | 4 +- impeller/geometry/half.h | 52 +++++++++++++------------ 5 files changed, 59 insertions(+), 28 deletions(-) create mode 100644 impeller/fixtures/half.frag diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn index 8dee5288196f8..d42c0c68e6ba4 100644 --- a/impeller/fixtures/BUILD.gn +++ b/impeller/fixtures/BUILD.gn @@ -55,8 +55,13 @@ impeller_shaders("shader_fixtures") { "sample.comp", "stage1.comp", "stage2.comp", + "half.frag", ] } + + if (impeller_enable_metal) { + shaders += [ "half.frag" ] + } } scenec("scene_fixtures") { diff --git a/impeller/fixtures/half.frag b/impeller/fixtures/half.frag new file mode 100644 index 0000000000000..527476d8b6eb8 --- /dev/null +++ b/impeller/fixtures/half.frag @@ -0,0 +1,21 @@ +// 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. + +#extension GL_AMD_gpu_shader_half_float : enable +#extension GL_AMD_gpu_shader_half_float_fetch : enable +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable + +uniform FragInfo { + float16_t half_1; + f16vec2 half_2; + f16vec3 half_3; + f16vec4 half_4; +} +frag_info; + +out vec4 frag_color; + +void main() { + frag_color = vec4(0); +} diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 30f0ab61265a3..f712f71576616 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -2089,7 +2089,9 @@ TEST(GeometryTest, Gradient) { } TEST(GeometryTest, HalfConversions) { -#ifndef FML_OS_WIN +#ifdef FML_OS_WIN + GTEST_SKIP() << "The reason this doesn't work on Windows"; +#endif ASSERT_EQ(ScalarToHalf(0.0), 0.0f16); ASSERT_EQ(ScalarToHalf(0.05), 0.05f16); ASSERT_EQ(ScalarToHalf(2.43), 2.43f16); @@ -2116,7 +2118,6 @@ TEST(GeometryTest, HalfConversions) { ASSERT_EQ(Half(0.5f), Half(0.5f16)); ASSERT_EQ(Half(0.5), Half(0.5f16)); ASSERT_EQ(Half(5), Half(5.0f16)); -#endif // FML_OS_WIN } } // namespace testing diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index e05a8307e6d19..1f5a4a656e883 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -8,11 +8,11 @@ namespace impeller { -_Half ScalarToHalf(Scalar f) { +InternalHalf ScalarToHalf(Scalar f) { #ifdef FML_OS_WIN FML_LOG(ERROR) << "ScalarToHalf conversion on unsupported platform."; #endif - return static_cast<_Half>(f); + return static_cast(f); } } // namespace impeller diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index c3aa904a79002..ebeea6330b294 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -6,15 +6,15 @@ #include "flutter/fml/build_config.h" -#include "color.h" -#include "point.h" -#include "scalar.h" -#include "vector.h" +#include "impeller/geometry/color.h" +#include "impeller/geometry/point.h" +#include "impeller/geometry/scalar.h" +#include "impeller/geometry/vector.h" #ifdef FML_OS_WIN -using _Half = uint16_t; +using InternalHalf = uint16_t; #else -using _Half = _Float16; +using InternalHalf = _Float16; #endif namespace impeller { @@ -23,11 +23,11 @@ namespace impeller { /// /// See also: https://clang.llvm.org/docs/LanguageExtensions.html /// This is not currently supported on windows toolchains. -_Half ScalarToHalf(Scalar f); +InternalHalf ScalarToHalf(Scalar f); /// @brief A storage only class for half precision floating point. struct Half { - _Half x = 0; + InternalHalf x = 0; constexpr Half() {} @@ -37,7 +37,7 @@ struct Half { constexpr Half(int value) : x(ScalarToHalf(static_cast(value))) {} - constexpr Half(_Half x) : x(x) {} + constexpr Half(InternalHalf x) : x(x) {} constexpr bool operator==(const Half& v) const { return v.x == x; } @@ -48,12 +48,12 @@ struct Half { struct HalfVector4 { union { struct { - _Half x = 0; - _Half y = 0; - _Half z = 0; - _Half w = 0; + InternalHalf x = 0; + InternalHalf y = 0; + InternalHalf z = 0; + InternalHalf w = 0; }; - _Half e[4]; + InternalHalf e[4]; }; constexpr HalfVector4() {} @@ -70,7 +70,10 @@ struct HalfVector4 { z(ScalarToHalf(a.z)), w(ScalarToHalf(a.w)) {} - constexpr HalfVector4(_Half x, _Half y, _Half z, _Half w) + constexpr HalfVector4(InternalHalf x, + InternalHalf y, + InternalHalf z, + InternalHalf w) : x(x), y(y), z(z), w(w) {} constexpr bool operator==(const HalfVector4& v) const { @@ -86,11 +89,11 @@ struct HalfVector4 { struct HalfVector3 { union { struct { - _Half x = 0; - _Half y = 0; - _Half z = 0; + InternalHalf x = 0; + InternalHalf y = 0; + InternalHalf z = 0; }; - _Half e[3]; + InternalHalf e[3]; }; constexpr HalfVector3() {} @@ -98,7 +101,8 @@ struct HalfVector3 { constexpr HalfVector3(const Vector3& a) : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)) {} - constexpr HalfVector3(_Half x, _Half y, _Half z) : x(x), y(y), z(z) {} + constexpr HalfVector3(InternalHalf x, InternalHalf y, InternalHalf z) + : x(x), y(y), z(z) {} constexpr bool operator==(const HalfVector3& v) const { return v.x == x && v.y == y && v.z == z; @@ -113,10 +117,10 @@ struct HalfVector3 { struct HalfVector2 { union { struct { - _Half x = 0; - _Half y = 0; + InternalHalf x = 0; + InternalHalf y = 0; }; - _Half e[2]; + InternalHalf e[2]; }; constexpr HalfVector2() {} @@ -124,7 +128,7 @@ struct HalfVector2 { constexpr HalfVector2(const Vector2& a) : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)) {} - constexpr HalfVector2(_Half x, _Half y) : x(x), y(y){}; + constexpr HalfVector2(InternalHalf x, InternalHalf y) : x(x), y(y){}; constexpr bool operator==(const HalfVector2& v) const { return v.x == x && v.y == y; From 251564b8f52aea4211a01310a63c78918d864716 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 27 Mar 2023 13:58:21 -0700 Subject: [PATCH 14/22] ++ --- impeller/fixtures/BUILD.gn | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn index d42c0c68e6ba4..cba9c78afe896 100644 --- a/impeller/fixtures/BUILD.gn +++ b/impeller/fixtures/BUILD.gn @@ -48,6 +48,7 @@ impeller_shaders("shader_fixtures") { "simple.vert", "test_texture.frag", "test_texture.vert", + "half.frag", ] if (impeller_enable_opengles) { @@ -58,10 +59,6 @@ impeller_shaders("shader_fixtures") { "half.frag", ] } - - if (impeller_enable_metal) { - shaders += [ "half.frag" ] - } } scenec("scene_fixtures") { From 51d7bb77cac1c348730c1f383eb82ceae43a509c Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 27 Mar 2023 14:03:07 -0700 Subject: [PATCH 15/22] ++ --- impeller/geometry/half.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index 1f5a4a656e883..b41f1e98a7a31 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "half.h" +#include "impeller/geometry/half.h" #include "flutter/fml/logging.h" From 9001fe16db20089098bf30f8f5126af8acbe92fd Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 27 Mar 2023 14:19:30 -0700 Subject: [PATCH 16/22] Update geometry_unittests.cc --- impeller/geometry/geometry_unittests.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index b106374644c6b..591962bd9eac0 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -2095,7 +2095,7 @@ TEST(GeometryTest, Gradient) { TEST(GeometryTest, HalfConversions) { #ifdef FML_OS_WIN GTEST_SKIP() << "The reason this doesn't work on Windows"; -#endif +#else ASSERT_EQ(ScalarToHalf(0.0), 0.0f16); ASSERT_EQ(ScalarToHalf(0.05), 0.05f16); ASSERT_EQ(ScalarToHalf(2.43), 2.43f16); @@ -2122,6 +2122,7 @@ TEST(GeometryTest, HalfConversions) { ASSERT_EQ(Half(0.5f), Half(0.5f16)); ASSERT_EQ(Half(0.5), Half(0.5f16)); ASSERT_EQ(Half(5), Half(5.0f16)); +#endif // FML_OS_WIN } } // namespace testing From 11f0c9fd33c82ea2ddc3dc63928e4cd02fb6ead1 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 27 Mar 2023 14:33:26 -0700 Subject: [PATCH 17/22] Update geometry_unittests.cc --- impeller/geometry/geometry_unittests.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 591962bd9eac0..1f5e3230480da 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -2122,7 +2122,7 @@ TEST(GeometryTest, HalfConversions) { ASSERT_EQ(Half(0.5f), Half(0.5f16)); ASSERT_EQ(Half(0.5), Half(0.5f16)); ASSERT_EQ(Half(5), Half(5.0f16)); -#endif // FML_OS_WIN +#endif // FML_OS_WIN } } // namespace testing From 6998f76a512f90fec46cca9636975b5a532575eb Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 27 Mar 2023 15:12:17 -0700 Subject: [PATCH 18/22] ++ --- impeller/compiler/shader_lib/impeller/types.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/compiler/shader_lib/impeller/types.glsl b/impeller/compiler/shader_lib/impeller/types.glsl index a2d9dbf668c41..0cc2fee2aa332 100644 --- a/impeller/compiler/shader_lib/impeller/types.glsl +++ b/impeller/compiler/shader_lib/impeller/types.glsl @@ -9,7 +9,7 @@ #extension GL_AMD_gpu_shader_half_float_fetch : enable #extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable -#ifndef IMPELLER_TARGET_METAL +#ifndef IMPELLER_TARGET_METAL_IOS precision mediump sampler2D; precision mediump float; From 736a3e506c81a009e2ff0b56e38b121c3633504f Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 27 Mar 2023 15:48:10 -0700 Subject: [PATCH 19/22] make this unreachable --- impeller/geometry/half.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc index b41f1e98a7a31..45bcf39fb7639 100644 --- a/impeller/geometry/half.cc +++ b/impeller/geometry/half.cc @@ -10,7 +10,7 @@ namespace impeller { InternalHalf ScalarToHalf(Scalar f) { #ifdef FML_OS_WIN - FML_LOG(ERROR) << "ScalarToHalf conversion on unsupported platform."; + FML_UNREACHABLE(); #endif return static_cast(f); } From 0af6ab989c54eec4d4c3afa0a75eb87a465d73ea Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 28 Mar 2023 13:46:24 -0700 Subject: [PATCH 20/22] ++ --- ci/licenses_golden/licenses_flutter | 2 -- impeller/compiler/reflector.cc | 6 +++--- impeller/geometry/BUILD.gn | 1 - impeller/geometry/geometry_unittests.cc | 3 ++- impeller/geometry/half.cc | 18 ------------------ impeller/geometry/half.h | 9 ++++++++- 6 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 impeller/geometry/half.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index a6b80db9c3320..e890eabfa2fe2 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1288,7 +1288,6 @@ ORIGIN: ../../../flutter/impeller/geometry/constants.h + ../../../flutter/LICENS ORIGIN: ../../../flutter/impeller/geometry/geometry_benchmarks.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/gradient.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/gradient.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/geometry/half.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/half.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/matrix.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/geometry/matrix.h + ../../../flutter/LICENSE @@ -3853,7 +3852,6 @@ FILE: ../../../flutter/impeller/geometry/constants.h FILE: ../../../flutter/impeller/geometry/geometry_benchmarks.cc FILE: ../../../flutter/impeller/geometry/gradient.cc FILE: ../../../flutter/impeller/geometry/gradient.h -FILE: ../../../flutter/impeller/geometry/half.cc FILE: ../../../flutter/impeller/geometry/half.h FILE: ../../../flutter/impeller/geometry/matrix.cc FILE: ../../../flutter/impeller/geometry/matrix.h diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index a9bc08d521169..93863aa03c234 100644 --- a/impeller/compiler/reflector.cc +++ b/impeller/compiler/reflector.cc @@ -775,7 +775,7 @@ std::vector Reflector::ReadStructMembers( // Tightly packed half Point (vec2). if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // - member.width == sizeof(float) * 4 && // + member.width == sizeof(Half) * 8 && // member.columns == 1 && // member.vecsize == 2 // ) { @@ -798,7 +798,7 @@ std::vector Reflector::ReadStructMembers( // Tightly packed Half Float Vector3. if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // - member.width == sizeof(float) * 4 && // + member.width == sizeof(Half) * 8 && // member.columns == 1 && // member.vecsize == 3 // ) { @@ -821,7 +821,7 @@ std::vector Reflector::ReadStructMembers( // Tightly packed Half Float Vector4. if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // - member.width == sizeof(float) * 4 && // + member.width == sizeof(Half) * 8 && // member.columns == 1 && // member.vecsize == 4 // ) { diff --git a/impeller/geometry/BUILD.gn b/impeller/geometry/BUILD.gn index 7a970f09a7a5e..9aaa4e8ec8149 100644 --- a/impeller/geometry/BUILD.gn +++ b/impeller/geometry/BUILD.gn @@ -12,7 +12,6 @@ impeller_component("geometry") { "constants.h", "gradient.cc", "gradient.h", - "half.cc", "half.h", "matrix.cc", "matrix.h", diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 1f5e3230480da..143de168ef293 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -2094,7 +2094,8 @@ TEST(GeometryTest, Gradient) { TEST(GeometryTest, HalfConversions) { #ifdef FML_OS_WIN - GTEST_SKIP() << "The reason this doesn't work on Windows"; + GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and " + "unavailable on Windows."; #else ASSERT_EQ(ScalarToHalf(0.0), 0.0f16); ASSERT_EQ(ScalarToHalf(0.05), 0.05f16); diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc deleted file mode 100644 index 45bcf39fb7639..0000000000000 --- a/impeller/geometry/half.cc +++ /dev/null @@ -1,18 +0,0 @@ -// 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 "impeller/geometry/half.h" - -#include "flutter/fml/logging.h" - -namespace impeller { - -InternalHalf ScalarToHalf(Scalar f) { -#ifdef FML_OS_WIN - FML_UNREACHABLE(); -#endif - return static_cast(f); -} - -} // namespace impeller diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index ebeea6330b294..6480f88583963 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#pragma once + #include #include "flutter/fml/build_config.h" @@ -23,7 +25,12 @@ namespace impeller { /// /// See also: https://clang.llvm.org/docs/LanguageExtensions.html /// This is not currently supported on windows toolchains. -InternalHalf ScalarToHalf(Scalar f); +inline constexpr InternalHalf ScalarToHalf(Scalar f) { +#ifdef FML_OS_WIN + FML_UNREACHABLE(); +#endif + return static_cast(f); +} /// @brief A storage only class for half precision floating point. struct Half { From c9ffbc5ac9303adebd68dc6181c866dbe7b10996 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 28 Mar 2023 14:40:52 -0700 Subject: [PATCH 21/22] ++ --- impeller/geometry/half.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index 6480f88583963..3612592369858 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -24,11 +24,8 @@ namespace impeller { /// @brief Convert a scalar to a half precision float. /// /// See also: https://clang.llvm.org/docs/LanguageExtensions.html -/// This is not currently supported on windows toolchains. +/// This is not currently supported on Windows toolchains. inline constexpr InternalHalf ScalarToHalf(Scalar f) { -#ifdef FML_OS_WIN - FML_UNREACHABLE(); -#endif return static_cast(f); } From 2f1f5c3b5a94ec031eb637d2273e9d3499316b4e Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 28 Mar 2023 14:44:41 -0700 Subject: [PATCH 22/22] ++ --- impeller/geometry/half.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index 3612592369858..ed81e16a110f4 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -26,7 +26,11 @@ namespace impeller { /// See also: https://clang.llvm.org/docs/LanguageExtensions.html /// This is not currently supported on Windows toolchains. inline constexpr InternalHalf ScalarToHalf(Scalar f) { +#ifdef FML_OS_WIN + return static_cast(0); +#else return static_cast(f); +#endif } /// @brief A storage only class for half precision floating point.