Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
4 changes: 2 additions & 2 deletions impeller/compiler/shader_lib/impeller/texture.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
72 changes: 68 additions & 4 deletions impeller/compiler/shader_lib/impeller/types.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this will work in general, the 16bit extensions aren't available everywhere and we can't actually support a backend that uses GLES and has 16bit uniform values, as the bindings will be incorrect.

Copy link
Member Author

Choose a reason for hiding this comment

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

16bit uniform buffer access is part of Vulkan 1.1 core, so this work on all of our targets. However, there are a few subproblems that I don't have time to work through right now: flutter/flutter#128836

Copy link
Contributor

Choose a reason for hiding this comment

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

TIL.

we use the same generated headers on GLES and Vulkan though, so we'd need to solve that issue too - probably generate a different set of bindings assuming 32bit and 16bit float and select at runtime.

Copy link
Member Author

Choose a reason for hiding this comment

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

we use the same generated headers on GLES and Vulkan though

Just for Android, right? On MacOS, I think we end up using the Metal headers for all of the backends, which maybe is another problem that needs to be solved. :/

I'm still not really sure what the best design approach would be for reconciling the different backend headers. Maybe we can automate the common case and create a generic lowest common denominator meta-header with special UBO/VBO builders to dispatch the specific packing behavior of the backend in use. But importantly, using this is optional, and we can still use the per-backend struct directly for special backend-specific optimizations whenever there's a need.

Copy link
Member Author

@bdero bdero Jun 14, 2023

Choose a reason for hiding this comment

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

Actually, we can probably further avoid this problem by just finishing our implementation of 16 bit uniform access for the other backends. Even if we can't use 16 bit uniforms on GLES 2 devices, we still just enumerate and pull each uniform out of the buffer on the CPU, and so we can emulate it.

So if we invest some time in fixing the GLES and Vulkan incompatibilities, we might be able to continue getting away with sharing headers for multiple backends. (FYI @chinmaygarde)

Copy link
Member Author

Choose a reason for hiding this comment

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

Added another issue for GLES here: flutter/flutter#128881


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
Expand Down
4 changes: 2 additions & 2 deletions impeller/entity/shaders/blending/advanced_blend.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions impeller/entity/shaders/blending/blend.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
8 changes: 4 additions & 4 deletions impeller/entity/shaders/blending/porter_duff_blend.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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) +
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/border_mask_blur.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/color_matrix_color_filter.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/glyph_atlas.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion impeller/entity/shaders/glyph_atlas_color.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion impeller/entity/shaders/linear_to_srgb_filter.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/morphology_filter.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/texture_fill.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
4 changes: 2 additions & 2 deletions impeller/entity/shaders/yuv_to_rgb_filter.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
24 changes: 24 additions & 0 deletions impeller/renderer/backend/vulkan/capabilities_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down