From 58ac1dadd69dfd2b873738edc5527400337771b8 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Wed, 6 Nov 2024 07:56:17 -0800 Subject: [PATCH] [Impeller] split downsample shader into GLES variant. (#56376) This fixes a crash reported on a moto g4 where the on device shader compiler fails to process the ifdef. --- ci/licenses_golden/licenses_flutter | 4 + impeller/entity/BUILD.gn | 1 + impeller/entity/contents/content_context.cc | 12 +- impeller/entity/contents/content_context.h | 11 + .../filters/gaussian_blur_filter_contents.cc | 15 +- impeller/entity/shaders/downsample.glsl | 44 ++++ .../entity/shaders/texture_downsample.frag | 45 +--- .../shaders/texture_downsample_gles.frag | 5 + impeller/tools/malioc.json | 192 +++++++++++++++++- 9 files changed, 279 insertions(+), 50 deletions(-) create mode 100644 impeller/entity/shaders/downsample.glsl create mode 100644 impeller/entity/shaders/texture_downsample_gles.frag diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 80872e87f85ec..e35f4f66585ac 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -43065,6 +43065,7 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.vert ORIGIN: ../../../flutter/impeller/entity/shaders/blending/vertices_uber.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/clip.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/clip.vert + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/downsample.glsl + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/filters/border_mask_blur.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/filters/color_matrix_color_filter.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/filters/filter_position.vert + ../../../flutter/LICENSE @@ -43093,6 +43094,7 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/runtime_effect.vert + ../../../ ORIGIN: ../../../flutter/impeller/entity/shaders/solid_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/solid_fill.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/texture_downsample.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/texture_downsample_gles.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill_strict_src.frag + ../../../flutter/LICENSE @@ -45925,6 +45927,7 @@ FILE: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.vert FILE: ../../../flutter/impeller/entity/shaders/blending/vertices_uber.frag FILE: ../../../flutter/impeller/entity/shaders/clip.frag FILE: ../../../flutter/impeller/entity/shaders/clip.vert +FILE: ../../../flutter/impeller/entity/shaders/downsample.glsl FILE: ../../../flutter/impeller/entity/shaders/filters/border_mask_blur.frag FILE: ../../../flutter/impeller/entity/shaders/filters/color_matrix_color_filter.frag FILE: ../../../flutter/impeller/entity/shaders/filters/filter_position.vert @@ -45953,6 +45956,7 @@ FILE: ../../../flutter/impeller/entity/shaders/runtime_effect.vert FILE: ../../../flutter/impeller/entity/shaders/solid_fill.frag FILE: ../../../flutter/impeller/entity/shaders/solid_fill.vert FILE: ../../../flutter/impeller/entity/shaders/texture_downsample.frag +FILE: ../../../flutter/impeller/entity/shaders/texture_downsample_gles.frag FILE: ../../../flutter/impeller/entity/shaders/texture_fill.frag FILE: ../../../flutter/impeller/entity/shaders/texture_fill.vert FILE: ../../../flutter/impeller/entity/shaders/texture_fill_strict_src.frag diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 76657a5595ad6..9fcee9c7afd54 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -51,6 +51,7 @@ impeller_shaders("entity_shaders") { "shaders/gradients/fast_gradient.vert", "shaders/gradients/fast_gradient.frag", "shaders/texture_downsample.frag", + "shaders/texture_downsample_gles.frag", ] } diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 5c141a9474afd..fe1725e5a8ac6 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -336,8 +336,8 @@ ContentContext::ContentContext( clip_pipelines_.SetDefault( options, std::make_unique(*context_, clip_pipeline_descriptor)); - texture_downsample_pipelines_.CreateDefault( - *context_, options_trianglestrip, {supports_decal}); + texture_downsample_pipelines_.CreateDefault(*context_, + options_trianglestrip); rrect_blur_pipelines_.CreateDefault(*context_, options_trianglestrip); texture_strict_src_pipelines_.CreateDefault(*context_, options); tiled_texture_pipelines_.CreateDefault(*context_, options, @@ -454,10 +454,14 @@ ContentContext::ContentContext( options_trianglestrip); yuv_to_rgb_filter_pipelines_.CreateDefault(*context_, options_trianglestrip); - // GLES only shader that is unsupported on macOS. -#if defined(IMPELLER_ENABLE_OPENGLES) && !defined(FML_OS_MACOSX) +#if defined(IMPELLER_ENABLE_OPENGLES) if (GetContext()->GetBackendType() == Context::BackendType::kOpenGLES) { +#if !defined(FML_OS_MACOSX) + // GLES only shader that is unsupported on macOS. tiled_texture_external_pipelines_.CreateDefault(*context_, options); +#endif // !defined(FML_OS_MACOSX) + texture_downsample_gles_pipelines_.CreateDefault(*context_, + options_trianglestrip); } #endif // IMPELLER_ENABLE_OPENGLES diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 390be88286c87..69d67b97f4657 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -70,6 +70,7 @@ #include "impeller/entity/vertices_uber.frag.h" #ifdef IMPELLER_ENABLE_OPENGLES +#include "impeller/entity/texture_downsample_gles.frag.h" #include "impeller/entity/tiled_texture_fill_external.frag.h" #endif // IMPELLER_ENABLE_OPENGLES @@ -239,6 +240,9 @@ using VerticesUberShader = RenderPipelineHandle; +using TextureDownsampleGlesPipeline = + RenderPipelineHandle; #endif // IMPELLER_ENABLE_OPENGLES /// Pipeline state configuration. @@ -426,6 +430,11 @@ class ContentContext { } #ifdef IMPELLER_ENABLE_OPENGLES + std::shared_ptr> + GetDownsampleTextureGlesPipeline(ContentContextOptions opts) const { + return GetPipeline(texture_downsample_gles_pipelines_, opts); + } + std::shared_ptr> GetTiledTextureExternalPipeline( ContentContextOptions opts) const { FML_DCHECK(GetContext()->GetBackendType() == @@ -873,6 +882,8 @@ class ContentContext { #ifdef IMPELLER_ENABLE_OPENGLES mutable Variants tiled_texture_external_pipelines_; + mutable Variants + texture_downsample_gles_pipelines_; #endif // IMPELLER_ENABLE_OPENGLES mutable Variants tiled_texture_pipelines_; mutable Variants gaussian_blur_pipelines_; diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 17017b1f9e00c..b2e81ce1dc342 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -396,7 +396,20 @@ fml::StatusOr MakeDownsampleSubpass( pass.SetCommandLabel("Gaussian blur downsample"); auto pipeline_options = OptionsFromPass(pass); pipeline_options.primitive_type = PrimitiveType::kTriangleStrip; +#ifdef IMPELLER_ENABLE_OPENGLES + // The GLES backend conditionally supports decal tile mode, while + // decal is always supported for Vulkan and Metal. + if (renderer.GetDeviceCapabilities() + .SupportsDecalSamplerAddressMode() || + tile_mode != Entity::TileMode::kDecal) { + pass.SetPipeline(renderer.GetDownsamplePipeline(pipeline_options)); + } else { + pass.SetPipeline( + renderer.GetDownsampleTextureGlesPipeline(pipeline_options)); + } +#else pass.SetPipeline(renderer.GetDownsamplePipeline(pipeline_options)); +#endif // IMPELLER_ENABLE_OPENGLES TextureFillVertexShader::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); @@ -407,8 +420,6 @@ fml::StatusOr MakeDownsampleSubpass( frag_info.edge = edge; frag_info.ratio = ratio; frag_info.pixel_size = Vector2(1.0f / Size(input_texture->GetSize())); - frag_info.use_decal = - (tile_mode == Entity::TileMode::kDecal) ? 1.0 : 0.0; const Quad& uvs = pass_args.uvs; std::array vertices = { diff --git a/impeller/entity/shaders/downsample.glsl b/impeller/entity/shaders/downsample.glsl new file mode 100644 index 0000000000000..58973b3043aaa --- /dev/null +++ b/impeller/entity/shaders/downsample.glsl @@ -0,0 +1,44 @@ +// 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. + +precision mediump float; + +#include +#include + +uniform f16sampler2D texture_sampler; + +uniform FragInfo { + float edge; + float ratio; + vec2 pixel_size; +} +frag_info; + +in highp vec2 v_texture_coords; + +out vec4 frag_color; + +vec4 Sample(vec2 uv) { +#ifdef SUPPORTS_DECAL + return texture(texture_sampler, uv, float16_t(kDefaultMipBias)); +#else + if ((uv.x < 0 || uv.y < 0 || uv.x > 1 || uv.y > 1)) { + return vec4(0); + } else { + return texture(texture_sampler, uv, float16_t(kDefaultMipBias)); + } +#endif +} + +void main() { + vec4 total = vec4(0.0); + for (float i = -frag_info.edge; i <= frag_info.edge; i += 2) { + for (float j = -frag_info.edge; j <= frag_info.edge; j += 2) { + total += (Sample(v_texture_coords + frag_info.pixel_size * vec2(i, j)) * + frag_info.ratio); + } + } + frag_color = total; +} diff --git a/impeller/entity/shaders/texture_downsample.frag b/impeller/entity/shaders/texture_downsample.frag index 487422f66b2d7..5b7b14d107002 100644 --- a/impeller/entity/shaders/texture_downsample.frag +++ b/impeller/entity/shaders/texture_downsample.frag @@ -2,47 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -precision mediump float; +#define SUPPORTS_DECAL 1 -#include -#include - -layout(constant_id = 0) const float supports_decal = 1.0; - -uniform f16sampler2D texture_sampler; - -uniform FragInfo { - float edge; - float ratio; - float use_decal; - vec2 pixel_size; -} -frag_info; - -in highp vec2 v_texture_coords; - -out vec4 frag_color; - -vec4 Sample(vec2 uv) { - if (supports_decal == 1.0) { - return texture(texture_sampler, uv, float16_t(kDefaultMipBias)); - } else { - if (frag_info.use_decal == 1.0 && - (uv.x < 0 || uv.y < 0 || uv.x > 1 || uv.y > 1)) { - return vec4(0); - } else { - return texture(texture_sampler, uv, float16_t(kDefaultMipBias)); - } - } -} - -void main() { - vec4 total = vec4(0.0); - for (float i = -frag_info.edge; i <= frag_info.edge; i += 2) { - for (float j = -frag_info.edge; j <= frag_info.edge; j += 2) { - total += (Sample(v_texture_coords + frag_info.pixel_size * vec2(i, j)) * - frag_info.ratio); - } - } - frag_color = total; -} +#include diff --git a/impeller/entity/shaders/texture_downsample_gles.frag b/impeller/entity/shaders/texture_downsample_gles.frag new file mode 100644 index 0000000000000..a16583437c2d7 --- /dev/null +++ b/impeller/entity/shaders/texture_downsample_gles.frag @@ -0,0 +1,5 @@ +// 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 diff --git a/impeller/tools/malioc.json b/impeller/tools/malioc.json index 1204c35fa36c2..21d6567c74d83 100644 --- a/impeller/tools/malioc.json +++ b/impeller/tools/malioc.json @@ -4845,7 +4845,125 @@ }, "thread_occupancy": 100, "uniform_registers_used": 1, - "work_registers_used": 3 + "work_registers_used": 4 + } + } + } + }, + "flutter/impeller/entity/gles/texture_downsample_gles.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/texture_downsample_gles.frag.gles", + "has_side_effects": false, + "has_uniform_computation": true, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 57, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + null + ], + "longest_path_cycles": [ + null, + null, + null, + null, + null, + null, + null + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "shortest_path_cycles": [ + 0.0625, + 0.0, + 0.0625, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.359375, + 0.125, + 0.359375, + 0.0, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 6, + "work_registers_used": 19 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/texture_downsample_gles.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + null + ], + "longest_path_cycles": [ + null, + null, + null + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic", + "load_store" + ], + "shortest_path_cycles": [ + 1.0, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 5.333333492279053, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 4 } } } @@ -7515,6 +7633,78 @@ } } }, + "flutter/impeller/entity/texture_downsample_gles.frag.vkspv": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/texture_downsample_gles.frag.vkspv", + "has_side_effects": false, + "has_uniform_computation": true, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 28, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + null + ], + "longest_path_cycles": [ + null, + null, + null, + null, + null, + null, + null + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "shortest_path_cycles": [ + 0.109375, + 0.0, + 0.109375, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.4375, + 0.09375, + 0.4375, + 0.0, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 17 + } + } + } + }, "flutter/impeller/entity/texture_fill.frag.vkspv": { "Mali-G78": { "core": "Mali-G78",