-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] support half precision uniforms and half precision samplers #40590
Changes from 23 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,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); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,9 +7,11 @@ | |
| #include <limits> | ||
| #include <sstream> | ||
|
|
||
| #include "flutter/fml/build_config.h" | ||
| #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" | ||
|
|
@@ -2090,5 +2092,38 @@ TEST(GeometryTest, Gradient) { | |
| } | ||
| } | ||
|
|
||
| TEST(GeometryTest, HalfConversions) { | ||
| #ifdef FML_OS_WIN | ||
| GTEST_SKIP() << "The reason this doesn't work on Windows"; | ||
|
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. Perhaps "Half-precision floats (IEEE 754) are not portable and unavailable on Windows."
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. We could write or use our own library (or a header rather) for doing this portably.
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. We could, one exists in an earlier commit. however we have as of today no use for it as this is only used on metal backends.
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. Comment fixed |
||
| #else | ||
| 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), 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 | ||
| } // namespace impeller | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // 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) { | ||
|
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 this just be inline constexpr in the header?
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
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. ahh, this means I can't LOG if you try to use this on windows. Instead I'll make it always return 0 so that it is obviously wrong. |
||
| #ifdef FML_OS_WIN | ||
| FML_UNREACHABLE(); | ||
| #endif | ||
| return static_cast<InternalHalf>(f); | ||
| } | ||
|
|
||
| } // namespace impeller | ||
Uh oh!
There was an error while loading. Please reload this page.