Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] support half precision uniforms and half precision samplers #40590

Merged
merged 28 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,7 @@ 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.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
Expand Down Expand Up @@ -3851,6 +3852,7 @@ 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.h
FILE: ../../../flutter/impeller/geometry/matrix.cc
FILE: ../../../flutter/impeller/geometry/matrix.h
FILE: ../../../flutter/impeller/geometry/matrix_decomposition.cc
Expand Down
75 changes: 75 additions & 0 deletions impeller/compiler/reflector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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(Half) * 8 && //
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argument comments are of the format /*arg_name=*/: https://google.github.io/styleguide/cppguide.html#Function_Argument_Comments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is following the style of the rest of the file.

Copy link
Contributor Author

@jonahwilliams jonahwilliams Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...also this is a struct, not a function call.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use /*field_name=*/ we can use the linter to verify that their name is correct. I turned this on years ago. I don't know if it still runs.

Copy link
Member

Choose a reason for hiding this comment

The 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: {.type = "HalfVector2"}.

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(Half) * 8 && //
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(Half) * 8 && //
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);
Expand Down
5 changes: 4 additions & 1 deletion impeller/compiler/shader_lib/impeller/types.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
#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
#ifndef IMPELLER_TARGET_METAL_IOS

precision mediump sampler2D;
precision mediump float;
Expand All @@ -17,6 +19,7 @@ precision mediump float;
#define f16vec3 vec3
#define f16vec4 vec4
#define f16mat4 mat4
#define f16sampler2D sampler2D

#endif // IMPELLER_TARGET_METAL

Expand Down
4 changes: 2 additions & 2 deletions impeller/entity/shaders/solid_fill.frag
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
#include <impeller/types.glsl>

uniform FragInfo {
vec4 color;
f16vec4 color;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this require #extension GL_EXT_shader_16bit_storage : require up top?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not, I'm not actually using a f16vec4 on glsl, here is the compiled shader:

#version 100
precision mediump float;
precision highp int;

struct FragInfo
{
    vec4 color;
};

uniform FragInfo frag_info;

void main()
{
    gl_FragData[0] = frag_info.color;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh - but this is all in types.glsl too

}
frag_info;

out vec4 frag_color;
out f16vec4 frag_color;

void main() {
frag_color = frag_info.color;
Expand Down
2 changes: 2 additions & 0 deletions impeller/fixtures/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ impeller_shaders("shader_fixtures") {
"simple.vert",
"test_texture.frag",
"test_texture.vert",
"half.frag",
]

if (impeller_enable_opengles) {
gles_exclusions = [
"sample.comp",
"stage1.comp",
"stage2.comp",
"half.frag",
]
}
}
Expand Down
21 changes: 21 additions & 0 deletions impeller/fixtures/half.frag
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);
}
1 change: 1 addition & 0 deletions impeller/geometry/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ impeller_component("geometry") {
"constants.h",
"gradient.cc",
"gradient.h",
"half.h",
"matrix.cc",
"matrix.h",
"matrix_decomposition.cc",
Expand Down
36 changes: 36 additions & 0 deletions impeller/geometry/geometry_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -2090,5 +2092,39 @@ TEST(GeometryTest, Gradient) {
}
}

TEST(GeometryTest, HalfConversions) {
#ifdef FML_OS_WIN
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);
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
Loading