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 diff --git a/impeller/compiler/compiler.cc b/impeller/compiler/compiler.cc index 38ea2a2b495ec..f7423ba2ec3de 100644 --- a/impeller/compiler/compiler.cc +++ b/impeller/compiler/compiler.cc @@ -364,6 +364,22 @@ Compiler::Compiler(const fml::Mapping& source_mapping, switch (source_options.target_platform) { case TargetPlatform::kMetalDesktop: case TargetPlatform::kMetalIOS: + spirv_options.SetOptimizationLevel( + shaderc_optimization_level::shaderc_optimization_level_performance); + if (source_options.use_half_textures) { + spirv_options.SetTargetEnvironment( + shaderc_target_env::shaderc_target_env_opengl, + shaderc_env_version::shaderc_env_version_opengl_4_5); + spirv_options.SetTargetSpirv( + shaderc_spirv_version::shaderc_spirv_version_1_0); + } else { + spirv_options.SetTargetEnvironment( + shaderc_target_env::shaderc_target_env_vulkan, + shaderc_env_version::shaderc_env_version_vulkan_1_1); + spirv_options.SetTargetSpirv( + shaderc_spirv_version::shaderc_spirv_version_1_3); + } + break; case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLDesktop: spirv_options.SetOptimizationLevel( diff --git a/impeller/compiler/impellerc_main.cc b/impeller/compiler/impellerc_main.cc index e50a5d76db94d..5629ca0754dd6 100644 --- a/impeller/compiler/impellerc_main.cc +++ b/impeller/compiler/impellerc_main.cc @@ -75,6 +75,7 @@ bool Main(const fml::CommandLine& command_line) { options.json_format = switches.json_format; options.gles_language_version = switches.gles_language_version; options.metal_version = switches.metal_version; + options.use_half_textures = switches.use_half_textures; Reflector::Options reflector_options; reflector_options.target_platform = switches.target_platform; diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index 09ad507111f9d..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" @@ -534,6 +535,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,6 +773,75 @@ std::vector Reflector::ReadStructMembers( continue; } + // 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(HalfVector2); + result.emplace_back(StructMember{ + "HalfVector2", // type + 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(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(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/compiler/shader_lib/impeller/blending.glsl b/impeller/compiler/shader_lib/impeller/blending.glsl index f92e6bc4ab9a0..bc49ed4e8db40 100644 --- a/impeller/compiler/shader_lib/impeller/blending.glsl +++ b/impeller/compiler/shader_lib/impeller/blending.glsl @@ -7,46 +7,48 @@ #include #include +#include //------------------------------------------------------------------------------ /// HSV utilities. /// -float IPLuminosity(vec3 color) { - return color.r * 0.3 + color.g * 0.59 + color.b * 0.11; +float16_t IPLuminosity(f16vec3 color) { + return color.r * 0.3hf + color.g * 0.59hf + color.b * 0.11hf; } /// Scales the color's luma by the amount necessary to place the color /// components in a 1-0 range. -vec3 IPClipColor(vec3 color) { - float lum = IPLuminosity(color); - float mn = min(min(color.r, color.g), color.b); - float mx = max(max(color.r, color.g), color.b); +f16vec3 IPClipColor(f16vec3 color) { + float16_t lum = IPLuminosity(color); + float16_t mn = min(min(color.r, color.g), color.b); + float16_t mx = max(max(color.r, color.g), color.b); // `lum - mn` and `mx - lum` will always be >= 0 in the following conditions, // so adding a tiny value is enough to make these divisions safe. - if (mn < 0) { - color = lum + (((color - lum) * lum) / (lum - mn + kEhCloseEnough)); + if (mn < 0.0hf) { + color = lum + (((color - lum) * lum) / (lum - mn + kEhCloseEnoughHf)); } - if (mx > 1) { - color = lum + (((color - lum) * (1 - lum)) / (mx - lum + kEhCloseEnough)); + if (mx > 1.0hf) { + color = + lum + (((color - lum) * (1.0hf - lum)) / (mx - lum + kEhCloseEnoughHf)); } return color; } -vec3 IPSetLuminosity(vec3 color, float luminosity) { - float relative_lum = luminosity - IPLuminosity(color); +f16vec3 IPSetLuminosity(f16vec3 color, float16_t luminosity) { + float16_t relative_lum = luminosity - IPLuminosity(color); return IPClipColor(color + relative_lum); } -float IPSaturation(vec3 color) { +float16_t IPSaturation(f16vec3 color) { return max(max(color.r, color.g), color.b) - min(min(color.r, color.g), color.b); } -vec3 IPSetSaturation(vec3 color, float saturation) { - float mn = min(min(color.r, color.g), color.b); - float mx = max(max(color.r, color.g), color.b); - return (mn < mx) ? ((color - mn) * saturation) / (mx - mn) : vec3(0); +f16vec3 IPSetSaturation(f16vec3 color, float16_t saturation) { + float16_t mn = min(min(color.r, color.g), color.b); + float16_t mx = max(max(color.r, color.g), color.b); + return (mn < mx) ? ((color - mn) * saturation) / (mx - mn) : f16vec3(0.0hf); } //------------------------------------------------------------------------------ @@ -58,134 +60,136 @@ vec3 IPSetSaturation(vec3 color, float saturation) { /// applied to the destination using `SourceOver` alpha compositing. /// -vec3 IPBlendScreen(vec3 dst, vec3 src) { +f16vec3 IPBlendScreen(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingscreen return dst + src - (dst * src); } -vec3 IPBlendHardLight(vec3 dst, vec3 src) { +f16vec3 IPBlendHardLight(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendinghardlight - return IPVec3Choose(dst * (2 * src), IPBlendScreen(dst, 2 * src - 1), src); + return IPVec3ChooseHf(dst * (2.0hf * src), + IPBlendScreen(dst, 2.0hf * src - 1.0hf), src); } -vec3 IPBlendOverlay(vec3 dst, vec3 src) { +f16vec3 IPBlendOverlay(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingoverlay // HardLight, but with reversed parameters. return IPBlendHardLight(src, dst); } -vec3 IPBlendDarken(vec3 dst, vec3 src) { +f16vec3 IPBlendDarken(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingdarken return min(dst, src); } -vec3 IPBlendLighten(vec3 dst, vec3 src) { +f16vec3 IPBlendLighten(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendinglighten return max(dst, src); } -vec3 IPBlendColorDodge(vec3 dst, vec3 src) { +f16vec3 IPBlendColorDodge(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingcolordodge - vec3 color = min(vec3(1), dst / (1 - src)); + f16vec3 color = min(f16vec3(1.0hf), dst / (1.0hf - src)); - if (dst.r < kEhCloseEnough) { - color.r = 0; + if (dst.r < kEhCloseEnoughHf) { + color.r = 0.0hf; } - if (dst.g < kEhCloseEnough) { - color.g = 0; + if (dst.g < kEhCloseEnoughHf) { + color.g = 0.0hf; } - if (dst.b < kEhCloseEnough) { - color.b = 0; + if (dst.b < kEhCloseEnoughHf) { + color.b = 0.0hf; } - if (1 - src.r < kEhCloseEnough) { - color.r = 1; + if (1.0hf - src.r < kEhCloseEnoughHf) { + color.r = 1.0hf; } - if (1 - src.g < kEhCloseEnough) { - color.g = 1; + if (1.0hf - src.g < kEhCloseEnoughHf) { + color.g = 1.0hf; } - if (1 - src.b < kEhCloseEnough) { - color.b = 1; + if (1.0hf - src.b < kEhCloseEnoughHf) { + color.b = 1.0hf; } return color; } -vec3 IPBlendColorBurn(vec3 dst, vec3 src) { +f16vec3 IPBlendColorBurn(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingcolorburn - vec3 color = 1 - min(vec3(1), (1 - dst) / src); + f16vec3 color = 1.0hf - min(f16vec3(1.0hf), (1.0hf - dst) / src); - if (1 - dst.r < kEhCloseEnough) { - color.r = 1; + if (1.0hf - dst.r < kEhCloseEnoughHf) { + color.r = 1.0hf; } - if (1 - dst.g < kEhCloseEnough) { - color.g = 1; + if (1.0hf - dst.g < kEhCloseEnoughHf) { + color.g = 1.0hf; } - if (1 - dst.b < kEhCloseEnough) { - color.b = 1; + if (1.0hf - dst.b < kEhCloseEnoughHf) { + color.b = 1.0hf; } - if (src.r < kEhCloseEnough) { - color.r = 0; + if (src.r < kEhCloseEnoughHf) { + color.r = 0.0hf; } - if (src.g < kEhCloseEnough) { - color.g = 0; + if (src.g < kEhCloseEnoughHf) { + color.g = 0.0hf; } - if (src.b < kEhCloseEnough) { - color.b = 0; + if (src.b < kEhCloseEnoughHf) { + color.b = 0.0hf; } return color; } -vec3 IPBlendSoftLight(vec3 dst, vec3 src) { +f16vec3 IPBlendSoftLight(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingsoftlight - vec3 D = IPVec3ChooseCutoff(((16 * dst - 12) * dst + 4) * dst, // - sqrt(dst), // - dst, // - 0.25); + f16vec3 D = + IPVec3ChooseCutoffHf(((16.0hf * dst - 12.0hf) * dst + 4.0hf) * dst, // + sqrt(dst), // + dst, // + 0.25hf); - return IPVec3Choose(dst - (1 - 2 * src) * dst * (1 - dst), // - dst + (2 * src - 1) * (D - dst), // - src); + return IPVec3ChooseHf(dst - (1.0hf - 2.0hf * src) * dst * (1.0hf - dst), // + dst + (2.0hf * src - 1.0hf) * (D - dst), // + src); } -vec3 IPBlendDifference(vec3 dst, vec3 src) { +f16vec3 IPBlendDifference(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingdifference return abs(dst - src); } -vec3 IPBlendExclusion(vec3 dst, vec3 src) { +f16vec3 IPBlendExclusion(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingexclusion - return dst + src - 2 * dst * src; + return dst + src - 2.0hf * dst * src; } -vec3 IPBlendMultiply(vec3 dst, vec3 src) { +f16vec3 IPBlendMultiply(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingmultiply return dst * src; } -vec3 IPBlendHue(vec3 dst, vec3 src) { +f16vec3 IPBlendHue(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendinghue return IPSetLuminosity(IPSetSaturation(src, IPSaturation(dst)), IPLuminosity(dst)); } -vec3 IPBlendSaturation(vec3 dst, vec3 src) { +f16vec3 IPBlendSaturation(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingsaturation return IPSetLuminosity(IPSetSaturation(dst, IPSaturation(src)), IPLuminosity(dst)); } -vec3 IPBlendColor(vec3 dst, vec3 src) { +f16vec3 IPBlendColor(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingcolor return IPSetLuminosity(src, IPLuminosity(dst)); } -vec3 IPBlendLuminosity(vec3 dst, vec3 src) { +f16vec3 IPBlendLuminosity(f16vec3 dst, f16vec3 src) { // https://www.w3.org/TR/compositing-1/#blendingluminosity return IPSetLuminosity(dst, IPLuminosity(src)); } diff --git a/impeller/compiler/shader_lib/impeller/branching.glsl b/impeller/compiler/shader_lib/impeller/branching.glsl index bfa00b62dc5f1..36cb9bf4a42e0 100644 --- a/impeller/compiler/shader_lib/impeller/branching.glsl +++ b/impeller/compiler/shader_lib/impeller/branching.glsl @@ -46,7 +46,27 @@ vec3 IPVec3ChooseCutoff(vec3 a, vec3 b, vec3 value, float cutoff) { /// For each vec3 component, if value > 0.5, return b, otherwise return a. vec3 IPVec3Choose(vec3 a, vec3 b, vec3 value) { - return IPVec3ChooseCutoff(a, b, value, 0.5); + return IPVec3ChooseCutoff(a, b, value, 0.5hf); +} + +/// Perform a branchless greater than check for each vec3 component. +/// +/// Returns 1.0 if x > y, otherwise 0.0. +f16vec3 IPVec3IsGreaterThanHf(f16vec3 x, f16vec3 y) { + return max(sign(x - y), 0.0hf); +} + +/// For each vec3 component, if value > cutoff, return b, otherwise return a. +f16vec3 IPVec3ChooseCutoffHf(f16vec3 a, + f16vec3 b, + f16vec3 value, + float16_t cutoff) { + return f16vec3(mix(a, b, IPVec3IsGreaterThanHf(value, f16vec3(cutoff)))); +} + +/// For each vec3 component, if value > 0.5, return b, otherwise return a. +f16vec3 IPVec3ChooseHf(f16vec3 a, f16vec3 b, f16vec3 value) { + return IPVec3ChooseCutoffHf(a, b, value, 0.5hf); } #endif diff --git a/impeller/compiler/shader_lib/impeller/color.glsl b/impeller/compiler/shader_lib/impeller/color.glsl index 303b68e4c4570..7a441862cb4b3 100644 --- a/impeller/compiler/shader_lib/impeller/color.glsl +++ b/impeller/compiler/shader_lib/impeller/color.glsl @@ -6,6 +6,7 @@ #define COLOR_GLSL_ #include +#include /// Convert a premultiplied color (a color which has its color components /// multiplied with its alpha value) to an unpremultiplied color. @@ -18,6 +19,13 @@ vec4 IPUnpremultiply(vec4 color) { return vec4(color.rgb / color.a, color.a); } +f16vec4 IPUnpremultiply(f16vec4 color) { + if (color.a == 0.0hf) { + return f16vec4(0.0hf); + } + return f16vec4(color.rgb / color.a, color.a); +} + /// Convert an unpremultiplied color (a color which has its color components /// separated from its alpha value) to a premultiplied color. /// @@ -26,4 +34,8 @@ vec4 IPPremultiply(vec4 color) { return vec4(color.rgb * color.a, color.a); } +f16vec4 IPPremultiply(f16vec4 color) { + return f16vec4(color.rgb * color.a, color.a); +} + #endif diff --git a/impeller/compiler/shader_lib/impeller/constants.glsl b/impeller/compiler/shader_lib/impeller/constants.glsl index 423f4dbd735cd..29b2ae1f982c6 100644 --- a/impeller/compiler/shader_lib/impeller/constants.glsl +++ b/impeller/compiler/shader_lib/impeller/constants.glsl @@ -5,18 +5,28 @@ #ifndef CONSTANTS_GLSL_ #define CONSTANTS_GLSL_ +#include + const float kEhCloseEnough = 0.000001; +const float16_t kEhCloseEnoughHf = 0.001hf; + // 1 / (2 * pi) const float k1Over2Pi = 0.1591549430918; // sqrt(2 * pi) const float kSqrtTwoPi = 2.50662827463; +const float16_t kSqrtTwoPiHf = 2.50662827463hf; + // sqrt(2) / 2 == 1 / sqrt(2) const float kHalfSqrtTwo = 0.70710678118; +const float16_t kHalfSqrtTwoHf = 0.70710678118hf; + // sqrt(3) const float kSqrtThree = 1.73205080757; +const float16_t kSqrtThreeHf = 1.73205080757hf; + #endif diff --git a/impeller/compiler/shader_lib/impeller/gaussian.glsl b/impeller/compiler/shader_lib/impeller/gaussian.glsl index 62874bec96d9c..b74b89f539860 100644 --- a/impeller/compiler/shader_lib/impeller/gaussian.glsl +++ b/impeller/compiler/shader_lib/impeller/gaussian.glsl @@ -6,51 +6,53 @@ #define GAUSSIAN_GLSL_ #include +#include /// Gaussian distribution function. -float IPGaussian(float x, float sigma) { - float variance = sigma * sigma; - return exp(-0.5 * x * x / variance) / (kSqrtTwoPi * sigma); +float16_t IPGaussian(float16_t x, float16_t sigma) { + float16_t variance = sigma * sigma; + return exp(-0.5hf * x * x / variance) / (kSqrtTwoPiHf * sigma); } /// Abramowitz and Stegun erf approximation. -float IPErf(float x) { - float a = abs(x); +float16_t IPErf(float16_t x) { + float16_t a = abs(x); // 0.278393*x + 0.230389*x^2 + 0.078108*x^4 + 1 - float b = (0.278393 + (0.230389 + 0.078108 * a * a) * a) * a + 1.0; - return sign(x) * (1 - 1 / (b * b * b * b)); + float16_t b = + (0.278393hf + (0.230389hf + 0.078108hf * a * a) * a) * a + 1.0hf; + return sign(x) * (1.0hf - 1.0hf / (b * b * b * b)); } /// Vec2 variation for the Abramowitz and Stegun erf approximation. -vec2 IPVec2Erf(vec2 x) { - vec2 a = abs(x); +f16vec2 IPVec2Erf(f16vec2 x) { + f16vec2 a = abs(x); // 0.278393*x + 0.230389*x^2 + 0.078108*x^4 + 1 - vec2 b = (0.278393 + (0.230389 + 0.078108 * a * a) * a) * a + 1.0; - return sign(x) * (1 - 1 / (b * b * b * b)); + f16vec2 b = (0.278393hf + (0.230389hf + 0.078108hf * a * a) * a) * a + 1.0hf; + return sign(x) * (1.0hf - 1.0hf / (b * b * b * b)); } /// The indefinite integral of the Gaussian function. /// Uses a very close approximation of Erf. -float IPGaussianIntegral(float x, float sigma) { +float16_t IPGaussianIntegral(float16_t x, float16_t sigma) { // ( 1 + erf( x * (sqrt(2) / (2 * sigma) ) ) / 2 - return (1 + IPErf(x * (kHalfSqrtTwo / sigma))) * 0.5; + return (1.0hf + IPErf(x * (kHalfSqrtTwoHf / sigma))) * 0.5hf; } /// Vec2 variation for the indefinite integral of the Gaussian function. /// Uses a very close approximation of Erf. -vec2 IPVec2GaussianIntegral(vec2 x, float sigma) { +f16vec2 IPVec2GaussianIntegral(f16vec2 x, float16_t sigma) { // ( 1 + erf( x * (sqrt(2) / (2 * sigma) ) ) / 2 - return (1 + IPVec2Erf(x * (kHalfSqrtTwo / sigma))) * 0.5; + return (1.0hf + IPVec2Erf(x * (kHalfSqrtTwoHf / sigma))) * 0.5hf; } /// Simpler (but less accurate) approximation of the Gaussian integral. -vec2 IPVec2FastGaussianIntegral(vec2 x, float sigma) { - return 1 / (1 + exp(-kSqrtThree / sigma * x)); +f16vec2 IPVec2FastGaussianIntegral(f16vec2 x, float16_t sigma) { + return 1.0hf / (1.0hf + exp(-kSqrtThreeHf / sigma * x)); } /// Simple logistic sigmoid with a domain of [-1, 1] and range of [0, 1]. -float IPSigmoid(float x) { - return 1.03731472073 / (1 + exp(-4 * x)) - 0.0186573603638; +float16_t IPSigmoid(float16_t x) { + return 1.03731472073hf / (1.0hf + exp(-4.0hf * x)) - 0.0186573603638hf; } #endif diff --git a/impeller/compiler/shader_lib/impeller/texture.glsl b/impeller/compiler/shader_lib/impeller/texture.glsl index 7979e897ea922..e808f8a8308e9 100644 --- a/impeller/compiler/shader_lib/impeller/texture.glsl +++ b/impeller/compiler/shader_lib/impeller/texture.glsl @@ -6,6 +6,7 @@ #define TEXTURE_GLSL_ #include +#include /// Sample from a texture. /// @@ -92,6 +93,20 @@ vec4 IPSampleWithTileMode(sampler2D tex, return texture(tex, coords); } +f16vec4 IPSampleWithTileMode(f16sampler2D tex, + f16vec2 coords, + float16_t x_tile_mode, + float16_t y_tile_mode) { + if (x_tile_mode == kTileModeDecal && + (coords.x < 0.0hf || coords.x >= 1.0hf) || + y_tile_mode == kTileModeDecal && + (coords.y < 0.0hf || coords.y >= 1.0hf)) { + return f16vec4(0.0hf); + } + + return texture(tex, coords); +} + /// Sample a texture, emulating a specific tile mode. /// /// This is useful for Impeller graphics backend that don't have native support @@ -122,6 +137,14 @@ vec4 IPSampleDecal(sampler2D texture_sampler, vec2 coords) { return texture(texture_sampler, coords); } +f16vec4 IPSampleDecal(f16sampler2D texture_sampler, f16vec2 coords) { + if (any(lessThan(coords, f16vec2(0.0hf))) || + any(greaterThanEqual(coords, f16vec2(1.0hf)))) { + return f16vec4(0.0hf); + } + return texture(texture_sampler, coords); +} + /// Sample a texture, emulating a specific tile mode. /// /// This is useful for Impeller graphics backend that don't have native support diff --git a/impeller/compiler/shader_lib/impeller/types.glsl b/impeller/compiler/shader_lib/impeller/types.glsl index 87c7eee666c69..a2d9dbf668c41 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/compiler/source_options.h b/impeller/compiler/source_options.h index c10e97f1f178b..797cb70a026f1 100644 --- a/impeller/compiler/source_options.h +++ b/impeller/compiler/source_options.h @@ -29,6 +29,10 @@ struct SourceOptions { bool json_format = false; std::string metal_version; + /// @brief Whether half-precision textures should be supported, requiring + /// opengl semantics. Only used on metal targets. + bool use_half_textures = false; + SourceOptions(); ~SourceOptions(); diff --git a/impeller/compiler/switches.cc b/impeller/compiler/switches.cc index 27fe2a6bf368f..6ad6d0de9dbe5 100644 --- a/impeller/compiler/switches.cc +++ b/impeller/compiler/switches.cc @@ -71,8 +71,8 @@ void Switches::PrintHelp(std::ostream& stream) { stream << "[optional] --depfile=" << std::endl; stream << "[optional] --gles-language-verision=" << std::endl; stream << "[optional] --json" << std::endl; - stream << "[optional] --remap-samplers (force metal sampler index to match " - "declared order)" + stream << "[optional] --use-half-textures (force openGL semantics when " + "targeting metal)" << std::endl; } @@ -134,7 +134,8 @@ Switches::Switches(const fml::CommandLine& command_line) metal_version( command_line.GetOptionValueWithDefault("metal-version", "1.2")), entry_point( - command_line.GetOptionValueWithDefault("entry-point", "main")) { + command_line.GetOptionValueWithDefault("entry-point", "main")), + use_half_textures(command_line.HasOption("use-half-textures")) { auto language = command_line.GetOptionValueWithDefault("source-language", "glsl"); std::transform(language.begin(), language.end(), language.begin(), diff --git a/impeller/compiler/switches.h b/impeller/compiler/switches.h index f9703f2e766b8..6c5ce9f9b2bf0 100644 --- a/impeller/compiler/switches.h +++ b/impeller/compiler/switches.h @@ -36,6 +36,7 @@ struct Switches { uint32_t gles_language_version; std::string metal_version; std::string entry_point; + bool use_half_textures; Switches(); diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 9689ac979e85d..844adbe867577 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -11,6 +11,8 @@ impeller_shaders("entity_shaders") { vulkan_language_version = 130 } + use_half_textures = true + shaders = [ "shaders/blending/advanced_blend.vert", "shaders/blending/advanced_blend_color.frag", diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index 461a7197f79a1..b8547671d9165 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -125,8 +125,8 @@ static std::optional AdvancedBlend( blend_info.dst_input_alpha = absorb_opacity ? dst_snapshot->opacity : 1.0; if (foreground_color.has_value()) { - blend_info.color_factor = 1; - blend_info.color = foreground_color.value(); + blend_info.color_factor = 1.0f; + blend_info.color = Vector4(foreground_color.value()); // This texture will not be sampled from due to the color factor. But // this is present so that validation doesn't trip on a missing // binding. @@ -134,7 +134,7 @@ static std::optional AdvancedBlend( } else { auto src_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler( src_snapshot->sampler_descriptor); - blend_info.color_factor = 0; + blend_info.color_factor = 0.0f; FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, src_sampler); frame_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale(); } @@ -220,9 +220,9 @@ static std::optional PipelineBlend( frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * Matrix::MakeTranslation(-coverage.origin) * input->transform; - FS::FragInfo frag_info; - frag_info.texture_sampler_y_coord_scale = + frame_info.texture_sampler_y_coord_scale = input->texture->GetYCoordScale(); + FS::FragInfo frag_info; frag_info.input_alpha = absorb_opacity ? input->opacity : 1.0; FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); diff --git a/impeller/entity/contents/solid_color_contents.cc b/impeller/entity/contents/solid_color_contents.cc index 09e921058d800..834991b1fac54 100644 --- a/impeller/entity/contents/solid_color_contents.cc +++ b/impeller/entity/contents/solid_color_contents.cc @@ -86,7 +86,7 @@ bool SolidColorContents::Render(const ContentContext& renderer, VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); FS::FragInfo frag_info; - frag_info.color = color_.Premultiply(); + frag_info.color = Vector4(color_.Premultiply()); FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); if (!pass.AddCommand(std::move(cmd))) { diff --git a/impeller/entity/shaders/blending/advanced_blend.glsl b/impeller/entity/shaders/blending/advanced_blend.glsl index 6c1ce2ef4acdc..f5f14ec577a04 100644 --- a/impeller/entity/shaders/blending/advanced_blend.glsl +++ b/impeller/entity/shaders/blending/advanced_blend.glsl @@ -8,35 +8,36 @@ #include uniform BlendInfo { - float dst_input_alpha; - float color_factor; - vec4 color; // This color input is expected to be unpremultiplied. + float16_t dst_input_alpha; + float16_t color_factor; + f16vec4 color; // This color input is expected to be unpremultiplied. } blend_info; -uniform sampler2D texture_sampler_dst; -uniform sampler2D texture_sampler_src; +uniform f16sampler2D texture_sampler_dst; +uniform f16sampler2D texture_sampler_src; -in vec2 v_dst_texture_coords; -in vec2 v_src_texture_coords; +in f16vec2 v_dst_texture_coords; +in f16vec2 v_src_texture_coords; -out vec4 frag_color; +out f16vec4 frag_color; void main() { - vec4 dst_sample = IPSampleDecal(texture_sampler_dst, // sampler - v_dst_texture_coords // texture coordinates - ) * - blend_info.dst_input_alpha; - - vec4 dst = IPUnpremultiply(dst_sample); - vec4 src = blend_info.color_factor > 0 - ? blend_info.color - : IPUnpremultiply(IPSampleDecal( - texture_sampler_src, // sampler - v_src_texture_coords // texture coordinates - )); - - vec4 blended = vec4(Blend(dst.rgb, src.rgb), 1) * dst.a; + f16vec4 dst_sample = + IPSampleDecal(texture_sampler_dst, // sampler + v_dst_texture_coords // texture coordinates + ) * + blend_info.dst_input_alpha; + + f16vec4 dst = IPUnpremultiply(dst_sample); + f16vec4 src = blend_info.color_factor > 0.0hf + ? blend_info.color + : IPUnpremultiply(IPSampleDecal( + texture_sampler_src, // sampler + v_src_texture_coords // texture coordinates + )); + + f16vec4 blended = f16vec4(Blend(dst.rgb, src.rgb), 1.0hf) * dst.a; frag_color = mix(dst_sample, blended, src.a); } diff --git a/impeller/entity/shaders/blending/advanced_blend.vert b/impeller/entity/shaders/blending/advanced_blend.vert index ff2cd86433fab..b0b187c469e6a 100644 --- a/impeller/entity/shaders/blending/advanced_blend.vert +++ b/impeller/entity/shaders/blending/advanced_blend.vert @@ -16,13 +16,13 @@ in vec2 vertices; in vec2 dst_texture_coords; in vec2 src_texture_coords; -out vec2 v_dst_texture_coords; -out vec2 v_src_texture_coords; +out f16vec2 v_dst_texture_coords; +out f16vec2 v_src_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(vertices, 0.0, 1.0); v_dst_texture_coords = - IPRemapCoords(dst_texture_coords, frame_info.dst_y_coord_scale); + f16vec2(IPRemapCoords(dst_texture_coords, frame_info.dst_y_coord_scale)); v_src_texture_coords = - IPRemapCoords(src_texture_coords, frame_info.src_y_coord_scale); + f16vec2(IPRemapCoords(src_texture_coords, frame_info.src_y_coord_scale)); } diff --git a/impeller/entity/shaders/blending/advanced_blend_color.frag b/impeller/entity/shaders/blending/advanced_blend_color.frag index 225bd3f098122..439a3598c9282 100644 --- a/impeller/entity/shaders/blending/advanced_blend_color.frag +++ b/impeller/entity/shaders/blending/advanced_blend_color.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendColor(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_colorburn.frag b/impeller/entity/shaders/blending/advanced_blend_colorburn.frag index 95aac01645999..80b747f6c3439 100644 --- a/impeller/entity/shaders/blending/advanced_blend_colorburn.frag +++ b/impeller/entity/shaders/blending/advanced_blend_colorburn.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendColorBurn(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_colordodge.frag b/impeller/entity/shaders/blending/advanced_blend_colordodge.frag index f11fc5e68584d..c6356530bbe96 100644 --- a/impeller/entity/shaders/blending/advanced_blend_colordodge.frag +++ b/impeller/entity/shaders/blending/advanced_blend_colordodge.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendColorDodge(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_darken.frag b/impeller/entity/shaders/blending/advanced_blend_darken.frag index 286b7ff2912e6..95c8802433bed 100644 --- a/impeller/entity/shaders/blending/advanced_blend_darken.frag +++ b/impeller/entity/shaders/blending/advanced_blend_darken.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendDarken(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_difference.frag b/impeller/entity/shaders/blending/advanced_blend_difference.frag index 9d9320fdffd78..d9569046d0571 100644 --- a/impeller/entity/shaders/blending/advanced_blend_difference.frag +++ b/impeller/entity/shaders/blending/advanced_blend_difference.frag @@ -4,7 +4,7 @@ #include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendDifference(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_exclusion.frag b/impeller/entity/shaders/blending/advanced_blend_exclusion.frag index 7c2f9f92996ca..2f613ec10939e 100644 --- a/impeller/entity/shaders/blending/advanced_blend_exclusion.frag +++ b/impeller/entity/shaders/blending/advanced_blend_exclusion.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendExclusion(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_hardlight.frag b/impeller/entity/shaders/blending/advanced_blend_hardlight.frag index aa126dfdc7cc7..7a5d77cd380e2 100644 --- a/impeller/entity/shaders/blending/advanced_blend_hardlight.frag +++ b/impeller/entity/shaders/blending/advanced_blend_hardlight.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendHardLight(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_hue.frag b/impeller/entity/shaders/blending/advanced_blend_hue.frag index c0355b4b00d34..2fee599fd42f9 100644 --- a/impeller/entity/shaders/blending/advanced_blend_hue.frag +++ b/impeller/entity/shaders/blending/advanced_blend_hue.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendHue(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_lighten.frag b/impeller/entity/shaders/blending/advanced_blend_lighten.frag index 32f2df082b4f5..c10ea8f0d40d2 100644 --- a/impeller/entity/shaders/blending/advanced_blend_lighten.frag +++ b/impeller/entity/shaders/blending/advanced_blend_lighten.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendLighten(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_luminosity.frag b/impeller/entity/shaders/blending/advanced_blend_luminosity.frag index 4ceae64493947..082a69ce70b08 100644 --- a/impeller/entity/shaders/blending/advanced_blend_luminosity.frag +++ b/impeller/entity/shaders/blending/advanced_blend_luminosity.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendLuminosity(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_multiply.frag b/impeller/entity/shaders/blending/advanced_blend_multiply.frag index a2fd42b6c7d2e..4034a42a3f24c 100644 --- a/impeller/entity/shaders/blending/advanced_blend_multiply.frag +++ b/impeller/entity/shaders/blending/advanced_blend_multiply.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendMultiply(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_overlay.frag b/impeller/entity/shaders/blending/advanced_blend_overlay.frag index 0837b91d8bfbd..520e356433999 100644 --- a/impeller/entity/shaders/blending/advanced_blend_overlay.frag +++ b/impeller/entity/shaders/blending/advanced_blend_overlay.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendOverlay(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_saturation.frag b/impeller/entity/shaders/blending/advanced_blend_saturation.frag index c3fd3bebc87d7..abd9cba668d77 100644 --- a/impeller/entity/shaders/blending/advanced_blend_saturation.frag +++ b/impeller/entity/shaders/blending/advanced_blend_saturation.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendSaturation(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_screen.frag b/impeller/entity/shaders/blending/advanced_blend_screen.frag index f65ab5db1d563..5d429d86768c8 100644 --- a/impeller/entity/shaders/blending/advanced_blend_screen.frag +++ b/impeller/entity/shaders/blending/advanced_blend_screen.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendScreen(dst, src); } diff --git a/impeller/entity/shaders/blending/advanced_blend_softlight.frag b/impeller/entity/shaders/blending/advanced_blend_softlight.frag index 3a504afbb99c6..2fa7182060f43 100644 --- a/impeller/entity/shaders/blending/advanced_blend_softlight.frag +++ b/impeller/entity/shaders/blending/advanced_blend_softlight.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendSoftLight(dst, src); } diff --git a/impeller/entity/shaders/blending/blend.frag b/impeller/entity/shaders/blending/blend.frag index af401a151d98d..195e1dcd4ca30 100644 --- a/impeller/entity/shaders/blending/blend.frag +++ b/impeller/entity/shaders/blending/blend.frag @@ -5,20 +5,18 @@ #include #include -uniform sampler2D texture_sampler_src; +uniform f16sampler2D texture_sampler_src; uniform FragInfo { - float texture_sampler_y_coord_scale; - float input_alpha; + float16_t input_alpha; } frag_info; -in vec2 v_texture_coords; +in f16vec2 v_texture_coords; -out vec4 frag_color; +out f16vec4 frag_color; void main() { - frag_color = IPSample(texture_sampler_src, v_texture_coords, - frag_info.texture_sampler_y_coord_scale) * - frag_info.input_alpha; + frag_color = + texture(texture_sampler_src, v_texture_coords) * frag_info.input_alpha; } diff --git a/impeller/entity/shaders/blending/blend.vert b/impeller/entity/shaders/blending/blend.vert index 3b4a4bd430445..d9572df2dd65b 100644 --- a/impeller/entity/shaders/blending/blend.vert +++ b/impeller/entity/shaders/blending/blend.vert @@ -2,19 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include uniform FrameInfo { mat4 mvp; + float texture_sampler_y_coord_scale; } frame_info; in vec2 vertices; in vec2 texture_coords; -out vec2 v_texture_coords; +out f16vec2 v_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(vertices, 0.0, 1.0); - v_texture_coords = texture_coords; + v_texture_coords = f16vec2( + IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale)); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl b/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl index 06324909a6af5..e65d10a0a10a4 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl @@ -31,14 +31,14 @@ in vec2 v_src_texture_coords; out vec4 frag_color; void main() { - vec4 dst_sample = ReadDestination(); - vec4 dst = IPUnpremultiply(dst_sample); + f16vec4 dst_sample = f16vec4(ReadDestination()); + f16vec4 dst = IPUnpremultiply(dst_sample); vec4 src = IPUnpremultiply(IPSampleDecal(texture_sampler_src, // sampler v_src_texture_coords // texture coordinates )); - vec4 blended = vec4(Blend(dst.rgb, src.rgb), 1) * dst.a; + f16vec4 blended = f16vec4(Blend(dst.rgb, f16vec3(src.rgb)), 1.0hf) * dst.a; - frag_color = mix(dst_sample, blended, src.a); + frag_color = vec4(mix(dst_sample, blended, float16_t(src.a))); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_color.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_color.frag index fee29215b1fef..062bff86ac722 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_color.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_color.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendColor(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_colorburn.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_colorburn.frag index bfbfb9dd40c91..25b44f7a13d39 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_colorburn.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_colorburn.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendColorBurn(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_colordodge.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_colordodge.frag index e89b27dc7f603..d4985dd389317 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_colordodge.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_colordodge.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendColorDodge(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_darken.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_darken.frag index 9e865c289eb14..77006e1e9485b 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_darken.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_darken.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendDarken(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_difference.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_difference.frag index e66cab545ba98..6dbc7bd12da4d 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_difference.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_difference.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendDifference(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_exclusion.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_exclusion.frag index 5c6b1ada4af77..96164a0d3ecd3 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_exclusion.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_exclusion.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendExclusion(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_hardlight.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_hardlight.frag index f3e1215a82bf0..88d88db11b0f3 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_hardlight.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_hardlight.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendHardLight(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_hue.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_hue.frag index b9e1cefb0502c..e30ded1bc3ddb 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_hue.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_hue.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendHue(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_lighten.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_lighten.frag index dd480737af68b..55fb6f0d0674c 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_lighten.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_lighten.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendLighten(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_luminosity.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_luminosity.frag index 66ba223e62b1d..75478e6641c22 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_luminosity.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_luminosity.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendLuminosity(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_multiply.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_multiply.frag index 3d8ec54b8e1f8..fa3e5330a3ae0 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_multiply.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_multiply.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendMultiply(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_overlay.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_overlay.frag index f412766d4f78a..61ecb34b2bbe1 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_overlay.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_overlay.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendOverlay(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_saturation.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_saturation.frag index 4e6b1e7947c84..f8bd56858eb3d 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_saturation.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_saturation.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendSaturation(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag index c1412a46c097e..ba96978e30f83 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendScreen(dst, src); } diff --git a/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag b/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag index a13caaa1a6461..1aec3e1715ae2 100644 --- a/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag +++ b/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec3 Blend(vec3 dst, vec3 src) { +f16vec3 Blend(f16vec3 dst, f16vec3 src) { return IPBlendSoftLight(dst, src); } diff --git a/impeller/entity/shaders/border_mask_blur.frag b/impeller/entity/shaders/border_mask_blur.frag index b28dfc8210380..e0e89b2e8edc5 100644 --- a/impeller/entity/shaders/border_mask_blur.frag +++ b/impeller/entity/shaders/border_mask_blur.frag @@ -15,42 +15,42 @@ // integral (using an erf approximation) to the 4 edges of the UV rectangle and // multiplying them. -uniform sampler2D texture_sampler; +uniform f16sampler2D texture_sampler; uniform FragInfo { - float src_factor; - float inner_blur_factor; - float outer_blur_factor; + float16_t src_factor; + float16_t inner_blur_factor; + float16_t outer_blur_factor; - vec2 sigma_uv; + f16vec2 sigma_uv; } frag_info; -in vec2 v_texture_coords; +in f16vec2 v_texture_coords; -out vec4 frag_color; +out f16vec4 frag_color; -float BoxBlurMask(vec2 uv) { +float16_t BoxBlurMask(f16vec2 uv) { // LTRB - return IPGaussianIntegral(uv.x, frag_info.sigma_uv.x) * // - IPGaussianIntegral(uv.y, frag_info.sigma_uv.y) * // - IPGaussianIntegral(1 - uv.x, frag_info.sigma_uv.x) * // - IPGaussianIntegral(1 - uv.y, frag_info.sigma_uv.y); + return IPGaussianIntegral(uv.x, frag_info.sigma_uv.x) * // + IPGaussianIntegral(uv.y, frag_info.sigma_uv.y) * // + IPGaussianIntegral(1.0hf - uv.x, frag_info.sigma_uv.x) * // + IPGaussianIntegral(1.0hf - uv.y, frag_info.sigma_uv.y); } void main() { - vec4 image_color = texture(texture_sampler, v_texture_coords); - float blur_factor = BoxBlurMask(v_texture_coords); + f16vec4 image_color = texture(texture_sampler, v_texture_coords); + float16_t blur_factor = BoxBlurMask(v_texture_coords); - float within_bounds = - float(v_texture_coords.x >= 0 && v_texture_coords.y >= 0 && - v_texture_coords.x < 1 && v_texture_coords.y < 1); - float inner_factor = + float16_t within_bounds = + float16_t(v_texture_coords.x >= 0.0hf && v_texture_coords.y >= 0.0hf && + v_texture_coords.x < 1.0hf && v_texture_coords.y < 1.0hf); + float16_t inner_factor = (frag_info.inner_blur_factor * blur_factor + frag_info.src_factor) * within_bounds; - float outer_factor = - frag_info.outer_blur_factor * blur_factor * (1 - within_bounds); + float16_t outer_factor = + frag_info.outer_blur_factor * blur_factor * (1.0hf - within_bounds); - float mask_factor = inner_factor + outer_factor; + float16_t mask_factor = inner_factor + outer_factor; frag_color = image_color * mask_factor; } diff --git a/impeller/entity/shaders/border_mask_blur.vert b/impeller/entity/shaders/border_mask_blur.vert index bff59a4747e65..74b9ae422483a 100644 --- a/impeller/entity/shaders/border_mask_blur.vert +++ b/impeller/entity/shaders/border_mask_blur.vert @@ -15,10 +15,10 @@ frame_info; in vec2 vertices; in vec2 texture_coords; -out vec2 v_texture_coords; +out f16vec2 v_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(vertices, 0.0, 1.0); - v_texture_coords = - IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale); + v_texture_coords = f16vec2( + IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale)); } diff --git a/impeller/entity/shaders/gaussian_blur.frag b/impeller/entity/shaders/gaussian_blur.frag index 8b483ae45de30..e3320059b7603 100644 --- a/impeller/entity/shaders/gaussian_blur.frag +++ b/impeller/entity/shaders/gaussian_blur.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec4 Sample(sampler2D tex, vec2 coords) { +f16vec4 Sample(f16sampler2D tex, f16vec2 coords) { return texture(tex, coords); } diff --git a/impeller/entity/shaders/gaussian_blur.glsl b/impeller/entity/shaders/gaussian_blur.glsl index 718b4826021c0..95102751b0304 100644 --- a/impeller/entity/shaders/gaussian_blur.glsl +++ b/impeller/entity/shaders/gaussian_blur.glsl @@ -18,38 +18,38 @@ #include #include -uniform sampler2D texture_sampler; -uniform sampler2D alpha_mask_sampler; +uniform f16sampler2D texture_sampler; +uniform f16sampler2D alpha_mask_sampler; uniform FragInfo { - vec2 texture_size; - vec2 blur_direction; + f16vec2 texture_size; + f16vec2 blur_direction; // The blur sigma and radius have a linear relationship which is defined // host-side, but both are useful controls here. Sigma (pixels per standard // deviation) is used to define the gaussian function itself, whereas the // radius is used to limit how much of the function is integrated. - float blur_sigma; - float blur_radius; + float16_t blur_sigma; + float16_t blur_radius; - float src_factor; - float inner_blur_factor; - float outer_blur_factor; + float16_t src_factor; + float16_t inner_blur_factor; + float16_t outer_blur_factor; } frag_info; -in vec2 v_texture_coords; -in vec2 v_src_texture_coords; +in f16vec2 v_texture_coords; +in f16vec2 v_src_texture_coords; -out vec4 frag_color; +out f16vec4 frag_color; void main() { - vec4 total_color = vec4(0); - float gaussian_integral = 0; - vec2 blur_uv_offset = frag_info.blur_direction / frag_info.texture_size; + f16vec4 total_color = f16vec4(0.0hf); + float16_t gaussian_integral = 0.0hf; + f16vec2 blur_uv_offset = frag_info.blur_direction / frag_info.texture_size; - for (float i = -frag_info.blur_radius; i <= frag_info.blur_radius; i++) { - float gaussian = IPGaussian(i, frag_info.blur_sigma); + for (float16_t i = -frag_info.blur_radius; i <= frag_info.blur_radius; i++) { + float16_t gaussian = IPGaussian(i, frag_info.blur_sigma); gaussian_integral += gaussian; total_color += gaussian * @@ -58,13 +58,14 @@ void main() { ); } - vec4 blur_color = total_color / gaussian_integral; + f16vec4 blur_color = total_color / gaussian_integral; - vec4 src_color = Sample(alpha_mask_sampler, // sampler - v_src_texture_coords // texture coordinates + f16vec4 src_color = Sample(alpha_mask_sampler, // sampler + v_src_texture_coords // texture coordinates ); - float blur_factor = frag_info.inner_blur_factor * float(src_color.a > 0) + - frag_info.outer_blur_factor * float(src_color.a == 0); + float16_t blur_factor = + frag_info.inner_blur_factor * float16_t(src_color.a > 0.0hf) + + frag_info.outer_blur_factor * float16_t(src_color.a == 0.0hf); frag_color = blur_color * blur_factor + src_color * frag_info.src_factor; } diff --git a/impeller/entity/shaders/gaussian_blur.vert b/impeller/entity/shaders/gaussian_blur.vert index f402003b13bf1..96b2ccf5c66c8 100644 --- a/impeller/entity/shaders/gaussian_blur.vert +++ b/impeller/entity/shaders/gaussian_blur.vert @@ -16,13 +16,13 @@ in vec2 vertices; in vec2 texture_coords; in vec2 src_texture_coords; -out vec2 v_texture_coords; -out vec2 v_src_texture_coords; +out f16vec2 v_texture_coords; +out f16vec2 v_src_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(vertices, 0.0, 1.0); - v_texture_coords = - IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale); - v_src_texture_coords = IPRemapCoords( - src_texture_coords, frame_info.alpha_mask_sampler_y_coord_scale); + v_texture_coords = f16vec2( + IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale)); + v_src_texture_coords = f16vec2(IPRemapCoords( + src_texture_coords, frame_info.alpha_mask_sampler_y_coord_scale)); } diff --git a/impeller/entity/shaders/gaussian_blur_decal.frag b/impeller/entity/shaders/gaussian_blur_decal.frag index c3076c7f7f902..89959df2b8130 100644 --- a/impeller/entity/shaders/gaussian_blur_decal.frag +++ b/impeller/entity/shaders/gaussian_blur_decal.frag @@ -3,8 +3,9 @@ // found in the LICENSE file. #include +#include -vec4 Sample(sampler2D tex, vec2 coords) { +f16vec4 Sample(f16sampler2D tex, f16vec2 coords) { return IPSampleDecal(tex, coords); } diff --git a/impeller/entity/shaders/rrect_blur.frag b/impeller/entity/shaders/rrect_blur.frag index 5b0ddff80976c..adfb99493a5d0 100644 --- a/impeller/entity/shaders/rrect_blur.frag +++ b/impeller/entity/shaders/rrect_blur.frag @@ -6,58 +6,59 @@ #include uniform FragInfo { - vec4 color; - float blur_sigma; - vec2 rect_size; - float corner_radius; + f16vec4 color; + f16vec2 rect_size; + float16_t blur_sigma; + float16_t corner_radius; } frag_info; -in vec2 v_position; +in f16vec2 v_position; -out vec4 frag_color; +out f16vec4 frag_color; const int kSampleCount = 4; -float RRectDistance(vec2 sample_position, vec2 half_size) { - vec2 space = abs(sample_position) - half_size + frag_info.corner_radius; - return length(max(space, 0.0)) + min(max(space.x, space.y), 0.0) - +float16_t RRectDistance(f16vec2 sample_position, f16vec2 half_size) { + f16vec2 space = abs(sample_position) - half_size + frag_info.corner_radius; + return length(max(space, 0.0hf)) + min(max(space.x, space.y), 0.0hf) - frag_info.corner_radius; } /// Closed form unidirectional rounded rect blur mask solution using the /// analytical Gaussian integral (with approximated erf). -float RRectShadowX(vec2 sample_position, vec2 half_size) { +float16_t RRectShadowX(f16vec2 sample_position, f16vec2 half_size) { // Compute the X direction distance field (not incorporating the Y distance) // for the rounded rect. - float space = - min(0, half_size.y - frag_info.corner_radius - abs(sample_position.y)); - float rrect_distance = + float16_t space = min( + 0.0hf, half_size.y - frag_info.corner_radius - abs(sample_position.y)); + float16_t rrect_distance = half_size.x - frag_info.corner_radius + - sqrt(max(0, frag_info.corner_radius * frag_info.corner_radius - - space * space)); + sqrt(max(0.0hf, frag_info.corner_radius * frag_info.corner_radius - + space * space)); // Map the linear distance field to the approximate Gaussian integral. - vec2 integral = IPVec2FastGaussianIntegral( - sample_position.x + vec2(-rrect_distance, rrect_distance), + f16vec2 integral = IPVec2FastGaussianIntegral( + sample_position.x + f16vec2(-rrect_distance, rrect_distance), frag_info.blur_sigma); return integral.y - integral.x; } -float RRectShadow(vec2 sample_position, vec2 half_size) { +float16_t RRectShadow(f16vec2 sample_position, f16vec2 half_size) { // Limit the sampling range to 3 standard deviations in the Y direction from // the kernel center to incorporate 99.7% of the color contribution. - float half_sampling_range = frag_info.blur_sigma * 3; + float16_t half_sampling_range = frag_info.blur_sigma * 3.0hf; - float begin_y = max(-half_sampling_range, sample_position.y - half_size.y); - float end_y = min(half_sampling_range, sample_position.y + half_size.y); - float interval = (end_y - begin_y) / kSampleCount; + float16_t begin_y = + max(-half_sampling_range, sample_position.y - half_size.y); + float16_t end_y = min(half_sampling_range, sample_position.y + half_size.y); + float16_t interval = (end_y - begin_y) / float16_t(kSampleCount); // Sample the X blur kSampleCount times, weighted by the Gaussian function. - float result = 0; + float16_t result = 0.0hf; for (int sample_i = 0; sample_i < kSampleCount; sample_i++) { - float y = begin_y + interval * (sample_i + 0.5); - result += RRectShadowX(vec2(sample_position.x, sample_position.y - y), + float16_t y = begin_y + interval * (float16_t(sample_i) + 0.5hf); + result += RRectShadowX(f16vec2(sample_position.x, sample_position.y - y), half_size) * IPGaussian(y, frag_info.blur_sigma) * interval; } @@ -68,10 +69,10 @@ float RRectShadow(vec2 sample_position, vec2 half_size) { void main() { frag_color = frag_info.color; - vec2 half_size = frag_info.rect_size * 0.5; - vec2 sample_position = v_position - half_size; + f16vec2 half_size = frag_info.rect_size * 0.5hf; + f16vec2 sample_position = v_position - half_size; - if (frag_info.blur_sigma > 0) { + if (frag_info.blur_sigma > 0.0hf) { frag_color *= RRectShadow(sample_position, half_size); } else { frag_color *= -RRectDistance(sample_position, half_size); diff --git a/impeller/entity/shaders/rrect_blur.vert b/impeller/entity/shaders/rrect_blur.vert index 87382f6b4dcbe..6ca9e06bba4b8 100644 --- a/impeller/entity/shaders/rrect_blur.vert +++ b/impeller/entity/shaders/rrect_blur.vert @@ -11,10 +11,10 @@ frame_info; in vec2 position; -out vec2 v_position; +out f16vec2 v_position; void main() { gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0); // The fragment stage uses local coordinates to compute the blur. - v_position = position; + v_position = f16vec2(position); } 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/entity/shaders/texture_fill.frag b/impeller/entity/shaders/texture_fill.frag index 78cb9d90b297e..85aae42445bc9 100644 --- a/impeller/entity/shaders/texture_fill.frag +++ b/impeller/entity/shaders/texture_fill.frag @@ -4,18 +4,18 @@ #include -uniform sampler2D texture_sampler; +uniform f16sampler2D texture_sampler; uniform FragInfo { - float alpha; + float16_t alpha; } frag_info; -in vec2 v_texture_coords; +in f16vec2 v_texture_coords; -out vec4 frag_color; +out f16vec4 frag_color; void main() { - vec4 sampled = texture(texture_sampler, v_texture_coords); + f16vec4 sampled = texture(texture_sampler, v_texture_coords); frag_color = sampled * frag_info.alpha; } diff --git a/impeller/entity/shaders/texture_fill.vert b/impeller/entity/shaders/texture_fill.vert index e0f2c7882936a..b6af412649d47 100644 --- a/impeller/entity/shaders/texture_fill.vert +++ b/impeller/entity/shaders/texture_fill.vert @@ -14,10 +14,10 @@ frame_info; in vec2 position; in vec2 texture_coords; -out vec2 v_texture_coords; +out f16vec2 v_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0); - v_texture_coords = - IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale); + v_texture_coords = f16vec2( + IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale)); } diff --git a/impeller/entity/shaders/tiled_texture_fill.frag b/impeller/entity/shaders/tiled_texture_fill.frag index 030a94ba09aba..7b864b88fa1e0 100644 --- a/impeller/entity/shaders/tiled_texture_fill.frag +++ b/impeller/entity/shaders/tiled_texture_fill.frag @@ -5,18 +5,18 @@ #include #include -uniform sampler2D texture_sampler; +uniform f16sampler2D texture_sampler; uniform FragInfo { - float x_tile_mode; - float y_tile_mode; - float alpha; + float16_t x_tile_mode; + float16_t y_tile_mode; + float16_t alpha; } frag_info; -in vec2 v_texture_coords; +in f16vec2 v_texture_coords; -out vec4 frag_color; +out f16vec4 frag_color; void main() { frag_color = IPSampleWithTileMode(texture_sampler, // sampler diff --git a/impeller/entity/shaders/tiled_texture_fill.vert b/impeller/entity/shaders/tiled_texture_fill.vert index e0f2c7882936a..b6af412649d47 100644 --- a/impeller/entity/shaders/tiled_texture_fill.vert +++ b/impeller/entity/shaders/tiled_texture_fill.vert @@ -14,10 +14,10 @@ frame_info; in vec2 position; in vec2 texture_coords; -out vec2 v_texture_coords; +out f16vec2 v_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0); - v_texture_coords = - IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale); + v_texture_coords = f16vec2( + IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale)); } diff --git a/impeller/geometry/BUILD.gn b/impeller/geometry/BUILD.gn index a1b511ce9f41b..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", diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 191d944952d79..89658c64ec997 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -10,6 +10,7 @@ #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" @@ -2086,5 +2087,16 @@ TEST(GeometryTest, Gradient) { } } +TEST(GeometryTest, Half) { + 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); +} + } // namespace testing } // namespace impeller diff --git a/impeller/geometry/half.cc b/impeller/geometry/half.cc new file mode 100644 index 0000000000000..42f99ccc5f978 --- /dev/null +++ b/impeller/geometry/half.cc @@ -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" + +namespace impeller { + +_Float16 ScalarToHalf(Scalar f) { + return static_cast<_Float16>(f); +} + +} // namespace impeller diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h new file mode 100644 index 0000000000000..e3a6404e4446d --- /dev/null +++ b/impeller/geometry/half.h @@ -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 + +#include "color.h" +#include "point.h" +#include "scalar.h" +#include "vector.h" + +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 { + 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.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)){}; +}; + +/// @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 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" diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni index c9a46c15a2511..d5bf709255d1e 100644 --- a/impeller/tools/impeller.gni +++ b/impeller/tools/impeller.gni @@ -305,6 +305,10 @@ template("impellerc") { args += [ "--metal-version=$metal_version" ] } + if (defined(invoker.use_half_textures) && invoker.use_half_textures) { + args += [ "--use-half-textures" ] + } + if (json) { args += [ "--json" ] } @@ -403,6 +407,11 @@ template("_impeller_shaders_metal") { metal_version = invoker.metal_version } + use_half_textures = false + if (defined(invoker.use_half_textures) && invoker.use_half_textures) { + use_half_textures = invoker.use_half_textures + } + shaders_base_name = string_join("", [ invoker.name, @@ -413,6 +422,7 @@ template("_impeller_shaders_metal") { shaders = invoker.shaders metal_version = metal_version sl_file_extension = "metal" + use_half_textures = use_half_textures shader_target_flag = "" defines = [ "IMPELLER_TARGET_METAL" ] if (is_ios) { @@ -666,12 +676,26 @@ template("_impeller_shaders_vk") { # # The SPIR-V version required by the shaders. # +# @param[options] use_half_textures +# +# Whether the metal shader is using half-precision textures and requires +# openGL semantics when compilig SPIR-V. +# template("impeller_shaders") { metal_version = "1.2" if (defined(invoker.metal_version)) { metal_version = invoker.metal_version } - not_needed([ "metal_version" ]) + + use_half_textures = false + if (defined(invoker.use_half_textures) && invoker.use_half_textures) { + use_half_textures = true + } + + not_needed([ + "metal_version", + "use_half_textures", + ]) enable_opengles = impeller_enable_opengles if (defined(invoker.enable_opengles)) { @@ -685,6 +709,7 @@ template("impeller_shaders") { name = invoker.name shaders = invoker.shaders metal_version = metal_version + use_half_textures = use_half_textures } }