diff --git a/impeller/compiler/shader_lib/impeller/texture.glsl b/impeller/compiler/shader_lib/impeller/texture.glsl index cd0e33c248bbe..02cfe241bce5e 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. @@ -139,7 +139,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 0cc2fee2aa332..ca31a6149f5bf 100644 --- a/impeller/compiler/shader_lib/impeller/types.glsl +++ b/impeller/compiler/shader_lib/impeller/types.glsl @@ -7,21 +7,85 @@ #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 -#ifndef IMPELLER_TARGET_METAL_IOS +#ifdef IMPELLER_TARGET_OPENGLES -precision mediump sampler2D; -precision mediump float; +// 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; #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 -#endif // IMPELLER_TARGET_METAL +#define u8vec3 vec3 +#define u16vec3 vec3 +#define u32vec3 vec3 +#define u64vec3 vec3 + +#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) + +// 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 f32sampler2D + +#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 d60e9237e1a86..6a9d47bef93c7 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 0c83645eb266c..9ea62b8eb36b9 100644 --- a/impeller/entity/shaders/blending/blend.frag +++ b/impeller/entity/shaders/blending/blend.frag @@ -17,6 +17,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 3b2818dee12ac..db3adeaa4585f 100644 --- a/impeller/entity/shaders/blending/porter_duff_blend.frag +++ b/impeller/entity/shaders/blending/porter_duff_blend.frag @@ -27,15 +27,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 033cb61b48a46..e5ace97b394f1 100644 --- a/impeller/entity/shaders/border_mask_blur.frag +++ b/impeller/entity/shaders/border_mask_blur.frag @@ -40,7 +40,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 8177f211a7ff9..2eae449f93f78 100644 --- a/impeller/entity/shaders/color_matrix_color_filter.frag +++ b/impeller/entity/shaders/color_matrix_color_filter.frag @@ -43,7 +43,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 d09c69fa69dd6..2dddf8ff1a5cc 100644 --- a/impeller/entity/shaders/glyph_atlas.frag +++ b/impeller/entity/shaders/glyph_atlas.frag @@ -16,6 +16,6 @@ in highp vec2 v_uv; 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 * frag_info.text_color; } diff --git a/impeller/entity/shaders/glyph_atlas_color.frag b/impeller/entity/shaders/glyph_atlas_color.frag index ea98bbbe28207..c868d002788f1 100644 --- a/impeller/entity/shaders/glyph_atlas_color.frag +++ b/impeller/entity/shaders/glyph_atlas_color.frag @@ -16,6 +16,6 @@ in highp vec2 v_uv; 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 * frag_info.text_color.aaaa; } diff --git a/impeller/entity/shaders/linear_to_srgb_filter.frag b/impeller/entity/shaders/linear_to_srgb_filter.frag index bb9edb7961f30..acbd47eb4cc0b 100644 --- a/impeller/entity/shaders/linear_to_srgb_filter.frag +++ b/impeller/entity/shaders/linear_to_srgb_filter.frag @@ -22,7 +22,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 17a7e47cdeb24..73335669fe441 100644 --- a/impeller/entity/shaders/morphology_filter.frag +++ b/impeller/entity/shaders/morphology_filter.frag @@ -34,7 +34,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/texture_fill.frag b/impeller/entity/shaders/texture_fill.frag index b99655489726d..e6bc381af1231 100644 --- a/impeller/entity/shaders/texture_fill.frag +++ b/impeller/entity/shaders/texture_fill.frag @@ -18,6 +18,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 * frag_info.alpha; } diff --git a/impeller/entity/shaders/yuv_to_rgb_filter.frag b/impeller/entity/shaders/yuv_to_rgb_filter.frag index 40b1a5671ee04..707cfcfb68536 100644 --- a/impeller/entity/shaders/yuv_to_rgb_filter.frag +++ b/impeller/entity/shaders/yuv_to_rgb_filter.frag @@ -31,7 +31,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/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc index ddbbdb9160fd2..26171024d9032 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -147,6 +147,14 @@ CapabilitiesVK::GetRequiredInstanceExtensions() 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; } @@ -175,6 +183,22 @@ CapabilitiesVK::GetRequiredDeviceExtensions( if (exts.find("VK_KHR_portability_subset") != exts.end()) { required.push_back("VK_KHR_portability_subset"); } + + // Vulkan 1.1 core extensions for 16 bit buffer access. + if (exts.find("VK_KHR_storage_buffer_storage_class") == exts.end()) { + VALIDATION_LOG << "Device does not support the " + "VK_KHR_storage_buffer_storage_class extension."; + return std::nullopt; + } + required.push_back("VK_KHR_storage_buffer_storage_class"); + if (exts.find("VK_KHR_16bit_storage") == exts.end()) { + VALIDATION_LOG << "Device does not support the " + "VK_KHR_16bit_storage extension."; + return std::nullopt; + } + required.push_back( + "VK_KHR_16bit_storage"); // Requires SPV_KHR_16bit_storage. + return required; }