diff --git a/impeller/compiler/shader_lib/impeller/texture.glsl b/impeller/compiler/shader_lib/impeller/texture.glsl index c973dd2971699..51f1418586734 100644 --- a/impeller/compiler/shader_lib/impeller/texture.glsl +++ b/impeller/compiler/shader_lib/impeller/texture.glsl @@ -100,7 +100,7 @@ f16vec4 IPHalfSampleWithTileMode(f16sampler2D tex, return f16vec4(0.0hf); } - return texture(tex, coords, kDefaultMipBiasHalf); + return f16vec4(texture(tex, coords, kDefaultMipBiasHalf)); } /// Sample a texture, emulating a specific tile mode. @@ -140,7 +140,7 @@ f16vec4 IPHalfSampleDecal(f16sampler2D texture_sampler, vec2 coords) { any(greaterThanEqual(coords, vec2(1)))) { return f16vec4(0.0); } - return texture(texture_sampler, coords, kDefaultMipBiasHalf); + return f16vec4(texture(texture_sampler, coords, kDefaultMipBiasHalf)); } /// Sample a texture, emulating a specific tile mode. diff --git a/impeller/compiler/shader_lib/impeller/types.glsl b/impeller/compiler/shader_lib/impeller/types.glsl index b0ce4188d08ee..766f45beaef6a 100644 --- a/impeller/compiler/shader_lib/impeller/types.glsl +++ b/impeller/compiler/shader_lib/impeller/types.glsl @@ -7,7 +7,13 @@ #extension GL_AMD_gpu_shader_half_float : enable #extension GL_AMD_gpu_shader_half_float_fetch : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable #extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_float32 : enable +#extension GL_EXT_shader_explicit_arithmetic_types_float64 : enable #ifdef IMPELLER_TARGET_OPENGLES #define IMPELLER_MAYBE_FLAT @@ -15,18 +21,81 @@ #define IMPELLER_MAYBE_FLAT flat #endif -#ifndef IMPELLER_TARGET_METAL_IOS +#if defined(IMPELLER_TARGET_OPENGLES) || defined(IMPELLER_TARGET_MOLTENVK) + +// OpenGLES 2 targets GLSL ES 1.0, which doesn't support explicit arithmetic +// types on individual declarations. So for GLES, we provide macros for 16 bit +// types to keep writing cross API shaders easy. +// +// By default, OpenGLES sets the floating point precision to `highp` for vertex +// shaders and `mediump` for fragment shaders. Fragment shader samplers are set +// to `lowp` by default. Individual shaders may explicitly declare the +// precision for all declarations in the shader. +// +// For example: +// precision mediump sampler2D; +// precision mediump float; precision mediump sampler2D; #define float16_t float +#define float32_t float +#define float64_t float + #define f16vec2 vec2 +#define f32vec2 vec2 +#define f64vec2 vec2 + #define f16vec3 vec3 +#define f32vec3 vec3 +#define f64vec3 vec3 + #define f16vec4 vec4 +#define f32vec4 vec4 +#define f64vec4 vec4 + #define f16mat4 mat4 +#define f32mat4 mat4 +#define f64mat4 mat4 + #define f16sampler2D sampler2D +#define f32sampler2D sampler2D +#define f64sampler2D sampler2D + +#define uint8_t uint +#define uint16_t uint +#define uint32_t uint +#define uint64_t uint + +#define u8vec2 vec2 +#define u16vec2 vec2 +#define u32vec2 vec2 +#define u64vec2 vec2 + +#define u8vec3 vec3 +#define u16vec3 vec3 +#define u32vec3 vec3 +#define u64vec3 vec3 -#endif // IMPELLER_TARGET_METAL +#define u8vec4 vec4 +#define u16vec4 vec4 +#define u32vec4 vec4 +#define u64vec4 vec4 + +#define u8mat4 mat4 +#define u16mat4 mat4 +#define u32mat4 mat4 +#define u64mat4 mat4 + +#elif defined(IMPELLER_TARGET_VULKAN) + +precision mediump sampler2D; + +// Vulkan does not support 16 bit floating point samplers. +// https://registry.khronos.org/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-StandaloneSpirv-OpTypeImage-04656 +#define f16sampler2D sampler2D + +#endif #define BoolF float #define BoolV2 vec2 diff --git a/impeller/entity/shaders/blending/advanced_blend.glsl b/impeller/entity/shaders/blending/advanced_blend.glsl index c2e26d59bf7b3..7d54f870d0b00 100644 --- a/impeller/entity/shaders/blending/advanced_blend.glsl +++ b/impeller/entity/shaders/blending/advanced_blend.glsl @@ -26,9 +26,9 @@ out f16vec4 frag_color; f16vec4 Sample(f16sampler2D texture_sampler, vec2 texture_coords) { // gles 2.0 is the only backend without native decal support. #ifdef IMPELLER_TARGET_OPENGLES - return IPSampleDecal(texture_sampler, texture_coords); + return IPHalfSampleDecal(texture_sampler, texture_coords); #else - return texture(texture_sampler, texture_coords); + return f16vec4(texture(texture_sampler, texture_coords)); #endif } diff --git a/impeller/entity/shaders/blending/blend.frag b/impeller/entity/shaders/blending/blend.frag index d8eb5b806f894..d2cb8a9810d55 100644 --- a/impeller/entity/shaders/blending/blend.frag +++ b/impeller/entity/shaders/blending/blend.frag @@ -19,6 +19,6 @@ in vec2 v_texture_coords; out f16vec4 frag_color; void main() { - frag_color = - texture(texture_sampler_src, v_texture_coords) * frag_info.input_alpha; + frag_color = f16vec4(texture(texture_sampler_src, v_texture_coords)) * + frag_info.input_alpha; } diff --git a/impeller/entity/shaders/blending/porter_duff_blend.frag b/impeller/entity/shaders/blending/porter_duff_blend.frag index 01ba70310f193..354f35c89e2da 100644 --- a/impeller/entity/shaders/blending/porter_duff_blend.frag +++ b/impeller/entity/shaders/blending/porter_duff_blend.frag @@ -29,15 +29,15 @@ out f16vec4 frag_color; f16vec4 Sample(f16sampler2D texture_sampler, vec2 texture_coords) { // gles 2.0 is the only backend without native decal support. #ifdef IMPELLER_TARGET_OPENGLES - return IPSampleDecal(texture_sampler, texture_coords); + return IPHalfSampleDecal(texture_sampler, texture_coords); #else - return texture(texture_sampler, texture_coords); + return f16vec4(texture(texture_sampler, texture_coords)); #endif } void main() { - f16vec4 dst = - texture(texture_sampler_dst, v_texture_coords) * frag_info.input_alpha; + f16vec4 dst = f16vec4(texture(texture_sampler_dst, v_texture_coords)) * + frag_info.input_alpha; f16vec4 src = frag_info.color; frag_color = src * (frag_info.src_coeff + dst.a * frag_info.src_coeff_dst_alpha) + diff --git a/impeller/entity/shaders/border_mask_blur.frag b/impeller/entity/shaders/border_mask_blur.frag index 55247604ad953..c3972bcb3ce1b 100644 --- a/impeller/entity/shaders/border_mask_blur.frag +++ b/impeller/entity/shaders/border_mask_blur.frag @@ -42,7 +42,7 @@ float16_t BoxBlurMask(f16vec2 uv) { } void main() { - f16vec4 image_color = texture(texture_sampler, v_texture_coords); + f16vec4 image_color = f16vec4(texture(texture_sampler, v_texture_coords)); float16_t blur_factor = BoxBlurMask(f16vec2(v_texture_coords)); float16_t within_bounds = diff --git a/impeller/entity/shaders/color_matrix_color_filter.frag b/impeller/entity/shaders/color_matrix_color_filter.frag index b8f2da6b1961b..aaf094bce333d 100644 --- a/impeller/entity/shaders/color_matrix_color_filter.frag +++ b/impeller/entity/shaders/color_matrix_color_filter.frag @@ -45,7 +45,7 @@ out f16vec4 frag_color; void main() { f16vec4 input_color = - texture(input_texture, v_texture_coords) * frag_info.input_alpha; + f16vec4(texture(input_texture, v_texture_coords)) * frag_info.input_alpha; // unpremultiply first, as filter inputs are premultiplied. f16vec4 color = IPHalfUnpremultiply(input_color); diff --git a/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl b/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl index 61724020d4445..6099aabaec064 100644 --- a/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl +++ b/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl @@ -47,7 +47,7 @@ f16vec4 Sample(f16sampler2D tex, vec2 coords) { #if ENABLE_DECAL_SPECIALIZATION return IPHalfSampleDecal(tex, coords); #else - return texture(tex, coords); + return f16vec4(texture(tex, coords)); #endif } diff --git a/impeller/entity/shaders/glyph_atlas.frag b/impeller/entity/shaders/glyph_atlas.frag index 9a9b71780dd33..b98a0035be65d 100644 --- a/impeller/entity/shaders/glyph_atlas.frag +++ b/impeller/entity/shaders/glyph_atlas.frag @@ -15,6 +15,6 @@ IMPELLER_MAYBE_FLAT in f16vec4 v_text_color; out f16vec4 frag_color; void main() { - f16vec4 value = texture(glyph_atlas_sampler, v_uv); + f16vec4 value = f16vec4(texture(glyph_atlas_sampler, v_uv)); frag_color = value.aaaa * v_text_color; } diff --git a/impeller/entity/shaders/glyph_atlas_color.frag b/impeller/entity/shaders/glyph_atlas_color.frag index 293329b764fca..802cb559f89b8 100644 --- a/impeller/entity/shaders/glyph_atlas_color.frag +++ b/impeller/entity/shaders/glyph_atlas_color.frag @@ -15,6 +15,6 @@ IMPELLER_MAYBE_FLAT in f16vec4 v_text_color; out f16vec4 frag_color; void main() { - f16vec4 value = texture(glyph_atlas_sampler, v_uv); + f16vec4 value = f16vec4(texture(glyph_atlas_sampler, v_uv)); frag_color = value * v_text_color.aaaa; } diff --git a/impeller/entity/shaders/linear_to_srgb_filter.frag b/impeller/entity/shaders/linear_to_srgb_filter.frag index d1f9e82930230..682e39d7d08a1 100644 --- a/impeller/entity/shaders/linear_to_srgb_filter.frag +++ b/impeller/entity/shaders/linear_to_srgb_filter.frag @@ -24,7 +24,7 @@ out f16vec4 frag_color; void main() { f16vec4 input_color = - texture(input_texture, v_texture_coords) * frag_info.input_alpha; + f16vec4(texture(input_texture, v_texture_coords)) * frag_info.input_alpha; f16vec4 color = IPHalfUnpremultiply(input_color); for (int i = 0; i < 3; i++) { diff --git a/impeller/entity/shaders/morphology_filter.frag b/impeller/entity/shaders/morphology_filter.frag index 8f2d01f98ee0d..86f08fc15fb0b 100644 --- a/impeller/entity/shaders/morphology_filter.frag +++ b/impeller/entity/shaders/morphology_filter.frag @@ -36,7 +36,7 @@ void main() { #ifdef IMPELLER_TARGET_OPENGLES f16vec4 color = IPHalfSampleDecal(texture_sampler, texture_coords); #else - f16vec4 color = texture(texture_sampler, texture_coords); + f16vec4 color = f16vec4(texture(texture_sampler, texture_coords)); #endif if (frag_info.morph_type == kMorphTypeDilate) { diff --git a/impeller/entity/shaders/srgb_to_linear_filter.frag b/impeller/entity/shaders/srgb_to_linear_filter.frag index 67736e2185563..66b8458af26fa 100644 --- a/impeller/entity/shaders/srgb_to_linear_filter.frag +++ b/impeller/entity/shaders/srgb_to_linear_filter.frag @@ -23,7 +23,7 @@ out f16vec4 frag_color; void main() { f16vec4 input_color = - texture(input_texture, v_texture_coords) * frag_info.input_alpha; + f16vec4(texture(input_texture, v_texture_coords)) * frag_info.input_alpha; f16vec4 color = IPHalfUnpremultiply(input_color); for (int i = 0; i < 3; i++) { diff --git a/impeller/entity/shaders/texture_fill.frag b/impeller/entity/shaders/texture_fill.frag index c520b4701ce8d..a5fe9221d3151 100644 --- a/impeller/entity/shaders/texture_fill.frag +++ b/impeller/entity/shaders/texture_fill.frag @@ -16,6 +16,6 @@ out f16vec4 frag_color; void main() { f16vec4 sampled = - texture(texture_sampler, v_texture_coords, kDefaultMipBiasHalf); + f16vec4(texture(texture_sampler, v_texture_coords, kDefaultMipBiasHalf)); frag_color = sampled * v_alpha; } diff --git a/impeller/entity/shaders/yuv_to_rgb_filter.frag b/impeller/entity/shaders/yuv_to_rgb_filter.frag index 6d8db224a5a6b..3e46ec445f49c 100644 --- a/impeller/entity/shaders/yuv_to_rgb_filter.frag +++ b/impeller/entity/shaders/yuv_to_rgb_filter.frag @@ -33,7 +33,7 @@ void main() { yuv_offset.x = 16.0hf / 255.0hf; } - yuv.x = texture(y_texture, v_texture_coords).r; - yuv.yz = texture(uv_texture, v_texture_coords).rg; + yuv.x = float16_t(texture(y_texture, v_texture_coords).r); + yuv.yz = f16vec2(texture(uv_texture, v_texture_coords).rg); frag_color = f16mat4(frag_info.matrix) * f16vec4(yuv - yuv_offset, 1.0hf); } diff --git a/impeller/geometry/half.h b/impeller/geometry/half.h index ed81e16a110f4..5659b9d02fe71 100644 --- a/impeller/geometry/half.h +++ b/impeller/geometry/half.h @@ -13,7 +13,7 @@ #include "impeller/geometry/scalar.h" #include "impeller/geometry/vector.h" -#ifdef FML_OS_WIN +#if defined(FML_OS_WIN) using InternalHalf = uint16_t; #else using InternalHalf = _Float16; @@ -24,10 +24,10 @@ namespace impeller { /// @brief Convert a scalar to a half precision float. /// /// See also: https://clang.llvm.org/docs/LanguageExtensions.html -/// This is not currently supported on Windows toolchains. +/// This is not currently supported on Windows on some Android toolchains. inline constexpr InternalHalf ScalarToHalf(Scalar f) { -#ifdef FML_OS_WIN - return static_cast(0); +#if defined(FML_OS_WIN) + return static_cast(f); #else return static_cast(f); #endif diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc index 78e6c0d0ff46f..1161892155634 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -145,6 +145,14 @@ CapabilitiesVK::GetEnabledInstanceExtensions() const { } } + // Vulkan 1.1 core extensions for 16 bit buffer access. + if (!HasExtension("VK_KHR_get_physical_device_properties2")) { + VALIDATION_LOG << "Instance does not support the " + "VK_KHR_get_physical_device_properties2 extension."; + return std::nullopt; + } + required.push_back("VK_KHR_get_physical_device_properties2"); + return required; } diff --git a/impeller/renderer/backend/vulkan/test/mock_vulkan.cc b/impeller/renderer/backend/vulkan/test/mock_vulkan.cc index a6f3d08e16dc1..0389d6adef392 100644 --- a/impeller/renderer/backend/vulkan/test/mock_vulkan.cc +++ b/impeller/renderer/backend/vulkan/test/mock_vulkan.cc @@ -36,13 +36,16 @@ VkResult vkEnumerateInstanceExtensionProperties( uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { if (!pProperties) { - *pPropertyCount = 2; + *pPropertyCount = 3; } else { strcpy(pProperties[0].extensionName, "VK_KHR_surface"); pProperties[0].specVersion = 0; strcpy(pProperties[1].extensionName, "VK_MVK_macos_surface"); pProperties[1].specVersion = 0; + strcpy(pProperties[2].extensionName, + "VK_KHR_get_physical_device_properties2"); + pProperties[2].specVersion = 0; } return VK_SUCCESS; } diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni index 2c20acf26d590..8b22cf118d397 100644 --- a/impeller/tools/impeller.gni +++ b/impeller/tools/impeller.gni @@ -596,6 +596,12 @@ template("_impeller_shaders_vk") { shader_target_flag = "--vulkan" defines = [ "IMPELLER_TARGET_VULKAN" ] + + # If we're compiling on a macOS host, then we're targeting MoltenVK which + # has additional constraints. + if (is_mac) { + defines += [ "IMPELLER_TARGET_MOLTENVK" ] + } } vk_shaders =