-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] support half precision uniforms and half precision samplers #40590
Changes from 10 commits
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 |
|---|---|---|
|
|
@@ -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" | ||
|
|
||
|
|
@@ -534,6 +535,11 @@ static std::optional<KnownType> 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,6 +773,75 @@ std::vector<StructMember> Reflector::ReadStructMembers( | |
| continue; | ||
| } | ||
|
|
||
| // Tightly packed half Point (vec2). | ||
| if (member.basetype == spirv_cross::SPIRType::BaseType::Half && // | ||
| member.width == sizeof(float) * 4 && // | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you double check this? The member width doesn't make sense for half base types. I may be misunderstanding.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, this was a hack I left in. Should be |
||
| member.columns == 1 && // | ||
| member.vecsize == 2 // | ||
| ) { | ||
| uint32_t stride = | ||
| GetArrayStride<sizeof(HalfVector2)>(struct_type, member, i); | ||
| uint32_t element_padding = stride - sizeof(HalfVector2); | ||
| result.emplace_back(StructMember{ | ||
| "HalfVector2", // type | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Argument comments are of the format
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is following the style of the rest of the file.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...also this is a struct, not a function call.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a function call, but with C++20, you can use aggregate initialization and do this without comments: |
||
| BaseTypeToString(member.basetype), // basetype | ||
| GetMemberNameAtIndex(struct_type, i), // name | ||
| struct_member_offset, // offset | ||
| sizeof(HalfVector2), // 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<sizeof(HalfVector3)>(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 && // | ||
| member.vecsize == 4 // | ||
| ) { | ||
| uint32_t stride = | ||
| GetArrayStride<sizeof(HalfVector4)>(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); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,11 +5,11 @@ | |
| #include <impeller/types.glsl> | ||
|
|
||
| uniform FragInfo { | ||
| vec4 color; | ||
| f16vec4 color; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this require
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh - but this is all in types.glsl too |
||
| } | ||
| frag_info; | ||
|
|
||
| out vec4 frag_color; | ||
| out f16vec4 frag_color; | ||
|
|
||
| void main() { | ||
| frag_color = frag_info.color; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // 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 "half.h" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (this should be based from the project root too)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops! |
||
|
|
||
| namespace impeller { | ||
|
|
||
| _Float16 ScalarToHalf(Scalar f) { | ||
| return static_cast<_Float16>(f); | ||
| } | ||
|
|
||
| } // namespace impeller | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| // 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 <cstdint> | ||
|
|
||
| #include "color.h" | ||
| #include "point.h" | ||
| #include "scalar.h" | ||
| #include "vector.h" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Includes should be rooted at the base of the project as seen above: https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
|
||
| namespace impeller { | ||
|
|
||
| /// @brief Convert a scalar to a half precision float. | ||
| /// | ||
| /// 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 { | ||
| _Float16 x = 0; | ||
|
|
||
| Half() = default; | ||
|
|
||
| Half(Scalar value) : x(ScalarToHalf(value)) {} | ||
| }; | ||
|
|
||
| /// @brief A storage only class for half precision floating point vector 4. | ||
| struct HalfVector4 { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did templating the existing Scalar type vectors not work? This is fine too but seems like we can dry this up.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did this above and backed it out. The big caveat is that 1) We need implicit constructor conversion to make the headers work 2) we generally don't want to ever use these in the backend besides that as it implies we're dropping precision before we need to. There is no performance improvement to be gained from this. In addition, if we end up needing to emulate _Float16 support for windows we'll likely end up needing to using uint16_t as a storage type and then we'd have to define all of the operators to make that work. Given all that, I'd really rather just leave them as storage only conversions. |
||
| union { | ||
| struct { | ||
| _Float16 x = 0; | ||
| _Float16 y = 0; | ||
| _Float16 z = 0; | ||
| _Float16 w = 0; | ||
| }; | ||
| _Float16 e[4]; | ||
| }; | ||
|
|
||
| constexpr HalfVector4() {} | ||
|
|
||
| constexpr HalfVector4(const Color& a) | ||
| : x(ScalarToHalf(a.red)), | ||
| y(ScalarToHalf(a.green)), | ||
| z(ScalarToHalf(a.green)), | ||
|
jonahwilliams marked this conversation as resolved.
Outdated
|
||
| 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)){}; | ||
| }; | ||
|
|
||
| /// @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; | ||
| }; | ||
| _Float16 e[3]; | ||
| }; | ||
|
|
||
| constexpr HalfVector3(){}; | ||
|
|
||
| constexpr HalfVector3(const Vector3& a) | ||
| : 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 { | ||
| _Float16 x = 0; | ||
| _Float16 y = 0; | ||
| }; | ||
| _Float16 e[2]; | ||
| }; | ||
|
|
||
| constexpr HalfVector2(){}; | ||
|
|
||
| constexpr HalfVector2(const Vector2& a) | ||
| : 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 | ||
Uh oh!
There was an error while loading. Please reload this page.