From 3b07c4c29c72b0c00d6690a1c1c026f37efe34b2 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Fri, 10 Mar 2023 14:24:45 -0800 Subject: [PATCH 01/16] [Impeller] remove unused shader, format malioc diff (#40230) [Impeller] remove unused shader, format malioc diff --- ci/licenses_golden/licenses_flutter | 2 - impeller/entity/BUILD.gn | 1 - impeller/entity/contents/content_context.cc | 2 - impeller/entity/contents/content_context.h | 9 - impeller/entity/contents/vertices_contents.cc | 1 - impeller/entity/shaders/position.vert | 21 - impeller/tools/malioc.json | 7429 ++++++++++++++++- impeller/tools/malioc_diff.py | 4 +- 8 files changed, 7431 insertions(+), 38 deletions(-) delete mode 100644 impeller/entity/shaders/position.vert diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 377e52850658f..85d675e57dca5 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1251,7 +1251,6 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/linear_to_srgb_filter.frag + .. ORIGIN: ../../../flutter/impeller/entity/shaders/linear_to_srgb_filter.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/morphology_filter.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/morphology_filter.vert + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/entity/shaders/position.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/position_color.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/position_uv.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/radial_gradient_fill.frag + ../../../flutter/LICENSE @@ -3781,7 +3780,6 @@ FILE: ../../../flutter/impeller/entity/shaders/linear_to_srgb_filter.frag FILE: ../../../flutter/impeller/entity/shaders/linear_to_srgb_filter.vert FILE: ../../../flutter/impeller/entity/shaders/morphology_filter.frag FILE: ../../../flutter/impeller/entity/shaders/morphology_filter.vert -FILE: ../../../flutter/impeller/entity/shaders/position.vert FILE: ../../../flutter/impeller/entity/shaders/position_color.vert FILE: ../../../flutter/impeller/entity/shaders/position_uv.vert FILE: ../../../flutter/impeller/entity/shaders/radial_gradient_fill.frag diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index dd328219e6b17..1c1fc90d25776 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -45,7 +45,6 @@ impeller_shaders("entity_shaders") { "shaders/morphology_filter.vert", "shaders/position_color.vert", "shaders/position_uv.vert", - "shaders/position.vert", "shaders/radial_gradient_fill.frag", "shaders/rrect_blur.vert", "shaders/rrect_blur.frag", diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index fcbead26b251c..36287aaf935f7 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -276,8 +276,6 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); geometry_color_pipelines_[{}] = CreateDefaultPipeline(*context_); - geometry_position_pipelines_[{}] = - CreateDefaultPipeline(*context_); yuv_to_rgb_filter_pipelines_[{}] = CreateDefaultPipeline(*context_); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 72c11360cf8f3..236167f3a9e58 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -52,7 +52,6 @@ #include "impeller/renderer/pipeline.h" #include "impeller/scene/scene_context.h" -#include "impeller/entity/position.vert.h" #include "impeller/entity/position_color.vert.h" #include "impeller/scene/scene_context.h" @@ -152,8 +151,6 @@ using GlyphAtlasSdfPipeline = using ClipPipeline = RenderPipelineT; -using GeometryPositionPipeline = - RenderPipelineT; using GeometryColorPipeline = RenderPipelineT; using YUVToRGBFilterPipeline = @@ -427,11 +424,6 @@ class ContentContext { return GetPipeline(geometry_color_pipelines_, opts); } - std::shared_ptr> GetGeometryPositionPipeline( - ContentContextOptions opts) const { - return GetPipeline(geometry_position_pipelines_, opts); - } - std::shared_ptr> GetYUVToRGBFilterPipeline( ContentContextOptions opts) const { return GetPipeline(yuv_to_rgb_filter_pipelines_, opts); @@ -661,7 +653,6 @@ class ContentContext { mutable Variants clip_pipelines_; mutable Variants glyph_atlas_pipelines_; mutable Variants glyph_atlas_sdf_pipelines_; - mutable Variants geometry_position_pipelines_; mutable Variants geometry_color_pipelines_; mutable Variants yuv_to_rgb_filter_pipelines_; // Advanced blends. diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc index de2954b00e1cc..0e675ae40498c 100644 --- a/impeller/entity/contents/vertices_contents.cc +++ b/impeller/entity/contents/vertices_contents.cc @@ -8,7 +8,6 @@ #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/texture_contents.h" -#include "impeller/entity/position.vert.h" #include "impeller/entity/position_color.vert.h" #include "impeller/entity/vertices.frag.h" #include "impeller/geometry/color.h" diff --git a/impeller/entity/shaders/position.vert b/impeller/entity/shaders/position.vert deleted file mode 100644 index db4c711fcb6c0..0000000000000 --- a/impeller/entity/shaders/position.vert +++ /dev/null @@ -1,21 +0,0 @@ -// 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 - -uniform FrameInfo { - mat4 mvp; - vec4 color; -} -frame_info; - -in vec2 position; - -out vec4 v_color; - -void main() { - gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0); - v_color = frame_info.color; -} diff --git a/impeller/tools/malioc.json b/impeller/tools/malioc.json index 2e3f6a5bf195a..6e7a73183f8c6 100644 --- a/impeller/tools/malioc.json +++ b/impeller/tools/malioc.json @@ -1 +1,7428 @@ -{"flutter/impeller/entity/gles/advanced_blend.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 8}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [3.299999952316284, 7.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [3.299999952316284, 7.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.3333332538604736, 7.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_color.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_color.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": 82, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma"], "longest_path_cycles": [0.65625, 0.65625, 0.53125, 0.625, 0.0, 0.5, 0.5], "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.375, 0.328125, 0.375, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_fma"], "total_cycles": [0.65625, 0.65625, 0.578125, 0.625, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_color.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [9.899999618530273, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [5.940000057220459, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [11.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_colorburn.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_colorburn.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu"], "longest_path_cycles": [0.6875, 0.265625, 0.675000011920929, 0.6875, 0.0, 0.5, 0.5], "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.515625, 0.234375, 0.515625, 0.4375, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.71875, 0.265625, 0.71875, 0.6875, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 26}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_colorburn.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [10.5600004196167, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [8.25, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [11.333333015441895, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_colordodge.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_colordodge.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu"], "longest_path_cycles": [0.6875, 0.234375, 0.675000011920929, 0.6875, 0.0, 0.5, 0.5], "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.515625, 0.203125, 0.515625, 0.4375, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.71875, 0.234375, 0.71875, 0.6875, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 26}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_colordodge.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [10.229999542236328, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [7.920000076293945, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [11.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_darken.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_darken.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.171875, 0.4375, 0.5, 0.0, 0.5, 0.5], "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.28125, 0.140625, 0.28125, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "total_cycles": [0.5, 0.171875, 0.484375, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_darken.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [5.940000057220459, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [3.299999952316284, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [6.666666507720947, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_difference.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_difference.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.203125, 0.40625, 0.5, 0.0, 0.5, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_cvt", "arith_sfu", "varying"], "shortest_path_cycles": [0.25, 0.171875, 0.25, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "total_cycles": [0.5, 0.203125, 0.453125, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_difference.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [5.940000057220459, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [3.299999952316284, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [6.666666507720947, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_exclusion.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_exclusion.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.265625, 0.40625, 0.5, 0.0, 0.5, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_cvt", "arith_sfu", "varying"], "shortest_path_cycles": [0.25, 0.234375, 0.25, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "total_cycles": [0.5, 0.265625, 0.453125, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_exclusion.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [6.599999904632568, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [3.9600000381469727, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [7.333333492279053, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_hardlight.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_hardlight.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.453125, 0.46875, 0.5, 0.0, 0.5, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma"], "shortest_path_cycles": [0.421875, 0.421875, 0.3125, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.515625, 0.453125, 0.515625, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 25}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_hardlight.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [7.590000152587891, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [4.949999809265137, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [8.333333015441895, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/advanced_blend_hue.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_hue.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": 86, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma"], "longest_path_cycles": [0.762499988079071, 0.762499988079071, 0.6875, 0.6875, 0.0, 0.5, 0.5], "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.515625, 0.328125, 0.515625, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.78125, 0.762499988079071, 0.78125, 0.6875, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_hue.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [11.880000114440918, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [6.269999980926514, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [13.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_lighten.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_lighten.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.171875, 0.4375, 0.5, 0.0, 0.5, 0.5], "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.28125, 0.140625, 0.28125, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "total_cycles": [0.5, 0.171875, 0.484375, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_lighten.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [5.940000057220459, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [3.299999952316284, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [6.666666507720947, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_luminosity.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_luminosity.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": 82, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma"], "longest_path_cycles": [0.65625, 0.65625, 0.53125, 0.625, 0.0, 0.5, 0.5], "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.375, 0.328125, 0.375, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_fma"], "total_cycles": [0.65625, 0.65625, 0.578125, 0.625, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_luminosity.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [9.899999618530273, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [5.940000057220459, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [11.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_multiply.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_multiply.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.203125, 0.40625, 0.5, 0.0, 0.5, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_cvt", "arith_sfu", "varying"], "shortest_path_cycles": [0.25, 0.171875, 0.25, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "total_cycles": [0.5, 0.203125, 0.453125, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_multiply.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [6.269999980926514, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [3.630000114440918, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [7.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_overlay.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_overlay.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.453125, 0.46875, 0.5, 0.0, 0.5, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma"], "shortest_path_cycles": [0.421875, 0.421875, 0.3125, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.515625, 0.453125, 0.515625, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 25}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_overlay.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [7.260000228881836, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [4.949999809265137, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [8.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/advanced_blend_saturation.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_saturation.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": 86, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma"], "longest_path_cycles": [0.762499988079071, 0.762499988079071, 0.6875, 0.6875, 0.0, 0.5, 0.5], "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.515625, 0.328125, 0.515625, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.78125, 0.762499988079071, 0.78125, 0.6875, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_saturation.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [12.210000038146973, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [6.599999904632568, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [13.333333015441895, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_screen.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_screen.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "longest_path_cycles": [0.5, 0.234375, 0.40625, 0.5, 0.0, 0.5, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_cvt", "arith_sfu", "varying"], "shortest_path_cycles": [0.25, 0.203125, 0.25, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "total_cycles": [0.5, 0.234375, 0.453125, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_screen.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [6.269999980926514, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [3.630000114440918, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [7.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_softlight.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_softlight.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma"], "longest_path_cycles": [0.71875, 0.71875, 0.609375, 0.6875, 0.0, 0.5, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma"], "shortest_path_cycles": [0.6875, 0.6875, 0.453125, 0.4375, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_fma"], "total_cycles": [0.71875, 0.71875, 0.65625, 0.6875, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_softlight.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [10.5600004196167, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [8.25, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [11.333333015441895, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/blend.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/blend.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["texture"], "longest_path_cycles": [0.09375, 0.046875, 0.09375, 0.0, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["texture"], "shortest_path_cycles": [0.0625, 0.046875, 0.0625, 0.0, 0.0, 0.125, 0.25], "total_bound_pipelines": ["texture"], "total_cycles": [0.09375, 0.046875, 0.09375, 0.0, 0.0, 0.125, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/blend.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic", "load_store", "texture"], "longest_path_cycles": [1.0, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 1.0, 1.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [1.3333333730697632, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/blend.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/blend.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/blend.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.640000104904175, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.640000104904175, 5.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [2.6666667461395264, 5.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/border_mask_blur.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/border_mask_blur.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": 10, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma"], "longest_path_cycles": [0.8125, 0.8125, 0.234375, 0.25, 0.0, 0.25, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma"], "shortest_path_cycles": [0.8125, 0.8125, 0.203125, 0.25, 0.0, 0.25, 0.25], "total_bound_pipelines": ["arith_total", "arith_fma"], "total_cycles": [0.8125, 0.8125, 0.234375, 0.25, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/border_mask_blur.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [8.90999984741211, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [8.90999984741211, 1.0, 1.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [9.333333015441895, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/border_mask_blur.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/border_mask_blur.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/border_mask_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 5.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 5.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma", "varying", "texture"], "longest_path_cycles": [0.25, 0.25, 0.09375, 0.0625, 0.0, 0.25, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma", "varying", "texture"], "shortest_path_cycles": [0.25, 0.25, 0.0625, 0.0625, 0.0, 0.25, 0.25], "total_bound_pipelines": ["arith_total", "arith_fma", "varying", "texture"], "total_cycles": [0.25, 0.25, 0.09375, 0.0625, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 14, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [2.640000104904175, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [2.640000104904175, 1.0, 1.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [3.0, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 3, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/gaussian_blur.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gaussian_blur.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": 76, "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": ["varying", "texture"], "shortest_path_cycles": [0.109375, 0.109375, 0.09375, 0.0625, 0.0, 0.25, 0.25], "total_bound_pipelines": ["varying", "texture"], "total_cycles": [0.3125, 0.3125, 0.21875, 0.125, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gaussian_blur.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"], "shortest_path_cycles": [2.9700000286102295, 2.0, 1.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [5.0, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 2, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/gaussian_blur.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gaussian_blur.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 8}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gaussian_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [3.299999952316284, 7.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [3.299999952316284, 7.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.3333332538604736, 7.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.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": 79, "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_sfu", "varying"], "shortest_path_cycles": [0.25, 0.109375, 0.1875, 0.25, 0.0, 0.25, 0.0], "total_bound_pipelines": ["arith_total", "arith_sfu", "varying", "texture"], "total_cycles": [0.5, 0.3125, 0.421875, 0.5, 0.0, 0.5, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.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"], "shortest_path_cycles": [4.289999961853027, 2.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [8.333333015441895, 2.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 2, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/glyph_atlas.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["varying"], "longest_path_cycles": [0.09375, 0.03125, 0.09375, 0.0, 0.0, 0.375, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["varying"], "shortest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 0.0, 0.375, 0.25], "total_bound_pipelines": ["varying"], "total_cycles": [0.09375, 0.03125, 0.09375, 0.0, 0.0, 0.375, 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/glyph_atlas.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic", "load_store", "texture"], "longest_path_cycles": [1.0, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 1.0, 1.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [1.3333333730697632, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/glyph_atlas.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 88, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.140625, 0.140625, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.140625, 0.140625, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.140625, 0.140625, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.0, 0.03125, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.0, 0.03125, 0.0, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.0, 0.03125, 0.0, 4.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 9}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/glyph_atlas.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 7.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 7.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 7.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 77, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma", "arith_sfu"], "longest_path_cycles": [0.3125, 0.3125, 0.046875, 0.3125, 0.0, 0.25, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma", "arith_sfu"], "shortest_path_cycles": [0.3125, 0.3125, 0.015625, 0.3125, 0.0, 0.25, 0.25], "total_bound_pipelines": ["arith_total", "arith_fma", "arith_sfu"], "total_cycles": [0.3125, 0.3125, 0.046875, 0.3125, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [3.299999952316284, 1.0, 3.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [3.299999952316284, 1.0, 3.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [3.6666667461395264, 1.0, 3.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 88, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.140625, 0.140625, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.140625, 0.140625, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.140625, 0.140625, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 5.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 5.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/gradient_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gradient_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 24, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.125, 0.125, 0.0, 0.0625, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 18, "work_registers_used": 9}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gradient_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [3.299999952316284, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [3.299999952316284, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.3333332538604736, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 5, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/linear_gradient_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/linear_gradient_fill.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": 70, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_cvt"], "longest_path_cycles": [0.40625, 0.28125, 0.40625, 0.125, 0.0, 0.125, 0.25], "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.1875, 0.171875, 0.1875, 0.125, 0.0, 0.125, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.484375, 0.3125, 0.484375, 0.125, 0.0, 0.125, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/linear_gradient_fill.frag.gles", "has_uniform_computation": true, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [6.929999828338623, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [2.309999942779541, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [7.666666507720947, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 40, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_cvt", "arith_sfu"], "longest_path_cycles": [0.4375, 0.328125, 0.4375, 0.4375, 0.0, 0.25, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_sfu"], "shortest_path_cycles": [0.4375, 0.328125, 0.40625, 0.4375, 0.0, 0.25, 0.25], "total_bound_pipelines": ["arith_total", "arith_cvt", "arith_sfu"], "total_cycles": [0.4375, 0.328125, 0.4375, 0.4375, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 30}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [4.949999809265137, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [4.949999809265137, 1.0, 1.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [5.333333492279053, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/morphology_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/morphology_filter.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": 83, "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.328125, 0.078125, 0.328125, 0.1875, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/morphology_filter.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"], "shortest_path_cycles": [1.9800000190734863, 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}}}}, "flutter/impeller/entity/gles/morphology_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/morphology_filter.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/morphology_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 5.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 5.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/position.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/position.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.0, 0.03125, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.0, 0.03125, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.0, 0.03125, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 5}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/position.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [2.6666667461395264, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/position_color.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/position_color.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/position_color.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.640000104904175, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.640000104904175, 5.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [2.6666667461395264, 5.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/position_uv.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/position_uv.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 20, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.125, 0.125, 0.0, 0.0625, 4.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 18, "work_registers_used": 10}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/position_uv.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [3.299999952316284, 6.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [3.299999952316284, 6.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.3333332538604736, 6.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/radial_gradient_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/radial_gradient_fill.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": 55, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_cvt"], "longest_path_cycles": [0.40625, 0.3125, 0.40625, 0.1875, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma"], "shortest_path_cycles": [0.203125, 0.203125, 0.1875, 0.1875, 0.0, 0.125, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.484375, 0.34375, 0.484375, 0.1875, 0.0, 0.125, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/radial_gradient_fill.frag.gles", "has_uniform_computation": true, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [6.929999828338623, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [2.309999942779541, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [7.666666507720947, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 2, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/rrect_blur.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/rrect_blur.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": 33, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_fma"], "longest_path_cycles": [1.5125000476837158, 1.5125000476837158, 0.546875, 1.5, 0.0, 0.125, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_fma"], "shortest_path_cycles": [0.203125, 0.203125, 0.046875, 0.0625, 0.0, 0.125, 0.0], "total_bound_pipelines": ["arith_total", "arith_fma"], "total_cycles": [1.6375000476837158, 1.6375000476837158, 0.578125, 1.5625, 0.0, 0.125, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 20, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/rrect_blur.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"], "shortest_path_cycles": [2.640000104904175, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [10.666666984558105, 1.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/rrect_blur.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/rrect_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/rrect_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [2.6666667461395264, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/runtime_effect.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/runtime_effect.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/runtime_effect.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [2.6666667461395264, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/solid_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/solid_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": null, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_cvt"], "longest_path_cycles": [0.0625, 0.0, 0.0625, 0.0, 0.0, 0.0, 0.0], "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.03125, 0.0, 0.03125, 0.0, 0.0, 0.0, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.0625, 0.0, 0.0625, 0.0, 0.0, 0.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 2, "work_registers_used": 18}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/solid_fill.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [1.0, 0.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [1.0, 0.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [0.6666666865348816, 0.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/solid_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/solid_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 14, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/solid_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.640000104904175, 3.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.640000104904175, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [2.6666667461395264, 3.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 40, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_cvt"], "longest_path_cycles": [0.484375, 0.328125, 0.484375, 0.4375, 0.0, 0.25, 0.25], "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.453125, 0.328125, 0.453125, 0.4375, 0.0, 0.25, 0.25], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.484375, 0.328125, 0.484375, 0.4375, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 28}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [4.949999809265137, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [4.949999809265137, 1.0, 1.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [5.333333492279053, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.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": 15, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_cvt"], "longest_path_cycles": [0.5, 0.453125, 0.5, 0.375, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["arith_total", "arith_sfu"], "shortest_path_cycles": [0.375, 0.34375, 0.28125, 0.375, 0.0, 0.125, 0.0], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.59375, 0.484375, 0.59375, 0.375, 0.0, 0.125, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 18, "work_registers_used": 24}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles", "has_uniform_computation": true, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [7.920000076293945, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [2.9700000286102295, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [8.666666984558105, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/texture_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/texture_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["varying", "texture"], "longest_path_cycles": [0.03125, 0.03125, 0.03125, 0.0, 0.0, 0.25, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["varying", "texture"], "shortest_path_cycles": [0.03125, 0.03125, 0.0, 0.0, 0.0, 0.25, 0.25], "total_bound_pipelines": ["varying", "texture"], "total_cycles": [0.03125, 0.03125, 0.03125, 0.0, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/texture_fill.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic", "load_store", "texture"], "longest_path_cycles": [1.0, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 1.0, 1.0], "total_bound_pipelines": ["load_store", "texture"], "total_cycles": [0.6666666865348816, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/texture_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/texture_fill.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/texture_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 5.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 5.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/tiled_texture_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.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": 33, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arith_total", "arith_cvt"], "longest_path_cycles": [0.265625, 0.03125, 0.265625, 0.0, 0.0, 0.25, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["varying", "texture"], "shortest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 0.0, 0.25, 0.25], "total_bound_pipelines": ["arith_total", "arith_cvt"], "total_cycles": [0.265625, 0.03125, 0.265625, 0.0, 0.0, 0.25, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [3.299999952316284, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [1.3200000524520874, 1.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [3.6666667461395264, 1.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 22, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.125, 0.125, 0.03125, 0.0625, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.125, 0.125, 0.03125, 0.0625, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.125, 0.125, 0.03125, 0.0625, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 8}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [3.9600000381469727, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [3.9600000381469727, 4.0, 0.0], "total_bound_pipelines": ["arithmetic", "load_store"], "total_cycles": [4.0, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 6, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/vertices.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/vertices.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["varying"], "longest_path_cycles": [0.03125, 0.03125, 0.03125, 0.0, 0.0, 0.25, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["varying"], "shortest_path_cycles": [0.03125, 0.03125, 0.0, 0.0, 0.0, 0.25, 0.0], "total_bound_pipelines": ["varying"], "total_cycles": [0.03125, 0.03125, 0.03125, 0.0, 0.0, 0.25, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 2, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/vertices.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic", "load_store"], "longest_path_cycles": [1.0, 1.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic", "load_store"], "shortest_path_cycles": [1.0, 1.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.6666666865348816, 1.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/yuv_to_rgb_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.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": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["texture"], "longest_path_cycles": [0.15625, 0.15625, 0.046875, 0.0, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["texture"], "shortest_path_cycles": [0.15625, 0.15625, 0.015625, 0.0, 0.0, 0.25, 0.5], "total_bound_pipelines": ["texture"], "total_cycles": [0.15625, 0.15625, 0.046875, 0.0, 0.0, 0.25, 0.5]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 12, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [2.309999942779541, 1.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["arithmetic"], "shortest_path_cycles": [2.309999942779541, 1.0, 2.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [2.6666667461395264, 1.0, 2.0]}, "thread_occupancy": 100, "uniform_registers_used": 3, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.03125, 0.015625, 0.03125, 0.0, 3.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 10, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [2.9700000286102295, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [2.9700000286102295, 4.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.0, 4.0, 0.0]}, "thread_occupancy": 100, "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/scene/shaders/gles/skinned.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/scene/shaders/gles/skinned.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 0, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store", "texture"], "longest_path_cycles": [3.075000047683716, 3.075000047683716, 0.09375, 0.0, 4.0, 4.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [1.2625000476837158, 1.2625000476837158, 0.296875, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store", "texture"], "total_cycles": [3.075000047683716, 3.075000047683716, 0.359375, 0.0, 4.0, 4.0]}, "stack_spill_bytes": 0, "thread_occupancy": 50, "uniform_registers_used": 30, "work_registers_used": 64}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [3.59375, 3.59375, 0.09375, 0.0, 13.0, 4.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [1.78125, 1.78125, 0.296875, 0.0, 11.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [3.59375, 3.59375, 0.359375, 0.0, 13.0, 4.0]}, "stack_spill_bytes": 0, "thread_occupancy": 50, "uniform_registers_used": 26, "work_registers_used": 64}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/scene/shaders/gles/skinned.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": true, "performance": {"longest_path_bound_pipelines": ["arithmetic"], "longest_path_cycles": [23.43000030517578, 17.0, 16.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [12.210000038146973, 13.0, 0.0], "total_bound_pipelines": ["arithmetic"], "total_cycles": [20.0, 17.0, 16.0]}, "thread_occupancy": 50, "uniform_registers_used": 7, "work_registers_used": 8}}}}, "flutter/impeller/scene/shaders/gles/unlit.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/scene/shaders/gles/unlit.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 0, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["varying"], "longest_path_cycles": [0.25, 0.25, 0.03125, 0.0, 0.0, 0.75, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_bound_pipelines": ["varying"], "shortest_path_cycles": [0.25, 0.25, 0.0, 0.0, 0.0, 0.75, 0.25], "total_bound_pipelines": ["varying"], "total_cycles": [0.25, 0.25, 0.03125, 0.0, 0.0, 0.75, 0.25]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 8, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/scene/shaders/gles/unlit.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [1.0, 2.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [1.0, 2.0, 1.0], "total_bound_pipelines": ["load_store"], "total_cycles": [1.3333333730697632, 2.0, 1.0]}, "thread_occupancy": 100, "uniform_registers_used": 2, "work_registers_used": 2}}}}, "flutter/impeller/scene/shaders/gles/unskinned.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/scene/shaders/gles/unskinned.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 0, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.265625, 0.265625, 0.0, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.265625, 0.265625, 0.0, 0.0, 2.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.265625, 0.265625, 0.0, 0.0, 2.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 24, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [0.75, 0.75, 0.0, 0.0, 11.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [0.75, 0.75, 0.0, 0.0, 11.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [0.75, 0.75, 0.0, 0.0, 11.0, 0.0]}, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 20, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/scene/shaders/gles/unskinned.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "performance": {"longest_path_bound_pipelines": ["load_store"], "longest_path_cycles": [5.28000020980835, 13.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_bound_pipelines": ["load_store"], "shortest_path_cycles": [5.28000020980835, 13.0, 0.0], "total_bound_pipelines": ["load_store"], "total_cycles": [5.333333492279053, 13.0, 0.0]}, "thread_occupancy": 50, "uniform_registers_used": 7, "work_registers_used": 6}}}}} \ No newline at end of file +{ + "flutter/impeller/entity/gles/advanced_blend.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 4.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 4.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 8 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 3.299999952316284, + 7.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 7.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.3333332538604736, + 7.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_color.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_color.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": 82, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "longest_path_cycles": [ + 0.65625, + 0.65625, + 0.53125, + 0.625, + 0.0, + 0.5, + 0.5 + ], + "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.375, + 0.328125, + 0.375, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "total_cycles": [ + 0.65625, + 0.65625, + 0.578125, + 0.625, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_color.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 9.899999618530273, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 5.940000057220459, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 11.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_colorburn.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_colorburn.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu" + ], + "longest_path_cycles": [ + 0.6875, + 0.265625, + 0.675000011920929, + 0.6875, + 0.0, + 0.5, + 0.5 + ], + "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.515625, + 0.234375, + 0.515625, + 0.4375, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.71875, + 0.265625, + 0.71875, + 0.6875, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 26 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_colorburn.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 10.5600004196167, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 8.25, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 11.333333015441895, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_colordodge.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_colordodge.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu" + ], + "longest_path_cycles": [ + 0.6875, + 0.234375, + 0.675000011920929, + 0.6875, + 0.0, + 0.5, + 0.5 + ], + "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.515625, + 0.203125, + 0.515625, + 0.4375, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.71875, + 0.234375, + 0.71875, + 0.6875, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 26 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_colordodge.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 10.229999542236328, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 7.920000076293945, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 11.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_darken.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_darken.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.171875, + 0.4375, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "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.28125, + 0.140625, + 0.28125, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "total_cycles": [ + 0.5, + 0.171875, + 0.484375, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_darken.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 5.940000057220459, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 6.666666507720947, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_difference.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_difference.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.203125, + 0.40625, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_cvt", + "arith_sfu", + "varying" + ], + "shortest_path_cycles": [ + 0.25, + 0.171875, + 0.25, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "total_cycles": [ + 0.5, + 0.203125, + 0.453125, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_difference.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 5.940000057220459, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 6.666666507720947, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_exclusion.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_exclusion.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.265625, + 0.40625, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_cvt", + "arith_sfu", + "varying" + ], + "shortest_path_cycles": [ + 0.25, + 0.234375, + 0.25, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "total_cycles": [ + 0.5, + 0.265625, + 0.453125, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_exclusion.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 6.599999904632568, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 3.9600000381469727, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 7.333333492279053, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_hardlight.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_hardlight.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.453125, + 0.46875, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "shortest_path_cycles": [ + 0.421875, + 0.421875, + 0.3125, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.515625, + 0.453125, + 0.515625, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 25 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_hardlight.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 7.590000152587891, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 4.949999809265137, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 8.333333015441895, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 4 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_hue.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_hue.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": 86, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "longest_path_cycles": [ + 0.762499988079071, + 0.762499988079071, + 0.6875, + 0.6875, + 0.0, + 0.5, + 0.5 + ], + "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.515625, + 0.328125, + 0.515625, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.78125, + 0.762499988079071, + 0.78125, + 0.6875, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_hue.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 11.880000114440918, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 6.269999980926514, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 13.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_lighten.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_lighten.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.171875, + 0.4375, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "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.28125, + 0.140625, + 0.28125, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "total_cycles": [ + 0.5, + 0.171875, + 0.484375, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_lighten.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 5.940000057220459, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 6.666666507720947, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_luminosity.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_luminosity.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": 82, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "longest_path_cycles": [ + 0.65625, + 0.65625, + 0.53125, + 0.625, + 0.0, + 0.5, + 0.5 + ], + "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.375, + 0.328125, + 0.375, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "total_cycles": [ + 0.65625, + 0.65625, + 0.578125, + 0.625, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_luminosity.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 9.899999618530273, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 5.940000057220459, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 11.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_multiply.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_multiply.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.203125, + 0.40625, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_cvt", + "arith_sfu", + "varying" + ], + "shortest_path_cycles": [ + 0.25, + 0.171875, + 0.25, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "total_cycles": [ + 0.5, + 0.203125, + 0.453125, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_multiply.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 6.269999980926514, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 3.630000114440918, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 7.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_overlay.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_overlay.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.453125, + 0.46875, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "shortest_path_cycles": [ + 0.421875, + 0.421875, + 0.3125, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.515625, + 0.453125, + 0.515625, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 25 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_overlay.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 7.260000228881836, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 4.949999809265137, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 8.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 4 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_saturation.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_saturation.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": 86, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "longest_path_cycles": [ + 0.762499988079071, + 0.762499988079071, + 0.6875, + 0.6875, + 0.0, + 0.5, + 0.5 + ], + "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.515625, + 0.328125, + 0.515625, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.78125, + 0.762499988079071, + 0.78125, + 0.6875, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_saturation.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 12.210000038146973, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 6.599999904632568, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 13.333333015441895, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_screen.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_screen.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.5, + 0.234375, + 0.40625, + 0.5, + 0.0, + 0.5, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_cvt", + "arith_sfu", + "varying" + ], + "shortest_path_cycles": [ + 0.25, + 0.203125, + 0.25, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "total_cycles": [ + 0.5, + 0.234375, + 0.453125, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_screen.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 6.269999980926514, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 3.630000114440918, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 7.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/advanced_blend_softlight.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/advanced_blend_softlight.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "longest_path_cycles": [ + 0.71875, + 0.71875, + 0.609375, + 0.6875, + 0.0, + 0.5, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "shortest_path_cycles": [ + 0.6875, + 0.6875, + 0.453125, + 0.4375, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "total_cycles": [ + 0.71875, + 0.71875, + 0.65625, + 0.6875, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 32 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/advanced_blend_softlight.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 10.5600004196167, + 2.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 8.25, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 11.333333015441895, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 4 + } + } + } + }, + "flutter/impeller/entity/gles/blend.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/blend.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "texture" + ], + "longest_path_cycles": [ + 0.09375, + 0.046875, + 0.09375, + 0.0, + 0.0, + 0.125, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "texture" + ], + "shortest_path_cycles": [ + 0.0625, + 0.046875, + 0.0625, + 0.0, + 0.0, + 0.125, + 0.25 + ], + "total_bound_pipelines": [ + "texture" + ], + "total_cycles": [ + 0.09375, + 0.046875, + 0.09375, + 0.0, + 0.0, + 0.125, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 19 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/blend.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "longest_path_cycles": [ + 1.0, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_cycles": [ + 1.0, + 1.0, + 1.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 1.3333333730697632, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/blend.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/blend.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 14, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": null, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 6 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/blend.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.640000104904175, + 5.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 2.6666667461395264, + 5.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/border_mask_blur.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/border_mask_blur.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": 10, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "longest_path_cycles": [ + 0.8125, + 0.8125, + 0.234375, + 0.25, + 0.0, + 0.25, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "shortest_path_cycles": [ + 0.8125, + 0.8125, + 0.203125, + 0.25, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "total_cycles": [ + 0.8125, + 0.8125, + 0.234375, + 0.25, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 32 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/border_mask_blur.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 8.90999984741211, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 8.90999984741211, + 1.0, + 1.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 9.333333015441895, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/border_mask_blur.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/border_mask_blur.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/border_mask_blur.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 5.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma", + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.25, + 0.25, + 0.09375, + 0.0625, + 0.0, + 0.25, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma", + "varying", + "texture" + ], + "shortest_path_cycles": [ + 0.25, + 0.25, + 0.0625, + 0.0625, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_fma", + "varying", + "texture" + ], + "total_cycles": [ + 0.25, + 0.25, + 0.09375, + 0.0625, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 14, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 2.640000104904175, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 1.0, + 1.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 3.0, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 3, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/gaussian_blur.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/gaussian_blur.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": 76, + "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": [ + "varying", + "texture" + ], + "shortest_path_cycles": [ + 0.109375, + 0.109375, + 0.09375, + 0.0625, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "varying", + "texture" + ], + "total_cycles": [ + 0.3125, + 0.3125, + 0.21875, + 0.125, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/gaussian_blur.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" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 2.0, + 1.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 5.0, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 2, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/gaussian_blur.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/gaussian_blur.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 4.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 4.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 8 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/gaussian_blur.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 3.299999952316284, + 7.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 7.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.3333332538604736, + 7.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.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": 79, + "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_sfu", + "varying" + ], + "shortest_path_cycles": [ + 0.25, + 0.109375, + 0.1875, + 0.25, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_sfu", + "varying", + "texture" + ], + "total_cycles": [ + 0.5, + 0.3125, + 0.421875, + 0.5, + 0.0, + 0.5, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.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" + ], + "shortest_path_cycles": [ + 4.289999961853027, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 8.333333015441895, + 2.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 2, + "work_registers_used": 4 + } + } + } + }, + "flutter/impeller/entity/gles/glyph_atlas.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/glyph_atlas.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "varying" + ], + "longest_path_cycles": [ + 0.09375, + 0.03125, + 0.09375, + 0.0, + 0.0, + 0.375, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "varying" + ], + "shortest_path_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 0.0, + 0.375, + 0.25 + ], + "total_bound_pipelines": [ + "varying" + ], + "total_cycles": [ + 0.09375, + 0.03125, + 0.09375, + 0.0, + 0.0, + 0.375, + 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/glyph_atlas.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "longest_path_cycles": [ + 1.0, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_cycles": [ + 1.0, + 1.0, + 1.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 1.3333333730697632, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/glyph_atlas.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/glyph_atlas.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 88, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.140625, + 0.140625, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.140625, + 0.140625, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.140625, + 0.140625, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": null, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.0, + 0.03125, + 0.0, + 4.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.0, + 0.03125, + 0.0, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.0, + 0.03125, + 0.0, + 4.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 9 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/glyph_atlas.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 7.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 7.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 7.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 77, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma", + "arith_sfu" + ], + "longest_path_cycles": [ + 0.3125, + 0.3125, + 0.046875, + 0.3125, + 0.0, + 0.25, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma", + "arith_sfu" + ], + "shortest_path_cycles": [ + 0.3125, + 0.3125, + 0.015625, + 0.3125, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_fma", + "arith_sfu" + ], + "total_cycles": [ + 0.3125, + 0.3125, + 0.046875, + 0.3125, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 3.299999952316284, + 1.0, + 3.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 1.0, + 3.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 3.6666667461395264, + 1.0, + 3.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 88, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.140625, + 0.140625, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.140625, + 0.140625, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.140625, + 0.140625, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": null, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 6 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 5.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/gradient_fill.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/gradient_fill.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 24, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.125, + 0.125, + 0.0, + 0.0625, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.125, + 0.125, + 0.0, + 0.0625, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.125, + 0.125, + 0.0, + 0.0625, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 18, + "work_registers_used": 9 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/gradient_fill.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 3.299999952316284, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.3333332538604736, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 5, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/linear_gradient_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/linear_gradient_fill.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": 70, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "longest_path_cycles": [ + 0.40625, + 0.28125, + 0.40625, + 0.125, + 0.0, + 0.125, + 0.25 + ], + "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.1875, + 0.171875, + 0.1875, + 0.125, + 0.0, + 0.125, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.484375, + 0.3125, + 0.484375, + 0.125, + 0.0, + 0.125, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/linear_gradient_fill.frag.gles", + "has_uniform_computation": true, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 6.929999828338623, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 2.309999942779541, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 7.666666507720947, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 40, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_cvt", + "arith_sfu" + ], + "longest_path_cycles": [ + 0.4375, + 0.328125, + 0.4375, + 0.4375, + 0.0, + 0.25, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_sfu" + ], + "shortest_path_cycles": [ + 0.4375, + 0.328125, + 0.40625, + 0.4375, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt", + "arith_sfu" + ], + "total_cycles": [ + 0.4375, + 0.328125, + 0.4375, + 0.4375, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 30 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 4.949999809265137, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 4.949999809265137, + 1.0, + 1.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 5.333333492279053, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/morphology_filter.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/morphology_filter.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": 83, + "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.328125, + 0.078125, + 0.328125, + 0.1875, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/morphology_filter.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" + ], + "shortest_path_cycles": [ + 1.9800000190734863, + 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 + } + } + } + }, + "flutter/impeller/entity/gles/morphology_filter.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/morphology_filter.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/morphology_filter.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 5.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/position_color.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/position_color.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 14, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": null, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/position_color.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.640000104904175, + 5.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 2.6666667461395264, + 5.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/position_uv.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/position_uv.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 20, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.125, + 0.125, + 0.0, + 0.0625, + 4.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.125, + 0.125, + 0.0, + 0.0625, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.125, + 0.125, + 0.0, + 0.0625, + 4.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 18, + "work_registers_used": 10 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/position_uv.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 3.299999952316284, + 6.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 3.299999952316284, + 6.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.3333332538604736, + 6.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/radial_gradient_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/radial_gradient_fill.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": 55, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "longest_path_cycles": [ + 0.40625, + 0.3125, + 0.40625, + 0.1875, + 0.0, + 0.125, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "shortest_path_cycles": [ + 0.203125, + 0.203125, + 0.1875, + 0.1875, + 0.0, + 0.125, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.484375, + 0.34375, + 0.484375, + 0.1875, + 0.0, + 0.125, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 20 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/radial_gradient_fill.frag.gles", + "has_uniform_computation": true, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 6.929999828338623, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 2.309999942779541, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 7.666666507720947, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 2, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/rrect_blur.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/rrect_blur.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": 33, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "longest_path_cycles": [ + 1.5125000476837158, + 1.5125000476837158, + 0.546875, + 1.5, + 0.0, + 0.125, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "shortest_path_cycles": [ + 0.203125, + 0.203125, + 0.046875, + 0.0625, + 0.0, + 0.125, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_fma" + ], + "total_cycles": [ + 1.6375000476837158, + 1.6375000476837158, + 0.578125, + 1.5625, + 0.0, + 0.125, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 20, + "work_registers_used": 32 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/rrect_blur.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" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 10.666666984558105, + 1.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 4 + } + } + } + }, + "flutter/impeller/entity/gles/rrect_blur.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/rrect_blur.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 14, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": null, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 6 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/rrect_blur.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.640000104904175, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 2.6666667461395264, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/runtime_effect.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/runtime_effect.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 14, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": null, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.0, + 0.0, + 0.0, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 6 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/runtime_effect.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.640000104904175, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 2.6666667461395264, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/solid_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/solid_fill.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": null, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "longest_path_cycles": [ + 0.0625, + 0.0, + 0.0625, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "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.03125, + 0.0, + 0.03125, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.0625, + 0.0, + 0.0625, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 2, + "work_registers_used": 18 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/solid_fill.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 1.0, + 0.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 1.0, + 0.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 0.6666666865348816, + 0.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/solid_fill.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/solid_fill.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 14, + "work_registers_used": 32 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/solid_fill.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.640000104904175, + 3.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 2.6666667461395264, + 3.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 40, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "longest_path_cycles": [ + 0.484375, + 0.328125, + 0.484375, + 0.4375, + 0.0, + 0.25, + 0.25 + ], + "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.453125, + 0.328125, + 0.453125, + 0.4375, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.484375, + 0.328125, + 0.484375, + 0.4375, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 28 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 4.949999809265137, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 4.949999809265137, + 1.0, + 1.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 5.333333492279053, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.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": 15, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "longest_path_cycles": [ + 0.5, + 0.453125, + 0.5, + 0.375, + 0.0, + 0.125, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arith_total", + "arith_sfu" + ], + "shortest_path_cycles": [ + 0.375, + 0.34375, + 0.28125, + 0.375, + 0.0, + 0.125, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.59375, + 0.484375, + 0.59375, + 0.375, + 0.0, + 0.125, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 18, + "work_registers_used": 24 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles", + "has_uniform_computation": true, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 7.920000076293945, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 8.666666984558105, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/texture_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/texture_fill.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "varying", + "texture" + ], + "longest_path_cycles": [ + 0.03125, + 0.03125, + 0.03125, + 0.0, + 0.0, + 0.25, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "varying", + "texture" + ], + "shortest_path_cycles": [ + 0.03125, + 0.03125, + 0.0, + 0.0, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "varying", + "texture" + ], + "total_cycles": [ + 0.03125, + 0.03125, + 0.03125, + 0.0, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 19 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/texture_fill.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "longest_path_cycles": [ + 1.0, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_cycles": [ + 1.0, + 1.0, + 1.0 + ], + "total_bound_pipelines": [ + "load_store", + "texture" + ], + "total_cycles": [ + 0.6666666865348816, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/texture_fill.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/texture_fill.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/texture_fill.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 5.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/tiled_texture_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/tiled_texture_fill.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": 33, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "longest_path_cycles": [ + 0.265625, + 0.03125, + 0.265625, + 0.0, + 0.0, + 0.25, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "varying", + "texture" + ], + "shortest_path_cycles": [ + 0.0625, + 0.03125, + 0.0625, + 0.0, + 0.0, + 0.25, + 0.25 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.265625, + 0.03125, + 0.265625, + 0.0, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 19 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/tiled_texture_fill.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 3.299999952316284, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 1.3200000524520874, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 3.6666667461395264, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 22, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.125, + 0.125, + 0.03125, + 0.0625, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.125, + 0.125, + 0.03125, + 0.0625, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.125, + 0.125, + 0.03125, + 0.0625, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 8 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 3.9600000381469727, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 3.9600000381469727, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic", + "load_store" + ], + "total_cycles": [ + 4.0, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 6, + "work_registers_used": 3 + } + } + } + }, + "flutter/impeller/entity/gles/vertices.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/vertices.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "varying" + ], + "longest_path_cycles": [ + 0.03125, + 0.03125, + 0.03125, + 0.0, + 0.0, + 0.25, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "varying" + ], + "shortest_path_cycles": [ + 0.03125, + 0.03125, + 0.0, + 0.0, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "varying" + ], + "total_cycles": [ + 0.03125, + 0.03125, + 0.03125, + 0.0, + 0.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 2, + "work_registers_used": 19 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/vertices.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic", + "load_store" + ], + "longest_path_cycles": [ + 1.0, + 1.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic", + "load_store" + ], + "shortest_path_cycles": [ + 1.0, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.6666666865348816, + 1.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/yuv_to_rgb_filter.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.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": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "texture" + ], + "longest_path_cycles": [ + 0.15625, + 0.15625, + 0.046875, + 0.0, + 0.0, + 0.25, + 0.5 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "texture" + ], + "shortest_path_cycles": [ + 0.15625, + 0.15625, + 0.015625, + 0.0, + 0.0, + 0.25, + 0.5 + ], + "total_bound_pipelines": [ + "texture" + ], + "total_cycles": [ + 0.15625, + 0.15625, + 0.046875, + 0.0, + 0.0, + 0.25, + 0.5 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 19 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 2.309999942779541, + 1.0, + 2.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 2.309999942779541, + 1.0, + 2.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 2.6666667461395264, + 1.0, + 2.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 3, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 80, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.078125, + 0.078125, + 0.046875, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 16, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 100, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.03125, + 0.015625, + 0.03125, + 0.0, + 3.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 7 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 4.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.0, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/scene/shaders/gles/skinned.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/scene/shaders/gles/skinned.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store", + "texture" + ], + "longest_path_cycles": [ + 3.075000047683716, + 3.075000047683716, + 0.09375, + 0.0, + 4.0, + 4.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 1.2625000476837158, + 1.2625000476837158, + 0.296875, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store", + "texture" + ], + "total_cycles": [ + 3.075000047683716, + 3.075000047683716, + 0.359375, + 0.0, + 4.0, + 4.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 50, + "uniform_registers_used": 30, + "work_registers_used": 64 + }, + "Varying": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 3.59375, + 3.59375, + 0.09375, + 0.0, + 13.0, + 4.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 1.78125, + 1.78125, + 0.296875, + 0.0, + 11.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 3.59375, + 3.59375, + 0.359375, + 0.0, + 13.0, + 4.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 50, + "uniform_registers_used": 26, + "work_registers_used": 64 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/scene/shaders/gles/skinned.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": true, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 23.43000030517578, + 17.0, + 16.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 12.210000038146973, + 13.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 20.0, + 17.0, + 16.0 + ] + }, + "thread_occupancy": 50, + "uniform_registers_used": 7, + "work_registers_used": 8 + } + } + } + }, + "flutter/impeller/scene/shaders/gles/unlit.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/scene/shaders/gles/unlit.frag.gles", + "has_side_effects": false, + "has_uniform_computation": false, + "modifies_coverage": false, + "reads_color_buffer": false, + "type": "Fragment", + "uses_late_zs_test": false, + "uses_late_zs_update": false, + "variants": { + "Main": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "varying" + ], + "longest_path_cycles": [ + 0.25, + 0.25, + 0.03125, + 0.0, + 0.0, + 0.75, + 0.25 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "varying", + "texture" + ], + "shortest_path_bound_pipelines": [ + "varying" + ], + "shortest_path_cycles": [ + 0.25, + 0.25, + 0.0, + 0.0, + 0.0, + 0.75, + 0.25 + ], + "total_bound_pipelines": [ + "varying" + ], + "total_cycles": [ + 0.25, + 0.25, + 0.03125, + 0.0, + 0.0, + 0.75, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 8, + "work_registers_used": 19 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/scene/shaders/gles/unlit.frag.gles", + "has_uniform_computation": false, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 1.0, + 2.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 1.0, + 2.0, + 1.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 1.3333333730697632, + 2.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 2, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/scene/shaders/gles/unskinned.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/scene/shaders/gles/unskinned.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.265625, + 0.265625, + 0.0, + 0.0, + 2.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.265625, + 0.265625, + 0.0, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.265625, + 0.265625, + 0.0, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 24, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.75, + 0.75, + 0.0, + 0.0, + 11.0, + 0.0 + ], + "pipelines": [ + "arith_total", + "arith_fma", + "arith_cvt", + "arith_sfu", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 0.75, + 0.75, + 0.0, + 0.0, + 11.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.75, + 0.75, + 0.0, + 0.0, + 11.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 20, + "work_registers_used": 32 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/scene/shaders/gles/unskinned.vert.gles", + "has_uniform_computation": false, + "type": "Vertex", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 5.28000020980835, + 13.0, + 0.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "load_store" + ], + "shortest_path_cycles": [ + 5.28000020980835, + 13.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 5.333333492279053, + 13.0, + 0.0 + ] + }, + "thread_occupancy": 50, + "uniform_registers_used": 7, + "work_registers_used": 6 + } + } + } + } +} \ No newline at end of file diff --git a/impeller/tools/malioc_diff.py b/impeller/tools/malioc_diff.py index b861ed381e069..309d8bd2e607f 100755 --- a/impeller/tools/malioc_diff.py +++ b/impeller/tools/malioc_diff.py @@ -119,6 +119,8 @@ def read_malioc_file(malioc_tree, json_file): filename = os.path.relpath(shader['filename'], build_gen_dir) if filename.startswith('../..'): filename = filename[6:] + if filename.startswith('../'): + filename = filename[3:] result['filename'] = filename result['core'] = shader['hardware']['core'] result['type'] = shader['shader']['type'] @@ -266,7 +268,7 @@ def main(argv): if args.update: # Write the new results to the file given by --before, then exit. with open(args.before, 'w') as file: - json.dump(after_json, file, sort_keys=True) + json.dump(after_json, file, sort_keys=True, indent=2) return 0 with open(args.before, 'r') as file: From c99baf29c33d5bebbea51b13e6d0431b1222aa99 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Fri, 10 Mar 2023 14:32:52 -0800 Subject: [PATCH 02/16] Roll Fuchsia Linux SDK to 12.20230309.0.1 (#40231) Roll Fuchsia Linux SDK to 12.20230309.0.1 --- DEPS | 2 +- ci/licenses_golden/licenses_fuchsia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 39c920f96e589..82046ca3f09eb 100644 --- a/DEPS +++ b/DEPS @@ -842,7 +842,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': '2R3ybztMdyKjvEdPR-vchKcZhjxosgkdGCod1t8MApUC' + 'version': 'VFZ_BtgLOf7FaEr6XYKW1wXqPuy7nQFMxd3P6-d9XwgC' } ], 'condition': 'host_os == "linux" and not download_fuchsia_sdk', diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index 85e150581bcdf..081306f66cc24 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: 3b439c79749ab1a71ef2b21c0b2018f1 +Signature: 943c8628754a36c980fd63c32c301539 ==================================================================================================== LIBRARY: fuchsia_sdk From 220e867d787668123b9938eda1d1a44f203946c1 Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Fri, 10 Mar 2023 14:38:58 -0800 Subject: [PATCH 03/16] Roll buildroot to 287917d342224d34d6fbdf863aee8417a5f2e8b8 (#40232) To pick up https://github.com/flutter/buildroot/pull/691 --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index 82046ca3f09eb..f064af73717e9 100644 --- a/DEPS +++ b/DEPS @@ -239,7 +239,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + 'a357fb6285af70772dbca8b164cd61af16cc8af1', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + '287917d342224d34d6fbdf863aee8417a5f2e8b8', # Fuchsia compatibility # From 3018843dc50c2b778ebbec19991735393e83411f Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Fri, 10 Mar 2023 17:44:48 -0500 Subject: [PATCH 04/16] Manual roll Dart SDK from 7240b35cc401 to c766fffb626e (9 revisions) (#40233) Manual roll requested by asiva@google.com https://dart.googlesource.com/sdk.git/+log/7240b35cc401..c766fffb626e 2023-03-10 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-322.0.dev 2023-03-10 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-321.0.dev 2023-03-10 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-320.0.dev 2023-03-10 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-319.0.dev 2023-03-09 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-318.0.dev 2023-03-09 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-317.0.dev 2023-03-09 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-316.0.dev 2023-03-09 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-315.0.dev 2023-03-09 dart-internal-merge@dart-ci-internal.iam.gserviceaccount.com Version 3.0.0-314.0.dev If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/dart-sdk-flutter-engine Please CC aam@google.com,asiva@google.com,dart-vm-team@google.com,jimgraham@google.com,rmistry@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter Engine: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md --- DEPS | 14 +++++++------- ci/licenses_golden/licenses_third_party | 2 +- sky/packages/sky_engine/LICENSE | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/DEPS b/DEPS index f064af73717e9..021b1f8f3309f 100644 --- a/DEPS +++ b/DEPS @@ -48,7 +48,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '7240b35cc401ad8cf3107e83c04b055ef3cc895d', + 'dart_revision': 'c766fffb626ecac3be237703d4c68178f308e5f3', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py @@ -61,14 +61,14 @@ vars = { 'dart_devtools_rev': 'bf15e7348d53dc83531d503be94e0c035b604984', 'dart_libprotobuf_rev': '24487dd1045c7f3d64a21f38a3f0c06cc4cf2edb', 'dart_perfetto_rev': 'b8da07095979310818f0efde2ef3c69ea70d62c5', - 'dart_protobuf_gn_rev': '5f87ef9990fc4f4ffd76b3f5b0138562178db8bc', + 'dart_protobuf_gn_rev': 'f872f05cb0378eef9a7a2609076929f0f35b4141', 'dart_protobuf_rev': '75bc380a6e9601565606a13dee16c5ab2bf5019c', 'dart_pub_rev': '048e3ad2b5e1b4ebe6883addbc95722be6904a7b', 'dart_root_certificates_rev': '692f6d6488af68e0121317a9c2c9eb393eb0ee50', 'dart_watcher_rev': '5968409e1d73e21e75fc22a6481d5efaef7f3558', - 'dart_webdev_rev': 'c007560346a53728920362e5ccaa7eaae85301a7', + 'dart_webdev_rev': 'cfe97534b33d37c7e0bbac2a3576085f74f2eaa3', 'dart_webkit_inspection_protocol_rev': '8401098ace995e4dcd9855a2741c2dacccaa780b', - 'dart_yaml_edit_rev': '998eea2e4fc474a5e95cfea117e4233d35c3069b', + 'dart_yaml_edit_rev': '6abc42a74b76700ad02fa1c1ebd94951b62626b9', 'dart_zlib_rev': '27c2f474b71d0d20764f86f60ef8b00da1a16cda', 'ocmock_rev': 'c4ec0e3a7a9f56cfdbd0aa01f4f97bb4b75c5ef8', # v3.7.1 @@ -449,13 +449,13 @@ deps = { Var('dart_git') + '/term_glyph.git@d275a8f7482b6a5e4f15d0da6feb66c24f52eb94', 'src/third_party/dart/third_party/pkg/test': - Var('dart_git') + '/test.git@92da93a83615f2bc0483aa00e6a85c4f89d616e4', + Var('dart_git') + '/test.git@3ba78f15538399073d0b5aba4ec19b1378af1625', 'src/third_party/dart/third_party/pkg/test_reflective_loader': Var('dart_git') + '/test_reflective_loader.git@c4c2d5c3f94a96f3fc79e9e28944fba391bc544c', 'src/third_party/dart/third_party/pkg/tools': - Var('dart_git') + '/tools.git@a1c35060d920122ecbecb8c5a389b58ccbceb125', + Var('dart_git') + '/tools.git@bed358ea8ca10551c710282be96cf6e95620fb24', 'src/third_party/dart/third_party/pkg/typed_data': Var('dart_git') + '/typed_data.git@f858046fb420cf644e7d8cb86b7893f2830d8a6c', @@ -476,7 +476,7 @@ deps = { Var('dart_git') + '/external/github.com/google/webkit_inspection_protocol.dart.git' + '@' + Var('dart_webkit_inspection_protocol_rev'), 'src/third_party/dart/third_party/pkg/yaml': - Var('dart_git') + '/yaml.git@a6d8781744d34c391368664b4c1e174f0433bbb6', + Var('dart_git') + '/yaml.git@0f80b12978f066b3547632dec4a273649138fae4', 'src/third_party/dart/third_party/pkg/yaml_edit': Var('dart_git') + '/yaml_edit.git' + '@' + Var('dart_yaml_edit_rev'), diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party index 8b25e72097fff..94f0ab6c3d2a8 100644 --- a/ci/licenses_golden/licenses_third_party +++ b/ci/licenses_golden/licenses_third_party @@ -1,4 +1,4 @@ -Signature: 479841c56f2e6285f5971d095ed2306c +Signature: 2959cbbbe19ce6fbee5f838b9de1f204 ==================================================================================================== LIBRARY: angle diff --git a/sky/packages/sky_engine/LICENSE b/sky/packages/sky_engine/LICENSE index 7cf2b9fd55629..d7a37ca940523 100644 --- a/sky/packages/sky_engine/LICENSE +++ b/sky/packages/sky_engine/LICENSE @@ -25614,6 +25614,7 @@ engine spring_animation tonic txt +web_sdk_version web_test_fonts web_unicode From 12f2fdff743a56ced0557c042c29d617af398873 Mon Sep 17 00:00:00 2001 From: Yegor Date: Fri, 10 Mar 2023 14:46:06 -0800 Subject: [PATCH 05/16] Revert "[web] Access engine version to get correct gstatic URL (#40194)" (#40235) This reverts commit 161f75931834b79ec9f700046c4d3fe748a7a60b. --- ci/licenses_golden/excluded_files | 1 - ci/licenses_golden/licenses_flutter | 5 --- lib/web_ui/lib/src/engine/configuration.dart | 9 ++-- lib/web_ui/pubspec.yaml | 3 -- third_party/web_sdk_version/BUILD.gn | 43 ------------------- .../web_sdk_version/lib/web_sdk_version.dart | 7 --- .../lib/web_sdk_version/web_sdk_version.dart | 10 ----- third_party/web_sdk_version/pubspec.yaml | 6 --- web_sdk/BUILD.gn | 12 ------ web_sdk/libraries.json | 9 ---- web_sdk/libraries.yaml | 9 ---- web_sdk/sdk_rewriter.dart | 1 - web_sdk/test/sdk_rewriter_test.dart | 4 -- 13 files changed, 6 insertions(+), 113 deletions(-) delete mode 100644 third_party/web_sdk_version/BUILD.gn delete mode 100644 third_party/web_sdk_version/lib/web_sdk_version.dart delete mode 100644 third_party/web_sdk_version/lib/web_sdk_version/web_sdk_version.dart delete mode 100644 third_party/web_sdk_version/pubspec.yaml diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index 717861a002dd6..2d0dbbe4c1f55 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -408,7 +408,6 @@ ../../../flutter/third_party/web_locale_keymap/README.md ../../../flutter/third_party/web_locale_keymap/pubspec.yaml ../../../flutter/third_party/web_locale_keymap/test -../../../flutter/third_party/web_sdk_version/pubspec.yaml ../../../flutter/third_party/web_test_fonts/pubspec.yaml ../../../flutter/third_party/web_unicode/README.md ../../../flutter/third_party/web_unicode/pubspec.yaml diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 85d675e57dca5..0d4ce0443790b 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -680,7 +680,6 @@ LIBRARY: engine LIBRARY: spring_animation LIBRARY: tonic LIBRARY: txt -LIBRARY: web_sdk_version LIBRARY: web_test_fonts LIBRARY: web_unicode ORIGIN: ../../../flutter/LICENSE @@ -3168,8 +3167,6 @@ ORIGIN: ../../../flutter/third_party/txt/src/txt/platform_fuchsia.cc + ../../../ ORIGIN: ../../../flutter/third_party/txt/src/txt/platform_linux.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/txt/src/txt/platform_mac.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/txt/src/txt/platform_windows.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/third_party/web_sdk_version/lib/web_sdk_version.dart + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/third_party/web_sdk_version/lib/web_sdk_version/web_sdk_version.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/web_test_fonts/lib/web_test_fonts.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/web_test_fonts/lib/web_test_fonts/web_test_fonts.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/web_unicode/lib/web_unicode.dart + ../../../flutter/LICENSE @@ -5718,8 +5715,6 @@ FILE: ../../../flutter/third_party/txt/src/txt/platform_fuchsia.cc FILE: ../../../flutter/third_party/txt/src/txt/platform_linux.cc FILE: ../../../flutter/third_party/txt/src/txt/platform_mac.mm FILE: ../../../flutter/third_party/txt/src/txt/platform_windows.cc -FILE: ../../../flutter/third_party/web_sdk_version/lib/web_sdk_version.dart -FILE: ../../../flutter/third_party/web_sdk_version/lib/web_sdk_version/web_sdk_version.dart FILE: ../../../flutter/third_party/web_test_fonts/lib/web_test_fonts.dart FILE: ../../../flutter/third_party/web_test_fonts/lib/web_test_fonts/web_test_fonts.dart FILE: ../../../flutter/third_party/web_unicode/lib/web_unicode.dart diff --git a/lib/web_ui/lib/src/engine/configuration.dart b/lib/web_ui/lib/src/engine/configuration.dart index 1307073277d44..e153286f711f8 100644 --- a/lib/web_ui/lib/src/engine/configuration.dart +++ b/lib/web_ui/lib/src/engine/configuration.dart @@ -46,11 +46,14 @@ library configuration; import 'package:js/js.dart'; import 'package:meta/meta.dart'; -import 'package:web_sdk_version/web_sdk_version.dart'; - import 'canvaskit/renderer.dart'; import 'dom.dart'; +/// The version of CanvasKit used by the web engine by default. +// DO NOT EDIT THE NEXT LINE OF CODE MANUALLY +// See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. +const String _canvaskitVersion = '0.38.0'; + /// The Web Engine configuration for the current application. FlutterConfiguration get configuration => _configuration ??= FlutterConfiguration.legacy(_jsConfiguration); @@ -179,7 +182,7 @@ class FlutterConfiguration { String get canvasKitBaseUrl => _configuration?.canvasKitBaseUrl ?? _defaultCanvasKitBaseUrl; static const String _defaultCanvasKitBaseUrl = String.fromEnvironment( 'FLUTTER_WEB_CANVASKIT_URL', - defaultValue: 'https://gstatic.com/flutter-canvaskit/$flutterWebSdkVersion/' + defaultValue: 'https://unpkg.com/canvaskit-wasm@$_canvaskitVersion/bin/', ); /// The variant of CanvasKit to download. diff --git a/lib/web_ui/pubspec.yaml b/lib/web_ui/pubspec.yaml index f3f239f86e55c..f35dafac5ca0f 100644 --- a/lib/web_ui/pubspec.yaml +++ b/lib/web_ui/pubspec.yaml @@ -17,9 +17,6 @@ dependencies: web_test_fonts: path: ../../third_party/web_test_fonts - web_sdk_version: - path: ../../third_party/web_sdk_version - dev_dependencies: analyzer: 5.2.0 archive: 3.1.2 diff --git a/third_party/web_sdk_version/BUILD.gn b/third_party/web_sdk_version/BUILD.gn deleted file mode 100644 index 5cb367593894b..0000000000000 --- a/third_party/web_sdk_version/BUILD.gn +++ /dev/null @@ -1,43 +0,0 @@ -import("//flutter/shell/version.gni") -import("//third_party/dart/build/dart/dart_action.gni") - -dart_sdk_package_config = "//third_party/dart/.dart_tool/package_config.json" - -prebuilt_dart_action("web_sdk_version") { - packages = dart_sdk_package_config - pool = "//flutter/build/dart:dart_pool" - - script = "version_writer.dart" - inputs = [ "version_writer.dart" ] - - stamp_location = "$target_gen_dir/$target_name.stamp" - outputs = [ - stamp_location, - invoker.output_dir, - ] - - input_dir = rebase_path(invoker.input_dir) - output_dir = rebase_path(invoker.output_dir) - - args = [ - "--output-dir=$output_dir", - "--input-dir=$input_dir", - "--stamp", - rebase_path(stamp_location, root_build_dir), - ] - if (ui) { - args += [ "--ui" ] - } else { - library_name = invoker.library_name - api_file = rebase_path(invoker.api_file) - args += [ - "--library-name=$library_name", - "--api-file=$api_file", - ] - } - - foreach(source_file, source_dart_files) { - path = rebase_path(source_file) - args += [ "--source-file=$path" ] - } -} diff --git a/third_party/web_sdk_version/lib/web_sdk_version.dart b/third_party/web_sdk_version/lib/web_sdk_version.dart deleted file mode 100644 index fe6c9c5ebe5e0..0000000000000 --- a/third_party/web_sdk_version/lib/web_sdk_version.dart +++ /dev/null @@ -1,7 +0,0 @@ -// 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. - -library web_sdk_version; - -export 'web_sdk_version/web_sdk_version.dart'; diff --git a/third_party/web_sdk_version/lib/web_sdk_version/web_sdk_version.dart b/third_party/web_sdk_version/lib/web_sdk_version/web_sdk_version.dart deleted file mode 100644 index b4b52c57d5ab9..0000000000000 --- a/third_party/web_sdk_version/lib/web_sdk_version/web_sdk_version.dart +++ /dev/null @@ -1,10 +0,0 @@ -// 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. - -// NOTE: This file is just a stub. The actual file is generated at build time -// with the actual current Git commit SHA. This stub is just here for local -// development. - -/// The Git SHA of the Flutter Engine. -const String flutterWebSdkVersion = 'IF YOU SEE THIS, FILE A BUG: https://github.com/flutter/flutter/issues/new?assignees=&labels=&template=2_bug.md&title='; diff --git a/third_party/web_sdk_version/pubspec.yaml b/third_party/web_sdk_version/pubspec.yaml deleted file mode 100644 index 102ae4aef7f27..0000000000000 --- a/third_party/web_sdk_version/pubspec.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: web_sdk_version - -publish_to: none - -environment: - sdk: ">=2.12.0-0 <3.0.0" diff --git a/web_sdk/BUILD.gn b/web_sdk/BUILD.gn index 86931fd239b29..957510f08ef93 100644 --- a/web_sdk/BUILD.gn +++ b/web_sdk/BUILD.gn @@ -4,7 +4,6 @@ import("//flutter/build/zip_bundle.gni") import("//flutter/common/config.gni") -import("//flutter/shell/version/version.gni") import("//third_party/dart/build/dart/dart_action.gni") dart_sdk_package_config = "//third_party/dart/.dart_tool/package_config.json" @@ -25,7 +24,6 @@ web_engine_libraries = [ ":web_unicode_library", ":web_test_fonts_library", ":web_locale_keymap_library", - ":web_sdk_version_library", ] group("web_sdk") { @@ -153,14 +151,6 @@ sdk_rewriter("web_locale_keymap_library") { output_dir = "$root_out_dir/flutter_web_sdk/lib/_web_locale_keymap/" } -generated_file("web_sdk_version_library") { - outputs = [ - "$root_out_dir/flutter_web_sdk/lib/_web_sdk_version/web_sdk_version.dart", - ] - - contents = "// Copyright 2013 The Flutter Authors. All rights reserved.$0x0A// Use of this source code is governed by a BSD-style license that can be$0x0A// found in the LICENSE file.$0x0A$0x0A@JS()$0x0Alibrary dart._web_sdk_version;$0x0A$0x0Aimport 'dart:_js_annotations';$0x0A$0x0Aconst String flutterWebSdkVersion = '$engine_version';$0x0A" -} - copy("web_ui_library") { sources = [ "//flutter/web_sdk/libraries.json" ] @@ -324,8 +314,6 @@ template("_compile_platform") { "dart:_web_unicode", "--source", "dart:_web_locale_keymap", - "--source", - "dart:_web_sdk_version", ] if (flutter_prebuilt_dart_sdk) { args += [ diff --git a/web_sdk/libraries.json b/web_sdk/libraries.json index 66e04eb053801..b55cd2bac65eb 100644 --- a/web_sdk/libraries.json +++ b/web_sdk/libraries.json @@ -26,9 +26,6 @@ }, "_web_test_fonts": { "uri": "lib/_web_test_fonts/web_test_fonts.dart" - }, - "_web_sdk_version": { - "uri": "lib/_web_sdk_version/web_sdk_version.dart" } } }, @@ -57,9 +54,6 @@ }, "_web_test_fonts": { "uri": "lib/_web_test_fonts/web_test_fonts.dart" - }, - "_web_sdk_version": { - "uri": "lib/_web_sdk_version/web_sdk_version.dart" } } }, @@ -88,9 +82,6 @@ }, "_web_test_fonts": { "uri": "lib/_web_test_fonts/web_test_fonts.dart" - }, - "_web_sdk_version": { - "uri": "lib/_web_sdk_version/web_sdk_version.dart" } } } diff --git a/web_sdk/libraries.yaml b/web_sdk/libraries.yaml index 765068efde506..d447436aea738 100644 --- a/web_sdk/libraries.yaml +++ b/web_sdk/libraries.yaml @@ -36,9 +36,6 @@ dartdevc: _web_test_fonts: uri: "lib/_web_test_fonts/web_test_fonts.dart" - _web_sdk_version: - uri: "lib/_web_sdk_version/web_sdk_version.dart" - dart2js: include: - {path: "../dart-sdk/lib/libraries.json", target: dart2js} @@ -62,9 +59,6 @@ dart2js: _web_test_fonts: uri: "lib/_web_test_fonts/web_test_fonts.dart" - _web_sdk_version: - uri: "lib/_web_sdk_version/web_sdk_version.dart" - wasm: include: - {path: "../dart-sdk/lib/libraries.json", target: wasm} @@ -87,6 +81,3 @@ wasm: _web_test_fonts: uri: "lib/_web_test_fonts/web_test_fonts.dart" - - _web_sdk_version: - uri: "lib/_web_sdk_version/web_sdk_version.dart" diff --git a/web_sdk/sdk_rewriter.dart b/web_sdk/sdk_rewriter.dart index 421fd037b81c8..77339f913667f 100644 --- a/web_sdk/sdk_rewriter.dart +++ b/web_sdk/sdk_rewriter.dart @@ -96,7 +96,6 @@ final Map extraImportsMap = { 'web_unicode': "import 'dart:_web_unicode';", 'web_test_fonts': "import 'dart:_web_test_fonts';", 'web_locale_keymap': "import 'dart:_web_locale_keymap' as locale_keymap;", - 'web_sdk_version': "import 'dart:_web_sdk_version';", }; // Rewrites the "package"-style web ui library into a dart:ui implementation. diff --git a/web_sdk/test/sdk_rewriter_test.dart b/web_sdk/test/sdk_rewriter_test.dart index fc65627ff0532..5602bb5679f41 100644 --- a/web_sdk/test/sdk_rewriter_test.dart +++ b/web_sdk/test/sdk_rewriter_test.dart @@ -132,21 +132,18 @@ void printSomething() { "import 'dart:_web_unicode';", "import 'dart:_web_test_fonts';", "import 'dart:_web_locale_keymap' as locale_keymap;", - "import 'dart:_web_sdk_version';", ]); expect(getExtraImportsForLibrary('skwasm_stub'), [ "import 'dart:_engine';", "import 'dart:_web_unicode';", "import 'dart:_web_test_fonts';", "import 'dart:_web_locale_keymap' as locale_keymap;", - "import 'dart:_web_sdk_version';", ]); expect(getExtraImportsForLibrary('skwasm_impl'), [ "import 'dart:_engine';", "import 'dart:_web_unicode';", "import 'dart:_web_test_fonts';", "import 'dart:_web_locale_keymap' as locale_keymap;", - "import 'dart:_web_sdk_version';", "import 'dart:ffi';", ]); @@ -154,6 +151,5 @@ void printSomething() { expect(getExtraImportsForLibrary('web_unicode'), isEmpty); expect(getExtraImportsForLibrary('web_test_fonts'), isEmpty); expect(getExtraImportsForLibrary('web_locale_keymap'), isEmpty); - expect(getExtraImportsForLibrary('web_sdk_version'), isEmpty); }); } From 7f250234104ae74bd36115780d5fca012d15ee6c Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Fri, 10 Mar 2023 15:42:18 -0800 Subject: [PATCH 06/16] Revert "Make FlutterTest the default test font (#40188)" (#40237) This reverts commit 9270e3de510eaee878920ffb0542fc78d2cdc9aa. --- .../lib/src/engine/canvaskit/fonts.dart | 9 +++------ .../lib/src/engine/text/font_collection.dart | 6 +++--- .../canvaskit/skia_font_collection_test.dart | 9 --------- runtime/test_font_data.cc | 6 +++--- testing/dart/canvas_test.dart | 1 - testing/dart/paragraph_builder_test.dart | 19 +++++++++++-------- 6 files changed, 20 insertions(+), 30 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/fonts.dart b/lib/web_ui/lib/src/engine/canvaskit/fonts.dart index 234d7908b99e6..84475d4f82a28 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/fonts.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/fonts.dart @@ -184,15 +184,12 @@ class SkiaFontCollection implements FontCollection { } } final List completedPendingFonts = await Future.wait(pendingFonts); - final List fonts = [ - UnregisteredFont( + completedPendingFonts.add(UnregisteredFont( EmbeddedTestFont.flutterTest.data.buffer, '', EmbeddedTestFont.flutterTest.fontFamily, - ), - ...completedPendingFonts.whereType(), - ]; - _unregisteredFonts.addAll(fonts); + )); + _unregisteredFonts.addAll(completedPendingFonts.whereType()); // Ahem must be added to font fallbacks list regardless of where it was // downloaded from. diff --git a/lib/web_ui/lib/src/engine/text/font_collection.dart b/lib/web_ui/lib/src/engine/text/font_collection.dart index 3865deb3343ea..7c863d5e87c2e 100644 --- a/lib/web_ui/lib/src/engine/text/font_collection.dart +++ b/lib/web_ui/lib/src/engine/text/font_collection.dart @@ -76,13 +76,13 @@ class HtmlFontCollection implements FontCollection { @override Future debugDownloadTestFonts() async { final FontManager fontManager = _testFontManager = FontManager(); + for (final MapEntry fontEntry in testFontUrls.entries) { + fontManager.downloadAsset(fontEntry.key, 'url(${fontEntry.value})', const {}); + } fontManager._downloadedFonts.add(createDomFontFace( EmbeddedTestFont.flutterTest.fontFamily, EmbeddedTestFont.flutterTest.data, )); - for (final MapEntry fontEntry in testFontUrls.entries) { - fontManager.downloadAsset(fontEntry.key, 'url(${fontEntry.value})', const {}); - } await fontManager.downloadAllFonts(); } diff --git a/lib/web_ui/test/canvaskit/skia_font_collection_test.dart b/lib/web_ui/test/canvaskit/skia_font_collection_test.dart index 75764a8c35f4f..2650e586fa864 100644 --- a/lib/web_ui/test/canvaskit/skia_font_collection_test.dart +++ b/lib/web_ui/test/canvaskit/skia_font_collection_test.dart @@ -181,14 +181,5 @@ void testMain() { expect(fontCollection.debugRegisteredFonts, isNotEmpty); expect(warnings, isEmpty); }); - - test('FlutterTest is the default test font', () async { - final SkiaFontCollection fontCollection = SkiaFontCollection(); - - await fontCollection.debugDownloadTestFonts(); - fontCollection.registerDownloadedFonts(); - expect(fontCollection.debugRegisteredFonts, isNotEmpty); - expect(fontCollection.debugRegisteredFonts!.first.family, 'FlutterTest'); - }); }); } diff --git a/runtime/test_font_data.cc b/runtime/test_font_data.cc index 9389079a8bbd1..9f86698dab1f1 100644 --- a/runtime/test_font_data.cc +++ b/runtime/test_font_data.cc @@ -1621,19 +1621,19 @@ namespace flutter { std::vector> GetTestFontData() { std::vector> typefaces; #if EMBED_TEST_FONT_DATA - typefaces.push_back(SkTypeface::MakeFromStream( - SkMemoryStream::MakeDirect(kFlutterTestFont, kFlutterTestFontLength))); typefaces.push_back(SkTypeface::MakeFromStream( SkMemoryStream::MakeDirect(kAhemFont, kAhemFontLength))); typefaces.push_back(SkTypeface::MakeFromStream( SkMemoryStream::MakeDirect(kCoughFont, kCoughFontLength))); + typefaces.push_back(SkTypeface::MakeFromStream( + SkMemoryStream::MakeDirect(kFlutterTestFont, kFlutterTestFontLength))); #endif // EMBED_TEST_FONT_DATA return typefaces; } std::vector GetTestFontFamilyNames() { #if EMBED_TEST_FONT_DATA - std::vector names = {"FlutterTest", "Ahem", "Cough"}; + std::vector names = {"Ahem", "Cough", "FlutterTest"}; #else // EMBED_TEST_FONT_DATA std::vector names; #endif // EMBED_TEST_FONT_DATA diff --git a/testing/dart/canvas_test.dart b/testing/dart/canvas_test.dart index 451beaf243af5..c230382017025 100644 --- a/testing/dart/canvas_test.dart +++ b/testing/dart/canvas_test.dart @@ -331,7 +331,6 @@ void main() { builder.pushStyle(TextStyle( decoration: TextDecoration.underline, decorationColor: const Color(0xFF0000FF), - fontFamily: 'Ahem', fontSize: 10, color: const Color(0xFF000000), decorationStyle: style, diff --git a/testing/dart/paragraph_builder_test.dart b/testing/dart/paragraph_builder_test.dart index 14761f17f9c83..37e27a758147a 100644 --- a/testing/dart/paragraph_builder_test.dart +++ b/testing/dart/paragraph_builder_test.dart @@ -7,6 +7,9 @@ import 'dart:ui'; import 'package:litetest/litetest.dart'; void main() { + // The actual values for font measurements will vary by platform slightly. + const double epsillon = 0.0001; + test('Should be able to build and layout a paragraph', () { final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle()); builder.addText('Hello'); @@ -37,10 +40,10 @@ void main() { final List boxes = paragraph.getBoxesForRange(0, 3); expect(boxes.length, 1); - expect(boxes.first.left, 0.0); - expect(boxes.first.top, 0.0); - expect(boxes.first.right, 42.0); - expect(boxes.first.bottom, 14.0); + expect(boxes.first.left, 0); + expect(boxes.first.top, closeTo(0, epsillon)); + expect(boxes.first.right, closeTo(42, epsillon)); + expect(boxes.first.bottom, closeTo(14, epsillon)); expect(boxes.first.direction, TextDirection.ltr); }); @@ -57,13 +60,13 @@ void main() { final List metrics = paragraph.computeLineMetrics(); expect(metrics.length, 1); expect(metrics.first.hardBreak, true); - expect(metrics.first.ascent, 10.5); - expect(metrics.first.descent, 3.5); - expect(metrics.first.unscaledAscent, 10.5); + expect(metrics.first.ascent, closeTo(11.200042724609375, epsillon)); + expect(metrics.first.descent, closeTo(2.799957275390625, epsillon)); + expect(metrics.first.unscaledAscent, closeTo(11.200042724609375, epsillon)); expect(metrics.first.height, 14.0); expect(metrics.first.width, 70.0); expect(metrics.first.left, 0.0); - expect(metrics.first.baseline, 10.5); + expect(metrics.first.baseline, closeTo(11.200042724609375, epsillon)); expect(metrics.first.lineNumber, 0); }); } From c7894a662ae10b3a203c2c608aa5f5529478e3af Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 10 Mar 2023 16:39:04 -0800 Subject: [PATCH 07/16] Make the context current before accessing GL in MakeSkiaGpuImage (#40208) Make the context current before accessing GL in MakeSkiaGpuImage --- shell/common/BUILD.gn | 8 ++++ shell/common/fixtures/shell_test.dart | 4 ++ shell/common/rasterizer.cc | 17 +++++--- shell/common/shell_unittests.cc | 61 +++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 7 deletions(-) diff --git a/shell/common/BUILD.gn b/shell/common/BUILD.gn index 7fa0c1b23ae70..d0255379bd84a 100644 --- a/shell/common/BUILD.gn +++ b/shell/common/BUILD.gn @@ -328,5 +328,13 @@ if (enable_unittests) { deps += [ "//third_party/swiftshader" ] } } + + if (shell_enable_gl) { + deps += [ + "//third_party/angle:libEGL_static", + "//third_party/angle:libGLESv2_static", + "//third_party/swiftshader", + ] + } } } diff --git a/shell/common/fixtures/shell_test.dart b/shell/common/fixtures/shell_test.dart index b88289a093f74..5f953fd64823d 100644 --- a/shell/common/fixtures/shell_test.dart +++ b/shell/common/fixtures/shell_test.dart @@ -354,6 +354,9 @@ void scene_with_red_box() { PlatformDispatcher.instance.scheduleFrame(); } +@pragma('vm:external-name', 'NativeOnBeforeToImageSync') +external void onBeforeToImageSync(); + @pragma('vm:entry-point') Future toImageSync() async { @@ -362,6 +365,7 @@ Future toImageSync() async { canvas.drawPaint(Paint()..color = const Color(0xFFAAAAAA)); final Picture picture = recorder.endRecording(); + onBeforeToImageSync(); final Image image = picture.toImageSync(20, 25); void expect(Object? a, Object? b) { if (a != b) { diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 478e5d0309393..d4a43e66b32da 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -289,17 +289,12 @@ std::unique_ptr Rasterizer::MakeSkiaGpuImage( TRACE_EVENT0("flutter", "Rasterizer::MakeGpuImage"); FML_DCHECK(display_list); -// TODO(dnfield): the Linux embedding is in a rough state right now and -// I can't seem to get the GPU path working on it. -// https://github.com/flutter/flutter/issues/108835 -#if FML_OS_LINUX - return MakeBitmapImage(display_list, image_info); -#endif - std::unique_ptr result; delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() .SetIfTrue([&result, &image_info, &display_list] { + // TODO(dnfield): This isn't safe if display_list contains any GPU + // resources like an SkImage_gpu. result = MakeBitmapImage(display_list, image_info); }) .SetIfFalse([&result, &image_info, &display_list, @@ -307,6 +302,14 @@ std::unique_ptr Rasterizer::MakeSkiaGpuImage( gpu_image_behavior = gpu_image_behavior_] { if (!surface || gpu_image_behavior == MakeGpuImageBehavior::kBitmap) { + // TODO(dnfield): This isn't safe if display_list contains any GPU + // resources like an SkImage_gpu. + result = MakeBitmapImage(display_list, image_info); + return; + } + + auto context_switch = surface->MakeRenderContextCurrent(); + if (!context_switch->GetResult()) { result = MakeBitmapImage(display_list, image_info); return; } diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 36c86463d8534..2d1b4f01f9259 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -11,6 +11,10 @@ #include #include +#if SHELL_ENABLE_GL +#include +#endif // SHELL_ENABLE_GL + #include "assets/directory_asset_bundle.h" #include "common/graphics/persistent_cache.h" #include "flutter/flow/layers/backdrop_filter_layer.h" @@ -3890,6 +3894,11 @@ TEST_F(ShellTest, PictureToImageSync) { ShellTestPlatformView::BackendType::kGLBackend // ); + AddNativeCallback("NativeOnBeforeToImageSync", + CREATE_NATIVE_ENTRY([&](auto args) { + // nop + })); + fml::CountDownLatch latch(2); AddNativeCallback("NotifyNative", CREATE_NATIVE_ENTRY([&](auto args) { // Teardown and set up rasterizer again. @@ -3912,6 +3921,58 @@ TEST_F(ShellTest, PictureToImageSync) { DestroyShell(std::move(shell)); } +#if SHELL_ENABLE_GL +// This test uses the GL backend and refers to symbols in egl.h +TEST_F(ShellTest, PictureToImageSyncWithTrampledContext) { + // make it easier to trample the GL context by running on a single task + // runner. + ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".", + ThreadHost::Type::Platform); + auto task_runner = thread_host.platform_thread->GetTaskRunner(); + TaskRunners task_runners("test", task_runner, task_runner, task_runner, + task_runner); + + auto settings = CreateSettingsForFixture(); + std::unique_ptr shell = + CreateShell(settings, // + task_runners, // + false, // + nullptr, // + false, // + ShellTestPlatformView::BackendType::kGLBackend // + ); + + AddNativeCallback( + "NativeOnBeforeToImageSync", CREATE_NATIVE_ENTRY([&](auto args) { + // Trample the GL context. If the rasterizer fails + // to make the right one current again, test will + // fail. + ::eglMakeCurrent(::eglGetCurrentDisplay(), NULL, NULL, NULL); + })); + + fml::CountDownLatch latch(2); + AddNativeCallback("NotifyNative", CREATE_NATIVE_ENTRY([&](auto args) { + // Teardown and set up rasterizer again. + PlatformViewNotifyDestroyed(shell.get()); + PlatformViewNotifyCreated(shell.get()); + latch.CountDown(); + })); + + ASSERT_NE(shell, nullptr); + ASSERT_TRUE(shell->IsSetup()); + auto configuration = RunConfiguration::InferFromSettings(settings); + PlatformViewNotifyCreated(shell.get()); + configuration.SetEntrypoint("toImageSync"); + RunEngine(shell.get(), std::move(configuration)); + PumpOneFrame(shell.get()); + + latch.Wait(); + + PlatformViewNotifyDestroyed(shell.get()); + DestroyShell(std::move(shell), task_runners); +} +#endif // SHELL_ENABLE_GL + TEST_F(ShellTest, PluginUtilitiesCallbackHandleErrorHandling) { auto settings = CreateSettingsForFixture(); std::unique_ptr shell = From 04e8d5431203fc8d5000bafa21e14e179c43b06b Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Sat, 11 Mar 2023 12:49:59 -0800 Subject: [PATCH 08/16] [macOS] Forward mouseDown/Up to view controller (#40241) This works around an AppKit bug in which mouseDown/mouseUp events are not correctly forwarded up the responder chain for views nested inside an NSPopover if (and only if) the macOS "Reduce Transparency" accessibility setting is enabled in the System Settings. When the above conditions are satisfied, the nested NSView receives the mouseDown:/mouseUp: call but if it delegates to the default implementation (implemented in NSResponder) mouseDown/mouseUp calls are triggered on containing views (in our case FlutterViewWrapper) but not triggered on the view controller and other responders in the responder chain until we an _NSPopoverWindow class is hit. A minimal AppKit-only (non-Flutter) repro shows this behaviour repros with even a minimal NSViewController implementation and an unmodified NSView. See: https://github.com/cbracken/PopoverRepro A radar has been filed with Apple and a copy posted to OpenRadar. See: http://www.openradar.me/FB12050037 In order to work around this bug, we override mouseDown/mouseUp in the topmost containing view of FlutterView (in our case, FlutterViewWrapper) to have the behaviour documented as the default behaviour in NSResponder's mouseDown/mouseUp documentation. In otherwords, to simply forward the call to self.nextResponder. See: https://developer.apple.com/documentation/appkit/nsresponder/1524634-mousedown Because replicating the exact configuration of a FlutterView contained in an NSPopover and System Settings that have been modified to enable the "Reduce Transparency" setting is difficult and likely error-prone in infra, we instead simulate the bug by testing that even if NSResponder's mouseDown/mouseUp method are swizzled to no-op, these calls are correctly forwarded to the next responder in the chain. If, in the future Apple does fix this issue, this workaround can be removed once Flutter's minimum supported macOS SDK is at least the version that contains the fix. Issue: https://github.com/flutter/flutter/issues/115015 --- .../framework/Source/FlutterViewController.mm | 28 +++++++ .../Source/FlutterViewControllerTest.mm | 75 +++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index ace1e145c1e17..b9999c0cfae01 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -278,6 +278,34 @@ - (NSArray*)accessibilityChildren { return @[ _flutterView ]; } +- (void)mouseDown:(NSEvent*)event { + // Work around an AppKit bug where mouseDown/mouseUp are not called on the view controller if the + // view is the content view of an NSPopover AND macOS's Reduced Transparency accessibility setting + // is enabled. + // + // This simply calls mouseDown on the next responder in the responder chain as the default + // implementation on NSResponder is documented to do. + // + // See: https://github.com/flutter/flutter/issues/115015 + // See: http://www.openradar.me/FB12050037 + // See: https://developer.apple.com/documentation/appkit/nsresponder/1524634-mousedown + [self.nextResponder mouseDown:event]; +} + +- (void)mouseUp:(NSEvent*)event { + // Work around an AppKit bug where mouseDown/mouseUp are not called on the view controller if the + // view is the content view of an NSPopover AND macOS's Reduced Transparency accessibility setting + // is enabled. + // + // This simply calls mouseUp on the next responder in the responder chain as the default + // implementation on NSResponder is documented to do. + // + // See: https://github.com/flutter/flutter/issues/115015 + // See: http://www.openradar.me/FB12050037 + // See: https://developer.apple.com/documentation/appkit/nsresponder/1535349-mouseup + [self.nextResponder mouseUp:event]; +} + @end #pragma mark - FlutterViewController implementation. diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm index ea96d6914d872..b48953923a38f 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm @@ -18,6 +18,8 @@ #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h" #import "flutter/testing/testing.h" +#pragma mark - Test Helper Classes + // A wrap to convert FlutterKeyEvent to a ObjC class. @interface KeyEventWrapper : NSObject @property(nonatomic) FlutterKeyEvent* data; @@ -36,6 +38,23 @@ - (void)dealloc { } @end +// A FlutterViewController subclass for testing that mouseDown/mouseUp get called when +// mouse events are sent to the associated view. +@interface MouseEventFlutterViewController : FlutterViewController +@property(nonatomic, assign) BOOL mouseDownCalled; +@property(nonatomic, assign) BOOL mouseUpCalled; +@end + +@implementation MouseEventFlutterViewController +- (void)mouseDown:(NSEvent*)event { + self.mouseDownCalled = YES; +} + +- (void)mouseUp:(NSEvent*)event { + self.mouseUpCalled = YES; +} +@end + @interface FlutterViewControllerTestObjC : NSObject - (bool)testKeyEventsAreSentToFramework; - (bool)testKeyEventsArePropagatedIfNotHandled; @@ -43,6 +62,7 @@ - (bool)testKeyEventsAreNotPropagatedIfHandled; - (bool)testFlagsChangedEventsArePropagatedIfNotHandled; - (bool)testKeyboardIsRestartedOnEngineRestart; - (bool)testTrackpadGesturesAreSentToFramework; +- (bool)testMouseDownUpEventsSentToNextResponder; - (bool)testModifierKeysAreSynthesizedOnMouseMove; - (bool)testViewWillAppearCalledMultipleTimes; - (bool)testFlutterViewIsConfigured; @@ -52,6 +72,8 @@ + (void)respondFalseForSendEvent:(const FlutterKeyEvent&)event userData:(nullable void*)userData; @end +#pragma mark - Static helper functions + using namespace ::flutter::testing::keycodes; namespace flutter::testing { @@ -108,6 +130,8 @@ id MockGestureEvent(NSEventType type, NSEventPhase phase, double magnification, } // namespace +#pragma mark - gtest tests + TEST(FlutterViewController, HasViewThatHidesOtherViewsInAccessibility) { FlutterViewController* viewControllerMock = CreateMockViewController(); @@ -196,6 +220,10 @@ id MockGestureEvent(NSEventType type, NSEventPhase phase, double magnification, ASSERT_TRUE([[FlutterViewControllerTestObjC alloc] testTrackpadGesturesAreSentToFramework]); } +TEST(FlutterViewControllerTest, TestMouseDownUpEventsSentToNextResponder) { + ASSERT_TRUE([[FlutterViewControllerTestObjC alloc] testMouseDownUpEventsSentToNextResponder]); +} + TEST(FlutterViewControllerTest, TestModifierKeysAreSynthesizedOnMouseMove) { ASSERT_TRUE([[FlutterViewControllerTestObjC alloc] testModifierKeysAreSynthesizedOnMouseMove]); } @@ -210,6 +238,8 @@ id MockGestureEvent(NSEventType type, NSEventPhase phase, double magnification, } // namespace flutter::testing +#pragma mark - FlutterViewControllerTestObjC + @implementation FlutterViewControllerTestObjC - (bool)testKeyEventsAreSentToFramework { @@ -802,6 +832,51 @@ - (bool)testViewWillAppearCalledMultipleTimes { return true; } +static void SwizzledNoop(id self, SEL _cmd) {} + +// Verify workaround an AppKit bug where mouseDown/mouseUp are not called on the view controller if +// the view is the content view of an NSPopover AND macOS's Reduced Transparency accessibility +// setting is enabled. +// +// See: https://github.com/flutter/flutter/issues/115015 +// See: http://www.openradar.me/FB12050037 +// See: https://developer.apple.com/documentation/appkit/nsresponder/1524634-mousedown +- (bool)testMouseDownUpEventsSentToNextResponder { + // The root cause of the above bug is NSResponder mouseDown/mouseUp methods that don't correctly + // walk the responder chain calling the appropriate method on the next responder under certain + // conditions. Simulate this by swizzling out the default implementations and replacing them with + // no-ops. + Method mouseDown = class_getInstanceMethod([NSResponder class], @selector(mouseDown:)); + Method mouseUp = class_getInstanceMethod([NSResponder class], @selector(mouseUp:)); + IMP noopImp = (IMP)SwizzledNoop; + IMP origMouseDown = method_setImplementation(mouseDown, noopImp); + IMP origMouseUp = method_setImplementation(mouseUp, noopImp); + + // Verify that mouseDown/mouseUp trigger mouseDown/mouseUp calls on FlutterViewController. + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + MouseEventFlutterViewController* viewController = + [[MouseEventFlutterViewController alloc] initWithEngine:engineMock nibName:@"" bundle:nil]; + FlutterView* view = (FlutterView*)[viewController view]; + + EXPECT_FALSE(viewController.mouseDownCalled); + EXPECT_FALSE(viewController.mouseUpCalled); + + NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00); + [view mouseDown:mouseEvent]; + EXPECT_TRUE(viewController.mouseDownCalled); + EXPECT_FALSE(viewController.mouseUpCalled); + + viewController.mouseDownCalled = NO; + [view mouseUp:mouseEvent]; + EXPECT_FALSE(viewController.mouseDownCalled); + EXPECT_TRUE(viewController.mouseUpCalled); + + // Restore the original NSResponder mouseDown/mouseUp implementations. + method_setImplementation(mouseDown, origMouseDown); + method_setImplementation(mouseUp, origMouseUp); + return true; +} + - (bool)testModifierKeysAreSynthesizedOnMouseMove { id engineMock = flutter::testing::CreateMockFlutterEngine(@""); // Need to return a real renderer to allow view controller to load. From 57f7120ef923a2806e2406319f0c35dc3619508b Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Sat, 11 Mar 2023 19:38:43 -0800 Subject: [PATCH 09/16] Add GN arguments that disable building host artifacts (#40242) --- common/config.gni | 8 ++++++-- tools/gn | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/common/config.gni b/common/config.gni index 48f78fbbc17c2..142701b8542ff 100644 --- a/common/config.gni +++ b/common/config.gni @@ -16,6 +16,9 @@ declare_args() { # Whether to use a prebuilt Dart SDK instead of building one. flutter_prebuilt_dart_sdk = false + + # Whether to build host-side development artifacts. + flutter_build_engine_artifacts = true } # feature_defines_list --------------------------------------------------------- @@ -122,5 +125,6 @@ if (flutter_prebuilt_dart_sdk) { # TODO: We can't build the engine artifacts for arm (32-bit) right now; # see https://github.com/flutter/flutter/issues/74322 build_engine_artifacts = - current_toolchain == host_toolchain || - (is_linux && !is_chromeos && current_cpu != "arm") || is_mac || is_win + flutter_build_engine_artifacts && + (current_toolchain == host_toolchain || + (is_linux && !is_chromeos && current_cpu != "arm") || is_mac || is_win) diff --git a/tools/gn b/tools/gn index b893752780775..072a6d289b272 100755 --- a/tools/gn +++ b/tools/gn @@ -264,7 +264,9 @@ def to_gn_args(args): gn_args['full_dart_sdk'] = args.full_dart_sdk if args.enable_unittests: - gn_args['enable_unittests'] = args.enable_unittests + gn_args['enable_unittests'] = True + if args.no_enable_unittests: + gn_args['enable_unittests'] = False # Skia GN args. gn_args['skia_enable_flutter_defines' @@ -323,6 +325,9 @@ def to_gn_args(args): gn_args['target_cpu'] = get_target_cpu(args) gn_args['dart_target_arch'] = gn_args['target_cpu'] + if not args.build_engine_artifacts: + gn_args['flutter_build_engine_artifacts'] = False + # We cannot cross-compile for 32 bit arm on a Windows host. We work around # this by leaving 'target_cpu' and 'dart_target_arch' set to 'arm' so that # Dart tools such as gen_snapshot that are built for the host will correctly @@ -660,7 +665,18 @@ def parse_args(args): parser.add_argument('--unoptimized', default=False, action='store_true') - parser.add_argument('--enable-unittests', action='store_true', default=False) + parser.add_argument( + '--enable-unittests', + action='store_true', + default=False, + help='Force enable building unit test binaries.' + ) + parser.add_argument( + '--no-enable-unittests', + default=False, + action='store_true', + help='Force disable building unit test binaries.' + ) parser.add_argument( '--runtime-mode', @@ -755,6 +771,19 @@ def parse_args(args): '--arm-float-abi', type=str, choices=['hard', 'soft', 'softfp'] ) + parser.add_argument( + '--build-engine-artifacts', + default=True, + action='store_true', + help='Build the host-side development artifacts.' + ) + parser.add_argument( + '--no-build-engine-artifacts', + dest='build_engine_artifacts', + action='store_false', + help='Do not build the host-side development artifacts.' + ) + parser.add_argument('--goma', default=True, action='store_true') parser.add_argument('--no-goma', dest='goma', action='store_false') parser.add_argument( From ae979a854eed6f645e6e057b89cde35ae28d6887 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Sun, 12 Mar 2023 23:49:22 -0700 Subject: [PATCH 10/16] [Impeller] More sundry fixes to the Vulkan backend. (#40244) [Impeller] More sundry fixes to the Vulkan backend. --- ci/licenses_golden/licenses_flutter | 26 +- impeller/aiks/aiks_unittests.cc | 2 +- impeller/aiks/picture.cc | 2 +- impeller/compiler/code_gen_template.h | 12 +- impeller/entity/contents/content_context.cc | 14 +- impeller/entity/contents/content_context.h | 4 +- .../contents/runtime_effect_contents.cc | 7 +- impeller/entity/entity_pass.cc | 6 +- .../backend/metal/playground_impl_mtl.mm | 5 +- impeller/playground/playground.cc | 9 +- impeller/renderer/BUILD.gn | 5 +- .../renderer/backend/gles/context_gles.cc | 14 +- impeller/renderer/backend/gles/context_gles.h | 9 +- impeller/renderer/backend/metal/context_mtl.h | 37 +- .../renderer/backend/metal/context_mtl.mm | 98 ++-- .../renderer/backend/metal/surface_mtl.mm | 3 +- impeller/renderer/backend/vulkan/BUILD.gn | 8 + .../renderer/backend/vulkan/allocator_vk.cc | 67 +-- .../renderer/backend/vulkan/allocator_vk.h | 2 +- .../backend/vulkan/blit_command_vk.cc | 104 ++-- .../backend/vulkan/capabilities_vk.cc | 324 +++++++++++- .../renderer/backend/vulkan/capabilities_vk.h | 68 ++- .../backend/vulkan/command_encoder_vk.cc | 179 +++++-- .../backend/vulkan/command_encoder_vk.h | 31 +- .../backend/vulkan/command_pool_vk.cc | 135 +++++ .../renderer/backend/vulkan/command_pool_vk.h | 55 ++ .../renderer/backend/vulkan/context_vk.cc | 492 ++++++------------ impeller/renderer/backend/vulkan/context_vk.h | 55 +- .../backend/vulkan/debug_report_vk.cc | 189 +++++++ .../renderer/backend/vulkan/debug_report_vk.h | 44 ++ .../backend/vulkan/descriptor_pool_vk.cc | 74 +++ .../backend/vulkan/descriptor_pool_vk.h | 48 ++ .../backend/vulkan/device_buffer_vk.cc | 2 +- .../backend/vulkan/device_buffer_vk.h | 2 +- .../backend/vulkan/fence_waiter_vk.cc | 108 ++++ .../renderer/backend/vulkan/fence_waiter_vk.h | 53 ++ impeller/renderer/backend/vulkan/formats_vk.h | 56 +- .../backend/vulkan/pipeline_library_vk.cc | 169 +++--- .../backend/vulkan/pipeline_library_vk.h | 5 +- .../renderer/backend/vulkan/pipeline_vk.cc | 49 +- .../renderer/backend/vulkan/pipeline_vk.h | 46 +- .../renderer/backend/vulkan/render_pass_vk.cc | 331 ++++++------ .../renderer/backend/vulkan/render_pass_vk.h | 3 +- .../backend/vulkan/sampler_library_vk.cc | 6 + .../renderer/backend/vulkan/sampler_vk.cc | 2 +- impeller/renderer/backend/vulkan/sampler_vk.h | 2 +- .../backend/vulkan/shared_object_vk.h | 9 +- .../renderer/backend/vulkan/surface_vk.cc | 8 +- .../backend/vulkan/swapchain_image_vk.cc | 25 +- .../backend/vulkan/swapchain_image_vk.h | 11 +- .../backend/vulkan/swapchain_impl_vk.cc | 61 ++- .../backend/vulkan/texture_source_vk.cc | 53 ++ .../backend/vulkan/texture_source_vk.h | 26 +- .../renderer/backend/vulkan/texture_vk.cc | 145 +++--- impeller/renderer/backend/vulkan/texture_vk.h | 9 +- impeller/renderer/capabilities.cc | 159 ++++++ impeller/renderer/capabilities.h | 80 +++ .../renderer/compute_subgroup_unittests.cc | 4 +- impeller/renderer/compute_unittests.cc | 4 +- impeller/renderer/context.cc | 4 +- impeller/renderer/context.h | 17 +- impeller/renderer/descriptor_set_layout.h | 27 - impeller/renderer/device_capabilities.cc | 141 ----- impeller/renderer/device_capabilities.h | 99 ---- impeller/renderer/formats.h | 4 + impeller/renderer/pipeline_builder.h | 4 +- impeller/renderer/render_target.cc | 10 +- impeller/renderer/sampler.h | 2 +- impeller/renderer/shader_types.h | 11 + impeller/renderer/testing/mocks.h | 5 +- impeller/renderer/vertex_descriptor.h | 1 - .../runtime_stage/runtime_stage_unittests.cc | 4 +- lib/ui/painting/image_decoder_impeller.cc | 2 +- .../darwin/ios/ios_surface_metal_impeller.mm | 75 +-- 74 files changed, 2539 insertions(+), 1423 deletions(-) create mode 100644 impeller/renderer/backend/vulkan/command_pool_vk.cc create mode 100644 impeller/renderer/backend/vulkan/command_pool_vk.h create mode 100644 impeller/renderer/backend/vulkan/debug_report_vk.cc create mode 100644 impeller/renderer/backend/vulkan/debug_report_vk.h create mode 100644 impeller/renderer/backend/vulkan/descriptor_pool_vk.cc create mode 100644 impeller/renderer/backend/vulkan/descriptor_pool_vk.h create mode 100644 impeller/renderer/backend/vulkan/fence_waiter_vk.cc create mode 100644 impeller/renderer/backend/vulkan/fence_waiter_vk.h create mode 100644 impeller/renderer/capabilities.cc create mode 100644 impeller/renderer/capabilities.h delete mode 100644 impeller/renderer/descriptor_set_layout.h delete mode 100644 impeller/renderer/device_capabilities.cc delete mode 100644 impeller/renderer/device_capabilities.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 0d4ce0443790b..f3cf26206c773 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1409,10 +1409,18 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc + ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.cc + ../../../flutter/LICENSE @@ -1454,6 +1462,8 @@ ORIGIN: ../../../flutter/impeller/renderer/buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/buffer_view.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/buffer_view.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/capabilities.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/capabilities.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/command.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/command.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/command_buffer.cc + ../../../flutter/LICENSE @@ -1468,13 +1478,10 @@ ORIGIN: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.cc + ../. ORIGIN: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/context.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/descriptor_set_layout.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer_descriptor.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer_descriptor.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/device_capabilities.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/device_capabilities.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/formats.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/formats.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/gpu_tracer.cc + ../../../flutter/LICENSE @@ -3936,10 +3943,18 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.cc @@ -3981,6 +3996,8 @@ FILE: ../../../flutter/impeller/renderer/buffer.cc FILE: ../../../flutter/impeller/renderer/buffer.h FILE: ../../../flutter/impeller/renderer/buffer_view.cc FILE: ../../../flutter/impeller/renderer/buffer_view.h +FILE: ../../../flutter/impeller/renderer/capabilities.cc +FILE: ../../../flutter/impeller/renderer/capabilities.h FILE: ../../../flutter/impeller/renderer/command.cc FILE: ../../../flutter/impeller/renderer/command.h FILE: ../../../flutter/impeller/renderer/command_buffer.cc @@ -3995,13 +4012,10 @@ FILE: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.cc FILE: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.h FILE: ../../../flutter/impeller/renderer/context.cc FILE: ../../../flutter/impeller/renderer/context.h -FILE: ../../../flutter/impeller/renderer/descriptor_set_layout.h FILE: ../../../flutter/impeller/renderer/device_buffer.cc FILE: ../../../flutter/impeller/renderer/device_buffer.h FILE: ../../../flutter/impeller/renderer/device_buffer_descriptor.cc FILE: ../../../flutter/impeller/renderer/device_buffer_descriptor.h -FILE: ../../../flutter/impeller/renderer/device_capabilities.cc -FILE: ../../../flutter/impeller/renderer/device_capabilities.h FILE: ../../../flutter/impeller/renderer/formats.cc FILE: ../../../flutter/impeller/renderer/formats.h FILE: ../../../flutter/impeller/renderer/gpu_tracer.cc diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 634bf58f27642..04fdeb5b01e4e 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -108,7 +108,7 @@ bool GenerateMipmap(const std::shared_ptr& context, } pass->GenerateMipmap(std::move(texture), std::move(label)); pass->EncodeCommands(context->GetResourceAllocator()); - return true; + return buffer->SubmitCommands(); } TEST_P(AiksTest, CanRenderTiledTexture) { diff --git a/impeller/aiks/picture.cc b/impeller/aiks/picture.cc index 97b48e357a321..10500e6c09d89 100644 --- a/impeller/aiks/picture.cc +++ b/impeller/aiks/picture.cc @@ -54,7 +54,7 @@ std::shared_ptr Picture::RenderToTexture( // features to Image someday. auto impeller_context = context.GetContext(); RenderTarget target; - if (impeller_context->GetDeviceCapabilities().SupportsOffscreenMSAA()) { + if (impeller_context->GetCapabilities()->SupportsOffscreenMSAA()) { target = RenderTarget::CreateOffscreenMSAA(*impeller_context, size); } else { target = RenderTarget::CreateOffscreen(*impeller_context, size); diff --git a/impeller/compiler/code_gen_template.h b/impeller/compiler/code_gen_template.h index d2708052d1838..2666a53f9ca96 100644 --- a/impeller/compiler/code_gen_template.h +++ b/impeller/compiler/code_gen_template.h @@ -22,8 +22,6 @@ constexpr std::string_view kReflectionHeaderTemplate = #include "impeller/renderer/compute_command.h" {# // nogncheck #} -#include "impeller/renderer/descriptor_set_layout.h" {# // nogncheck #} - #include "impeller/renderer/sampler.h" {# // nogncheck #} #include "impeller/renderer/shader_types.h" {# // nogncheck #} @@ -166,17 +164,15 @@ std::move({{ arg.argument_name }}){% if not loop.is_last %}, {% endif %} {% for buffer in buffers %} DescriptorSetLayout{ {{buffer.binding}}, // binding = {{buffer.binding}} - DescriptorType::kUniformBuffer, // descriptorType = Uniform Buffer - 1, // descriptorCount = 1 - {{to_shader_stage(shader_stage)}}, // stageFlags = {{to_shader_stage(shader_stage)}} + DescriptorType::kUniformBuffer, // descriptor_type = Uniform Buffer + {{to_shader_stage(shader_stage)}}, // shader_stage = {{to_shader_stage(shader_stage)}} }, {% endfor %} {% for sampled_image in sampled_images %} DescriptorSetLayout{ {{sampled_image.binding}}, // binding = {{sampled_image.binding}} - DescriptorType::kSampledImage, // descriptorType = Sampled Image - 1, // descriptorCount = 1 - {{to_shader_stage(shader_stage)}}, // stageFlags = {{to_shader_stage(shader_stage)}} + DescriptorType::kSampledImage, // descriptor_type = Sampled Image + {{to_shader_stage(shader_stage)}}, // shader_stage = {{to_shader_stage(shader_stage)}} }, {% endfor %} }; diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 36287aaf935f7..54a9fb46250fc 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -154,7 +154,8 @@ static std::unique_ptr CreateDefaultPipeline( return nullptr; } // Apply default ContentContextOptions to the descriptor. - const auto default_color_fmt = context.GetColorAttachmentPixelFormat(); + const auto default_color_fmt = + context.GetCapabilities()->GetDefaultColorFormat(); ContentContextOptions{.color_attachment_pixel_format = default_color_fmt} .ApplyToPipelineDescriptor(*desc); return std::make_unique(context, desc); @@ -175,7 +176,7 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); radial_gradient_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); - if (context_->GetDeviceCapabilities().SupportsSSBO()) { + if (context_->GetCapabilities()->SupportsSSBO()) { linear_gradient_ssbo_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); radial_gradient_ssbo_fill_pipelines_[{}] = @@ -183,7 +184,7 @@ ContentContext::ContentContext(std::shared_ptr context) sweep_gradient_ssbo_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); } - if (context_->GetDeviceCapabilities().SupportsFramebufferFetch()) { + if (context_->GetCapabilities()->SupportsFramebufferFetch()) { framebuffer_blend_color_pipelines_[{}] = CreateDefaultPipeline(*context_); framebuffer_blend_colorburn_pipelines_[{}] = @@ -315,8 +316,7 @@ std::shared_ptr ContentContext::MakeSubpass( auto context = GetContext(); RenderTarget subpass_target; - if (context->GetDeviceCapabilities().SupportsOffscreenMSAA() && - msaa_enabled) { + if (context->GetCapabilities()->SupportsOffscreenMSAA() && msaa_enabled) { subpass_target = RenderTarget::CreateOffscreenMSAA( *context, texture_size, SPrintF("%s Offscreen", label.c_str()), RenderTarget::kDefaultColorAttachmentConfigMSAA, std::nullopt); @@ -374,8 +374,8 @@ std::shared_ptr ContentContext::GetContext() const { return context_; } -const IDeviceCapabilities& ContentContext::GetDeviceCapabilities() const { - return context_->GetDeviceCapabilities(); +const Capabilities& ContentContext::GetDeviceCapabilities() const { + return *context_->GetCapabilities(); } void ContentContext::SetWireframe(bool wireframe) { diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 236167f3a9e58..3449236aae490 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -47,7 +47,7 @@ #include "impeller/entity/vertices.frag.h" #include "impeller/entity/yuv_to_rgb_filter.frag.h" #include "impeller/entity/yuv_to_rgb_filter.vert.h" -#include "impeller/renderer/device_capabilities.h" +#include "impeller/renderer/capabilities.h" #include "impeller/renderer/formats.h" #include "impeller/renderer/pipeline.h" #include "impeller/scene/scene_context.h" @@ -601,7 +601,7 @@ class ContentContext { std::shared_ptr GetGlyphAtlasContext() const; - const IDeviceCapabilities& GetDeviceCapabilities() const; + const Capabilities& GetDeviceCapabilities() const; void SetWireframe(bool wireframe); diff --git a/impeller/entity/contents/runtime_effect_contents.cc b/impeller/entity/contents/runtime_effect_contents.cc index 841027d84fc54..9f7aaadbde09c 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -102,10 +102,9 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, /// Get or create runtime stage pipeline. /// - const auto& device_capabilities = context->GetDeviceCapabilities(); - const auto color_attachment_format = context->GetColorAttachmentPixelFormat(); - const auto stencil_attachment_format = - device_capabilities.GetDefaultStencilFormat(); + const auto& caps = context->GetCapabilities(); + const auto color_attachment_format = caps->GetDefaultColorFormat(); + const auto stencil_attachment_format = caps->GetDefaultStencilFormat(); using VS = RuntimeEffectVertexShader; PipelineDescriptor desc; diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 487c56d063976..5e00c6b1c1ee0 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -152,7 +152,7 @@ static RenderTarget CreateRenderTarget(ContentContext& renderer, /// What's important is the `StorageMode` of the textures, which cannot be /// changed for the lifetime of the textures. - if (context->GetDeviceCapabilities().SupportsOffscreenMSAA()) { + if (context->GetCapabilities()->SupportsOffscreenMSAA()) { return RenderTarget::CreateOffscreenMSAA( *context, // context size, // size @@ -210,8 +210,8 @@ bool EntityPass::Render(ContentContext& renderer, command_buffer->SetLabel("EntityPass Root Command Buffer"); if (renderer.GetContext() - ->GetDeviceCapabilities() - .SupportsTextureToTextureBlits()) { + ->GetCapabilities() + ->SupportsTextureToTextureBlits()) { auto blit_pass = command_buffer->CreateBlitPass(); blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(), diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index 2418d1dae7c9a..cf26700b41706 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -82,9 +82,8 @@ } data_->metal_layer = [CAMetalLayer layer]; data_->metal_layer.device = ContextMTL::Cast(*context).GetMTLDevice(); - // This pixel format is one of the documented supported formats. - const auto color_fmt = context->GetColorAttachmentPixelFormat(); - data_->metal_layer.pixelFormat = ToMTLPixelFormat(color_fmt); + data_->metal_layer.pixelFormat = + ToMTLPixelFormat(context->GetCapabilities()->GetDefaultColorFormat()); data_->metal_layer.framebufferOnly = NO; cocoa_window.contentView.layer = data_->metal_layer; cocoa_window.contentView.wantsLayer = YES; diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index 85042638b8044..ecce6934d7ae4 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -402,8 +402,13 @@ std::shared_ptr Playground::CreateTextureForFixture( std::shared_ptr Playground::CreateTextureForFixture( const char* fixture_name, bool enable_mipmapping) const { - return CreateTextureForFixture(OpenAssetAsMapping(fixture_name), - enable_mipmapping); + auto texture = CreateTextureForFixture(OpenAssetAsMapping(fixture_name), + enable_mipmapping); + if (texture == nullptr) { + return nullptr; + } + texture->SetLabel(fixture_name); + return texture; } std::shared_ptr Playground::CreateTextureCubeForFixture( diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn index 792fc8ed85ff9..f968e626ee074 100644 --- a/impeller/renderer/BUILD.gn +++ b/impeller/renderer/BUILD.gn @@ -16,6 +16,8 @@ impeller_component("renderer") { "buffer.h", "buffer_view.cc", "buffer_view.h", + "capabilities.cc", + "capabilities.h", "command.cc", "command.h", "command_buffer.cc", @@ -30,13 +32,10 @@ impeller_component("renderer") { "compute_pipeline_descriptor.h", "context.cc", "context.h", - "descriptor_set_layout.h", "device_buffer.cc", "device_buffer.h", "device_buffer_descriptor.cc", "device_buffer_descriptor.h", - "device_capabilities.cc", - "device_capabilities.h", "formats.cc", "formats.h", "gpu_tracer.cc", diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index 85e1bd3ee8f78..b523a0d598250 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -7,7 +7,7 @@ #include "impeller/base/config.h" #include "impeller/base/validation.h" #include "impeller/base/work_queue_common.h" -#include "impeller/renderer/device_capabilities.h" +#include "impeller/renderer/capabilities.h" namespace impeller { @@ -72,7 +72,7 @@ ContextGLES::ContextGLES(std::unique_ptr gl, // Create the device capabilities. { device_capabilities_ = - DeviceCapabilitiesBuilder() + CapabilitiesBuilder() .SetHasThreadingRestrictions(true) .SetSupportsOffscreenMSAA(false) .SetSupportsSSBO(false) @@ -145,13 +145,9 @@ std::shared_ptr ContextGLES::GetWorkQueue() const { } // |Context| -const IDeviceCapabilities& ContextGLES::GetDeviceCapabilities() const { - return *device_capabilities_; -} - -// |Context| -PixelFormat ContextGLES::GetColorAttachmentPixelFormat() const { - return PixelFormat::kR8G8B8A8UNormInt; +const std::shared_ptr& ContextGLES::GetCapabilities() + const { + return device_capabilities_; } } // namespace impeller diff --git a/impeller/renderer/backend/gles/context_gles.h b/impeller/renderer/backend/gles/context_gles.h index 39e1384d97512..030877262741d 100644 --- a/impeller/renderer/backend/gles/context_gles.h +++ b/impeller/renderer/backend/gles/context_gles.h @@ -12,8 +12,8 @@ #include "impeller/renderer/backend/gles/reactor_gles.h" #include "impeller/renderer/backend/gles/sampler_library_gles.h" #include "impeller/renderer/backend/gles/shader_library_gles.h" +#include "impeller/renderer/capabilities.h" #include "impeller/renderer/context.h" -#include "impeller/renderer/device_capabilities.h" namespace impeller { @@ -41,7 +41,7 @@ class ContextGLES final : public Context, std::shared_ptr sampler_library_; std::shared_ptr work_queue_; std::shared_ptr resource_allocator_; - std::unique_ptr device_capabilities_; + std::shared_ptr device_capabilities_; bool is_valid_ = false; ContextGLES( @@ -70,10 +70,7 @@ class ContextGLES final : public Context, std::shared_ptr GetWorkQueue() const override; // |Context| - const IDeviceCapabilities& GetDeviceCapabilities() const override; - - // |Context| - PixelFormat GetColorAttachmentPixelFormat() const override; + const std::shared_ptr& GetCapabilities() const override; FML_DISALLOW_COPY_AND_ASSIGN(ContextGLES); }; diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index bd75e585d86c0..80b9bdc8f04ab 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -16,8 +16,8 @@ #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h" #include "impeller/renderer/backend/metal/pipeline_library_mtl.h" #include "impeller/renderer/backend/metal/shader_library_mtl.h" +#include "impeller/renderer/capabilities.h" #include "impeller/renderer/context.h" -#include "impeller/renderer/device_capabilities.h" #include "impeller/renderer/sampler.h" namespace impeller { @@ -37,22 +37,6 @@ class ContextMTL final : public Context, id GetMTLDevice() const; - private: - id device_ = nullptr; - id command_queue_ = nullptr; - std::shared_ptr shader_library_; - std::shared_ptr pipeline_library_; - std::shared_ptr sampler_library_; - std::shared_ptr resource_allocator_; - std::shared_ptr work_queue_; - std::shared_ptr gpu_tracer_; - std::unique_ptr device_capabilities_; - bool is_valid_ = false; - - ContextMTL(id device, NSArray>* shader_libraries); - - bool SupportsFramebufferFetch() const; - // |Context| bool IsValid() const override; @@ -78,7 +62,24 @@ class ContextMTL final : public Context, std::shared_ptr GetGPUTracer() const override; // |Context| - const IDeviceCapabilities& GetDeviceCapabilities() const override; + const std::shared_ptr& GetCapabilities() const override; + + // |Context| + bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override; + + private: + id device_ = nullptr; + id command_queue_ = nullptr; + std::shared_ptr shader_library_; + std::shared_ptr pipeline_library_; + std::shared_ptr sampler_library_; + std::shared_ptr resource_allocator_; + std::shared_ptr work_queue_; + std::shared_ptr gpu_tracer_; + std::shared_ptr device_capabilities_; + bool is_valid_ = false; + + ContextMTL(id device, NSArray>* shader_libraries); std::shared_ptr CreateCommandBufferInQueue( id queue) const; diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index 70c76592aa5fa..ce114a9862b5f 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -11,11 +11,56 @@ #include "flutter/fml/paths.h" #include "impeller/base/platform/darwin/work_queue_darwin.h" #include "impeller/renderer/backend/metal/sampler_library_mtl.h" -#include "impeller/renderer/device_capabilities.h" +#include "impeller/renderer/capabilities.h" #include "impeller/renderer/sampler_descriptor.h" namespace impeller { +static bool DeviceSupportsFramebufferFetch(id device) { + // The iOS simulator lies about supporting framebuffer fetch. +#if FML_OS_IOS_SIMULATOR + return false; +#endif // FML_OS_IOS_SIMULATOR + + if (@available(macOS 10.15, iOS 13, tvOS 13, *)) { + return [device supportsFamily:MTLGPUFamilyApple2]; + } + // According to + // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf , Apple2 + // corresponds to iOS GPU family 2, which supports A8 devices. +#if FML_OS_IOS + return [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]; +#else + return false; +#endif // FML_OS_IOS +} + +static bool DeviceSupportsComputeSubgroups(id device) { + bool supports_subgroups = false; + // Refer to the "SIMD-scoped reduction operations" feature in the table + // below: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf + if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) { + supports_subgroups = [device supportsFamily:MTLGPUFamilyApple7] || + [device supportsFamily:MTLGPUFamilyMac2]; + } + return supports_subgroups; +} + +static std::unique_ptr InferMetalCapabilities( + id device, + PixelFormat color_format = PixelFormat::kB8G8R8A8UNormInt) { + return CapabilitiesBuilder() + .SetHasThreadingRestrictions(false) + .SetSupportsOffscreenMSAA(true) + .SetSupportsSSBO(true) + .SetSupportsTextureToTextureBlits(true) + .SetSupportsFramebufferFetch(DeviceSupportsFramebufferFetch(device)) + .SetDefaultColorFormat(color_format) + .SetDefaultStencilFormat(PixelFormat::kS8UInt) + .SetSupportsCompute(true, DeviceSupportsComputeSubgroups(device)) + .Build(); +} + ContextMTL::ContextMTL(id device, NSArray>* shader_libraries) : device_(device) { @@ -89,50 +134,11 @@ { gpu_tracer_ = std::shared_ptr(new GPUTracerMTL(device_)); } #endif - { - bool supports_subgroups = false; - // Refer to the "SIMD-scoped reduction operations" feature in the table - // below: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf - if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) { - supports_subgroups = [device supportsFamily:MTLGPUFamilyApple7] || - [device supportsFamily:MTLGPUFamilyMac2]; - } - - device_capabilities_ = - DeviceCapabilitiesBuilder() - .SetHasThreadingRestrictions(false) - .SetSupportsOffscreenMSAA(true) - .SetSupportsSSBO(true) - .SetSupportsTextureToTextureBlits(true) - .SetSupportsFramebufferFetch(SupportsFramebufferFetch()) - .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) - .SetDefaultStencilFormat(PixelFormat::kS8UInt) - .SetSupportsCompute(true, supports_subgroups) - .Build(); - } + device_capabilities_ = InferMetalCapabilities(device_); is_valid_ = true; } -bool ContextMTL::SupportsFramebufferFetch() const { - // The iOS simulator lies about supporting framebuffer fetch. -#if FML_OS_IOS_SIMULATOR - return false; -#endif // FML_OS_IOS_SIMULATOR - - if (@available(macOS 10.15, iOS 13, tvOS 13, *)) { - return [device_ supportsFamily:MTLGPUFamilyApple2]; - } - // According to - // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf , Apple2 - // corresponds to iOS GPU family 2, which supports A8 devices. -#if FML_OS_IOS - return [device_ supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]; -#else - return false; -#endif // FML_OS_IOS -} - static NSArray>* MTLShaderLibraryFromFilePaths( id device, const std::vector& libraries_paths) { @@ -287,8 +293,14 @@ return device_; } -const IDeviceCapabilities& ContextMTL::GetDeviceCapabilities() const { - return *device_capabilities_; +const std::shared_ptr& ContextMTL::GetCapabilities() const { + return device_capabilities_; +} + +// |Context| +bool ContextMTL::UpdateOffscreenLayerPixelFormat(PixelFormat format) { + device_capabilities_ = InferMetalCapabilities(device_); + return true; } } // namespace impeller diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index 70eedfd7aee60..dccdac147f4e9 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -64,6 +64,7 @@ resolve_tex_desc.format = color_format; resolve_tex_desc.size = msaa_tex_desc.size; resolve_tex_desc.usage = static_cast(TextureUsage::kRenderTarget); + resolve_tex_desc.sample_count = SampleCount::kCount1; resolve_tex_desc.storage_mode = StorageMode::kDevicePrivate; std::shared_ptr resolve_tex = @@ -86,7 +87,7 @@ stencil_tex_desc.type = TextureType::kTexture2DMultisample; stencil_tex_desc.sample_count = SampleCount::kCount4; stencil_tex_desc.format = - context->GetDeviceCapabilities().GetDefaultStencilFormat(); + context->GetCapabilities()->GetDefaultStencilFormat(); stencil_tex_desc.size = msaa_tex_desc.size; stencil_tex_desc.usage = static_cast(TextureUsage::kRenderTarget); diff --git a/impeller/renderer/backend/vulkan/BUILD.gn b/impeller/renderer/backend/vulkan/BUILD.gn index 2c30458c842b8..a5de877f8afc9 100644 --- a/impeller/renderer/backend/vulkan/BUILD.gn +++ b/impeller/renderer/backend/vulkan/BUILD.gn @@ -18,10 +18,18 @@ impeller_component("vulkan") { "command_buffer_vk.h", "command_encoder_vk.cc", "command_encoder_vk.h", + "command_pool_vk.cc", + "command_pool_vk.h", "context_vk.cc", "context_vk.h", + "debug_report_vk.cc", + "debug_report_vk.h", + "descriptor_pool_vk.cc", + "descriptor_pool_vk.h", "device_buffer_vk.cc", "device_buffer_vk.h", + "fence_waiter_vk.cc", + "fence_waiter_vk.h", "formats_vk.cc", "formats_vk.h", "pipeline_library_vk.cc", diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc index f1c1e210e6ec9..25631dacb5ec9 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -152,10 +152,12 @@ static constexpr vk::ImageUsageFlags ToVKImageUsageFlags(PixelFormat format, } } - // TODO (https://github.com/flutter/flutter/issues/121634): - // Add transfer usage flags to support blit passes - vk_usage |= vk::ImageUsageFlagBits::eTransferSrc | - vk::ImageUsageFlagBits::eTransferDst; + if (mode != StorageMode::kDeviceTransient) { + // TODO (https://github.com/flutter/flutter/issues/121634): + // Add transfer usage flags to support blit passes + vk_usage |= vk::ImageUsageFlagBits::eTransferSrc | + vk::ImageUsageFlagBits::eTransferDst; + } return vk_usage; } @@ -211,8 +213,10 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { public: AllocatedTextureSourceVK(const TextureDescriptor& desc, VmaAllocator allocator, - vk::Device device) { + vk::Device device) + : TextureSourceVK(desc) { vk::ImageCreateInfo image_info; + image_info.flags = ToVKImageCreateFlags(desc.type); image_info.imageType = vk::ImageType::e2D; image_info.format = ToVKImageFormat(desc.format); image_info.extent = VkExtent3D{ @@ -229,13 +233,11 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { ToVKImageUsageFlags(desc.format, desc.usage, desc.storage_mode); image_info.sharingMode = vk::SharingMode::eExclusive; - VmaAllocationCreateInfo alloc_create_info = {}; + VmaAllocationCreateInfo alloc_nfo = {}; - alloc_create_info.usage = ToVMAMemoryUsage(); - alloc_create_info.preferredFlags = - ToVKMemoryPropertyFlags(desc.storage_mode, true); - alloc_create_info.flags = - ToVmaAllocationCreateFlags(desc.storage_mode, true); + alloc_nfo.usage = ToVMAMemoryUsage(); + alloc_nfo.preferredFlags = ToVKMemoryPropertyFlags(desc.storage_mode, true); + alloc_nfo.flags = ToVmaAllocationCreateFlags(desc.storage_mode, true); auto create_info_native = static_cast(image_info); @@ -244,13 +246,13 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { VmaAllocation allocation = {}; VmaAllocationInfo allocation_info = {}; { - auto result = vk::Result{vmaCreateImage(allocator, // - &create_info_native, // - &alloc_create_info, // - &vk_image, // - &allocation, // - &allocation_info // - )}; + auto result = vk::Result{::vmaCreateImage(allocator, // + &create_info_native, // + &alloc_nfo, // + &vk_image, // + &allocation, // + &allocation_info // + )}; if (result != vk::Result::eSuccess) { VALIDATION_LOG << "Unable to allocate Vulkan Image: " << vk::to_string(result); @@ -262,25 +264,24 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { allocator_ = allocator; allocation_ = allocation; - vk::ImageViewCreateInfo view_create_info = {}; - view_create_info.image = image_; - view_create_info.viewType = vk::ImageViewType::e2D; - view_create_info.format = image_info.format; - view_create_info.subresourceRange.aspectMask = - ToVKImageAspectFlags(desc.format); - view_create_info.subresourceRange.levelCount = image_info.mipLevels; - view_create_info.subresourceRange.layerCount = 1u; + vk::ImageViewCreateInfo view_info = {}; + view_info.image = image_; + view_info.viewType = ToVKImageViewType(desc.type); + view_info.format = image_info.format; + view_info.subresourceRange.aspectMask = ToVKImageAspectFlags(desc.format); + view_info.subresourceRange.levelCount = image_info.mipLevels; + view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type); // Vulkan does not have an image format that is equivalent to // `MTLPixelFormatA8Unorm`, so we use `R8Unorm` instead. Given that the // shaders expect that alpha channel to be set in the cases, we swizzle. // See: https://github.com/flutter/flutter/issues/115461 for more details. if (desc.format == PixelFormat::kA8UNormInt) { - view_create_info.components.a = vk::ComponentSwizzle::eR; - view_create_info.components.r = vk::ComponentSwizzle::eA; + view_info.components.a = vk::ComponentSwizzle::eR; + view_info.components.r = vk::ComponentSwizzle::eA; } - auto [result, image_view] = device.createImageViewUnique(view_create_info); + auto [result, image_view] = device.createImageViewUnique(view_info); if (result != vk::Result::eSuccess) { VALIDATION_LOG << "Unable to create an image view for allocation: " << vk::to_string(result); @@ -294,7 +295,7 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { ~AllocatedTextureSourceVK() { image_view_.reset(); if (image_) { - vmaDestroyImage( + ::vmaDestroyImage( allocator_, // static_cast(image_), // allocation_ // @@ -335,9 +336,9 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { bool IsValid() const { return is_valid_; } - vk::Image GetVKImage() const override { return image_; } + vk::Image GetImage() const override { return image_; } - vk::ImageView GetVKImageView() const override { return image_view_.get(); } + vk::ImageView GetImageView() const override { return image_view_.get(); } private: vk::Image image_ = {}; @@ -362,7 +363,7 @@ std::shared_ptr AllocatorVK::OnCreateTexture( if (!source->IsValid()) { return nullptr; } - return std::make_shared(desc, context_, std::move(source)); + return std::make_shared(context_, std::move(source)); } // |Allocator| diff --git a/impeller/renderer/backend/vulkan/allocator_vk.h b/impeller/renderer/backend/vulkan/allocator_vk.h index f4a9e8ee3b297..0b4f3541bce98 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.h +++ b/impeller/renderer/backend/vulkan/allocator_vk.h @@ -28,7 +28,7 @@ class AllocatorVK final : public Allocator { VmaAllocator allocator_ = {}; std::weak_ptr context_; vk::Device device_; - ISize max_texture_size_ = {4096, 4096}; + ISize max_texture_size_; bool is_valid_ = false; AllocatorVK(std::weak_ptr context, diff --git a/impeller/renderer/backend/vulkan/blit_command_vk.cc b/impeller/renderer/backend/vulkan/blit_command_vk.cc index 8c27935cf84c8..98c8ab0d4ec85 100644 --- a/impeller/renderer/backend/vulkan/blit_command_vk.cc +++ b/impeller/renderer/backend/vulkan/blit_command_vk.cc @@ -29,11 +29,27 @@ bool BlitCopyTextureToTextureCommandVK::Encode( const auto& src = TextureVK::Cast(*source); const auto& dst = TextureVK::Cast(*destination); - const auto src_layout = vk::ImageLayout::eTransferSrcOptimal; - const auto dst_layout = vk::ImageLayout::eTransferDstOptimal; - - if (!src.SetLayout(src_layout, cmd_buffer) || - !dst.SetLayout(dst_layout, cmd_buffer)) { + LayoutTransition src_tran; + src_tran.cmd_buffer = cmd_buffer; + src_tran.new_layout = vk::ImageLayout::eTransferSrcOptimal; + src_tran.src_access = vk::AccessFlagBits::eTransferWrite | + vk::AccessFlagBits::eShaderWrite | + vk::AccessFlagBits::eColorAttachmentWrite; + src_tran.src_stage = vk::PipelineStageFlagBits::eTransfer | + vk::PipelineStageFlagBits::eFragmentShader | + vk::PipelineStageFlagBits::eColorAttachmentOutput; + src_tran.dst_access = vk::AccessFlagBits::eTransferRead; + src_tran.dst_stage = vk::PipelineStageFlagBits::eTransfer; + + LayoutTransition dst_tran; + dst_tran.cmd_buffer = cmd_buffer; + dst_tran.new_layout = vk::ImageLayout::eTransferDstOptimal; + dst_tran.src_access = {}; + dst_tran.src_stage = vk::PipelineStageFlagBits::eTopOfPipe; + dst_tran.dst_access = vk::AccessFlagBits::eShaderRead; + dst_tran.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; + + if (!src.SetLayout(src_tran) || !dst.SetLayout(dst_tran)) { VALIDATION_LOG << "Could not complete layout transitions."; return false; } @@ -54,11 +70,11 @@ bool BlitCopyTextureToTextureCommandVK::Encode( // Issue the copy command now that the images are already in the right // layouts. - cmd_buffer.copyImage(src.GetImage(), // - src_layout, // - dst.GetImage(), // - dst_layout, // - image_copy // + cmd_buffer.copyImage(src.GetImage(), // + src_tran.new_layout, // + dst.GetImage(), // + dst_tran.new_layout, // + image_copy // ); return true; @@ -79,6 +95,20 @@ bool BlitCopyTextureToBufferCommandVK::Encode(CommandEncoderVK& encoder) const { // cast source and destination to TextureVK const auto& src = TextureVK::Cast(*source); + + LayoutTransition transition; + transition.cmd_buffer = cmd_buffer; + transition.new_layout = vk::ImageLayout::eTransferSrcOptimal; + transition.src_access = vk::AccessFlagBits::eShaderWrite | + vk::AccessFlagBits::eTransferWrite | + vk::AccessFlagBits::eColorAttachmentWrite; + transition.src_stage = vk::PipelineStageFlagBits::eFragmentShader | + vk::PipelineStageFlagBits::eTransfer | + vk::PipelineStageFlagBits::eColorAttachmentOutput; + transition.dst_access = vk::AccessFlagBits::eShaderRead; + transition.dst_stage = vk::PipelineStageFlagBits::eVertexShader | + vk::PipelineStageFlagBits::eFragmentShader; + const auto& dst = DeviceBufferVK::Cast(*destination); vk::BufferImageCopy image_copy; @@ -92,15 +122,15 @@ bool BlitCopyTextureToBufferCommandVK::Encode(CommandEncoderVK& encoder) const { image_copy.setImageExtent( vk::Extent3D(source_region.size.width, source_region.size.height, 1)); - if (!src.SetLayout(vk::ImageLayout::eTransferSrcOptimal, cmd_buffer)) { + if (!src.SetLayout(transition)) { VALIDATION_LOG << "Could not encode layout transition."; return false; } - cmd_buffer.copyImageToBuffer(src.GetImage(), // - vk::ImageLayout::eTransferSrcOptimal, // - dst.GetVKBufferHandle(), // - image_copy // + cmd_buffer.copyImageToBuffer(src.GetImage(), // + transition.new_layout, // + dst.GetBuffer(), // + image_copy // ); return true; @@ -204,10 +234,12 @@ bool BlitGenerateMipmapCommandVK::Encode(CommandEncoderVK& encoder) const { // offsets[0] is origin. blit.srcOffsets[1].x = size.width; blit.srcOffsets[1].y = size.height; + blit.srcOffsets[1].z = 1u; // offsets[0] is origin. - blit.dstOffsets[1].x = size.width >> mip_level; - blit.dstOffsets[1].y = size.height >> mip_level; + blit.dstOffsets[1].x = std::max(size.width >> mip_level, 1u); + blit.dstOffsets[1].y = std::max(size.height >> mip_level, 1u); + blit.dstOffsets[1].z = 1u; cmd.blitImage(image, // src image vk::ImageLayout::eTransferSrcOptimal, // src layout @@ -222,27 +254,27 @@ bool BlitGenerateMipmapCommandVK::Encode(CommandEncoderVK& encoder) const { // Transition all mip levels to shader read. The base mip level has a // different "old" layout than the rest now. InsertImageMemoryBarrier( - cmd, // command buffer - image, // image - vk::AccessFlagBits::eTransferRead, // src access mask - vk::AccessFlagBits::eShaderRead, // dst access mask - vk::ImageLayout::eTransferSrcOptimal, // old layout - vk::ImageLayout::eShaderReadOnlyOptimal, // new layout - vk::PipelineStageFlagBits::eTransfer, // src stage - vk::PipelineStageFlagBits::eAllGraphics, // dst stage - 0u // mip level + cmd, // command buffer + image, // image + vk::AccessFlagBits::eTransferWrite, // src access mask + vk::AccessFlagBits::eShaderRead, // dst access mask + vk::ImageLayout::eTransferSrcOptimal, // old layout + vk::ImageLayout::eShaderReadOnlyOptimal, // new layout + vk::PipelineStageFlagBits::eTransfer, // src stage + vk::PipelineStageFlagBits::eFragmentShader, // dst stage + 0u // mip level ); InsertImageMemoryBarrier( - cmd, // command buffer - image, // image - vk::AccessFlagBits::eTransferRead, // src access mask - vk::AccessFlagBits::eShaderRead, // dst access mask - vk::ImageLayout::eTransferDstOptimal, // old layout - vk::ImageLayout::eShaderReadOnlyOptimal, // new layout - vk::PipelineStageFlagBits::eTransfer, // src stage - vk::PipelineStageFlagBits::eAllGraphics, // dst stage - 1u, // mip level - mip_count - 1 // mip level count + cmd, // command buffer + image, // image + vk::AccessFlagBits::eTransferWrite, // src access mask + vk::AccessFlagBits::eShaderRead, // dst access mask + vk::ImageLayout::eTransferDstOptimal, // old layout + vk::ImageLayout::eShaderReadOnlyOptimal, // new layout + vk::PipelineStageFlagBits::eTransfer, // src stage + vk::PipelineStageFlagBits::eFragmentShader, // dst stage + 1u, // mip level + mip_count - 1 // mip level count ); // We modified the layouts of this image from underneath it. Tell it its new diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc index 645ae1cf70375..048dc3592c645 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -4,39 +4,337 @@ #include "impeller/renderer/backend/vulkan/capabilities_vk.h" +#include + +#include "impeller/base/validation.h" #include "impeller/renderer/backend/vulkan/vk.h" namespace impeller { -CapabilitiesVK::CapabilitiesVK() { - for (const auto& ext : vk::enumerateInstanceExtensionProperties().value) { - extensions_.insert(ext.extensionName); +static constexpr const char* kInstanceLayer = "ImpellerInstance"; + +CapabilitiesVK::CapabilitiesVK(bool enable_validations) + : enable_validations_(enable_validations) { + auto extensions = vk::enumerateInstanceExtensionProperties(); + auto layers = vk::enumerateInstanceLayerProperties(); + + if (extensions.result != vk::Result::eSuccess || + layers.result != vk::Result::eSuccess) { + return; } - for (const auto& layer : vk::enumerateInstanceLayerProperties().value) { - layers_.insert(layer.layerName); + for (const auto& ext : extensions.value) { + exts_[kInstanceLayer].insert(ext.extensionName); + } + + for (const auto& layer : layers.value) { + const std::string layer_name = layer.layerName; + auto layer_exts = vk::enumerateInstanceExtensionProperties(layer_name); + if (layer_exts.result != vk::Result::eSuccess) { + return; + } + for (const auto& layer_ext : layer_exts.value) { + exts_[layer_name].insert(layer_ext.extensionName); + } } + + is_valid_ = true; } CapabilitiesVK::~CapabilitiesVK() = default; -bool CapabilitiesVK::HasExtension(const std::string& extension) const { - return extensions_.count(extension) == 1u; +bool CapabilitiesVK::IsValid() const { + return is_valid_; +} + +bool CapabilitiesVK::AreValidationsEnabled() const { + return enable_validations_; +} + +std::optional> CapabilitiesVK::GetRequiredLayers() + const { + std::vector required; + + if (enable_validations_) { + if (!HasLayer("VK_LAYER_KHRONOS_validation")) { + VALIDATION_LOG + << "Requested validations but the validation layer was not found."; + return std::nullopt; + } + required.push_back("VK_LAYER_KHRONOS_validation"); + } + + return required; +} + +std::optional> +CapabilitiesVK::GetRequiredInstanceExtensions() const { + std::vector required; + + if (!HasExtension("VK_KHR_surface")) { + // Swapchain support is required and this is a dependency of + // VK_KHR_swapchain. + VALIDATION_LOG << "Could not find the surface extension."; + return std::nullopt; + } + required.push_back("VK_KHR_surface"); + + auto has_wsi = false; + if (HasExtension("VK_MVK_macos_surface")) { + required.push_back("VK_MVK_macos_surface"); + has_wsi = true; + } + + if (HasExtension("VK_EXT_metal_surface")) { + required.push_back("VK_EXT_metal_surface"); + has_wsi = true; + } + + if (HasExtension("VK_KHR_portability_enumeration")) { + required.push_back("VK_KHR_portability_enumeration"); + has_wsi = true; + } + + if (HasExtension("VK_KHR_win32_surface")) { + required.push_back("VK_KHR_win32_surface"); + has_wsi = true; + } + + if (HasExtension("VK_KHR_android_surface")) { + required.push_back("VK_KHR_android_surface"); + has_wsi = true; + } + + if (HasExtension("VK_KHR_xcb_surface")) { + required.push_back("VK_KHR_xcb_surface"); + has_wsi = true; + } + + if (HasExtension("VK_KHR_xlib_surface")) { + required.push_back("VK_KHR_xlib_surface"); + has_wsi = true; + } + + if (HasExtension("VK_KHR_wayland_surface")) { + required.push_back("VK_KHR_wayland_surface"); + has_wsi = true; + } + + if (!has_wsi) { + // Don't really care which WSI extension there is as long there is at least + // one. + VALIDATION_LOG << "Could not find a WSI extension."; + return std::nullopt; + } + + if (enable_validations_) { + if (!HasExtension("VK_EXT_debug_utils")) { + VALIDATION_LOG << "Requested validations but could not find the " + "VK_EXT_debug_utils extension."; + return std::nullopt; + } + required.push_back("VK_EXT_debug_utils"); + + if (!HasExtension("VK_EXT_validation_features")) { + VALIDATION_LOG << "Requested validations but could not find the " + "VK_EXT_validation_features extension."; + return std::nullopt; + } + required.push_back("VK_EXT_validation_features"); + } + + return required; +} + +std::optional> +CapabilitiesVK::GetRequiredDeviceExtensions( + const vk::PhysicalDevice& physical_device) const { + auto device_extensions = physical_device.enumerateDeviceExtensionProperties(); + if (device_extensions.result != vk::Result::eSuccess) { + return std::nullopt; + } + + std::set exts; + for (const auto& device_extension : device_extensions.value) { + exts.insert(device_extension.extensionName); + } + + std::vector required; + + if (exts.find("VK_KHR_swapchain") == exts.end()) { + VALIDATION_LOG << "Device does not support the swapchain extension."; + return std::nullopt; + } + required.push_back("VK_KHR_swapchain"); + + // Required for non-conformant implementations like MoltenVK. + if (exts.find("VK_KHR_portability_subset") != exts.end()) { + required.push_back("VK_KHR_portability_subset"); + } + return required; +} + +static bool HasSuitableColorFormat(const vk::PhysicalDevice& device, + vk::Format format) { + const auto props = device.getFormatProperties(format); + // This needs to be more comprehensive. + return !!(props.optimalTilingFeatures & + vk::FormatFeatureFlagBits::eColorAttachment); +} + +static bool HasSuitableDepthStencilFormat(const vk::PhysicalDevice& device, + vk::Format format) { + const auto props = device.getFormatProperties(format); + return !!(props.optimalTilingFeatures & + vk::FormatFeatureFlagBits::eDepthStencilAttachment); +} + +static bool PhysicalDeviceSupportsRequiredFormats( + const vk::PhysicalDevice& device) { + const auto has_color_format = + HasSuitableColorFormat(device, vk::Format::eB8G8R8A8Unorm); + const auto has_depth_stencil_format = + HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint) || + HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint); + return has_color_format && has_depth_stencil_format; +} + +static bool HasRequiredProperties(const vk::PhysicalDevice& physical_device) { + auto properties = physical_device.getProperties(); + if (!(properties.limits.framebufferColorSampleCounts & + (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) { + return false; + } + return true; +} + +static bool HasRequiredQueues(const vk::PhysicalDevice& physical_device) { + auto queue_flags = vk::QueueFlags{}; + for (const auto& queue : physical_device.getQueueFamilyProperties()) { + if (queue.queueCount == 0) { + continue; + } + queue_flags |= queue.queueFlags; + } + return static_cast(queue_flags & + (vk::QueueFlagBits::eGraphics | + vk::QueueFlagBits::eCompute | + vk::QueueFlagBits::eTransfer)); +} + +std::optional +CapabilitiesVK::GetRequiredDeviceFeatures( + const vk::PhysicalDevice& device) const { + if (!PhysicalDeviceSupportsRequiredFormats(device)) { + VALIDATION_LOG << "Device doesn't support the required formats."; + return std::nullopt; + } + + if (!HasRequiredProperties(device)) { + VALIDATION_LOG << "Device doesn't support the required properties."; + return std::nullopt; + } + + if (!HasRequiredQueues(device)) { + VALIDATION_LOG << "Device doesn't support the required queues."; + return std::nullopt; + } + + if (!GetRequiredDeviceExtensions(device).has_value()) { + VALIDATION_LOG << "Device doesn't support the required queues."; + return std::nullopt; + } + + const auto device_features = device.getFeatures(); + + vk::PhysicalDeviceFeatures required; + + // We require this for enabling wireframes in the playground. But its not + // necessarily a big deal if we don't have this feature. + required.fillModeNonSolid = device_features.fillModeNonSolid; + + return required; } bool CapabilitiesVK::HasLayer(const std::string& layer) const { - return layers_.count(layer) == 1u; + for (const auto& [found_layer, exts] : exts_) { + if (found_layer == layer) { + return true; + } + } + return false; } -bool CapabilitiesVK::HasLayerExtension(const std::string& layer, - const std::string& extension) { - for (const auto& ext : - vk::enumerateInstanceExtensionProperties(layer).value) { - if (std::string{ext.extensionName} == extension) { +bool CapabilitiesVK::HasExtension(const std::string& ext) const { + for (const auto& [layer, exts] : exts_) { + if (exts.find(ext) != exts.end()) { return true; } } return false; } +bool CapabilitiesVK::SetDevice(const vk::PhysicalDevice& device) { + if (HasSuitableColorFormat(device, vk::Format::eB8G8R8A8Unorm)) { + color_format_ = PixelFormat::kB8G8R8A8UNormInt; + } else { + return false; + } + + if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) { + depth_stencil_format_ = PixelFormat::kS8UInt; + } else if (HasSuitableDepthStencilFormat(device, + vk::Format::eD24UnormS8Uint)) { + depth_stencil_format_ = PixelFormat::kD32FloatS8UInt; + } else { + return false; + } + return true; +} + +// |Capabilities| +bool CapabilitiesVK::HasThreadingRestrictions() const { + return false; +} + +// |Capabilities| +bool CapabilitiesVK::SupportsOffscreenMSAA() const { + return true; +} + +// |Capabilities| +bool CapabilitiesVK::SupportsSSBO() const { + return false; +} + +// |Capabilities| +bool CapabilitiesVK::SupportsTextureToTextureBlits() const { + return true; +} + +// |Capabilities| +bool CapabilitiesVK::SupportsFramebufferFetch() const { + return false; +} + +// |Capabilities| +bool CapabilitiesVK::SupportsCompute() const { + return false; +} + +// |Capabilities| +bool CapabilitiesVK::SupportsComputeSubgroups() const { + return false; +} + +// |Capabilities| +PixelFormat CapabilitiesVK::GetDefaultColorFormat() const { + return color_format_; +} + +// |Capabilities| +PixelFormat CapabilitiesVK::GetDefaultStencilFormat() const { + return depth_stencil_format_; +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.h b/impeller/renderer/backend/vulkan/capabilities_vk.h index 2b62e05e498ca..21545e4384bc7 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.h +++ b/impeller/renderer/backend/vulkan/capabilities_vk.h @@ -4,29 +4,81 @@ #pragma once +#include #include #include +#include #include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/vk.h" +#include "impeller/renderer/capabilities.h" namespace impeller { -class CapabilitiesVK { +class ContextVK; + +//------------------------------------------------------------------------------ +/// @brief The Vulkan layers and extensions wrangler. +/// +class CapabilitiesVK final : public Capabilities { public: - CapabilitiesVK(); + CapabilitiesVK(bool enable_validations = false); ~CapabilitiesVK(); - bool HasExtension(const std::string& extension) const; + bool IsValid() const; - bool HasLayer(const std::string& layer) const; + bool AreValidationsEnabled() const; + + std::optional> GetRequiredLayers() const; + + std::optional> GetRequiredInstanceExtensions() const; + + std::optional> GetRequiredDeviceExtensions( + const vk::PhysicalDevice& physical_device) const; + + std::optional GetRequiredDeviceFeatures( + const vk::PhysicalDevice& physical_device) const; + + [[nodiscard]] bool SetDevice(const vk::PhysicalDevice& physical_device); + + // |Capabilities| + bool HasThreadingRestrictions() const override; + + // |Capabilities| + bool SupportsOffscreenMSAA() const override; - bool HasLayerExtension(const std::string& layer, - const std::string& extension); + // |Capabilities| + bool SupportsSSBO() const override; + + // |Capabilities| + bool SupportsTextureToTextureBlits() const override; + + // |Capabilities| + bool SupportsFramebufferFetch() const override; + + // |Capabilities| + bool SupportsCompute() const override; + + // |Capabilities| + bool SupportsComputeSubgroups() const override; + + // |Capabilities| + PixelFormat GetDefaultColorFormat() const override; + + // |Capabilities| + PixelFormat GetDefaultStencilFormat() const override; private: - std::set extensions_; - std::set layers_; + const bool enable_validations_; + std::map> exts_; + PixelFormat color_format_ = PixelFormat::kUnknown; + PixelFormat depth_stencil_format_ = PixelFormat::kUnknown; + bool is_valid_ = false; + + bool HasExtension(const std::string& ext) const; + + bool HasLayer(const std::string& layer) const; FML_DISALLOW_COPY_AND_ASSIGN(CapabilitiesVK); }; diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.cc b/impeller/renderer/backend/vulkan/command_encoder_vk.cc index 6fbf12950f49b..a65d61249aedd 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.cc +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.cc @@ -5,31 +5,91 @@ #include "impeller/renderer/backend/vulkan/command_encoder_vk.h" #include "flutter/fml/closure.h" +#include "flutter/fml/trace_event.h" #include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h" +#include "impeller/renderer/backend/vulkan/texture_vk.h" namespace impeller { +class TrackedObjectsVK { + public: + explicit TrackedObjectsVK(const vk::Device& device, + const std::shared_ptr& pool) + : desc_pool_(device) { + if (!pool) { + return; + } + auto buffer = pool->CreateGraphicsCommandBuffer(); + if (!buffer) { + return; + } + pool_ = pool; + buffer_ = std::move(buffer); + is_valid_ = true; + } + + ~TrackedObjectsVK() { + if (!buffer_) { + return; + } + auto pool = pool_.lock(); + if (!pool) { + VALIDATION_LOG + << "Command pool died before a command buffer could be recycled."; + return; + } + pool->CollectGraphicsCommandBuffer(std::move(buffer_)); + } + + bool IsValid() const { return is_valid_; } + + void Track(std::shared_ptr object) { + tracked_objects_.insert(std::move(object)); + } + + void Track(std::shared_ptr buffer) { + tracked_buffers_.insert(std::move(buffer)); + } + + void Track(std::shared_ptr texture) { + tracked_textures_.insert(std::move(texture)); + } + + vk::CommandBuffer GetCommandBuffer() const { return *buffer_; } + + DescriptorPoolVK& GetDescriptorPool() { return desc_pool_; } + + private: + DescriptorPoolVK desc_pool_; + std::weak_ptr pool_; + vk::UniqueCommandBuffer buffer_; + std::set> tracked_objects_; + std::set> tracked_buffers_; + std::set> tracked_textures_; + bool is_valid_ = false; + + FML_DISALLOW_COPY_AND_ASSIGN(TrackedObjectsVK); +}; + CommandEncoderVK::CommandEncoderVK(vk::Device device, vk::Queue queue, - vk::CommandPool pool) { - vk::CommandBufferAllocateInfo alloc_info; - alloc_info.commandPool = pool; - alloc_info.commandBufferCount = 1u; - alloc_info.level = vk::CommandBufferLevel::ePrimary; - auto [result, buffers] = device.allocateCommandBuffersUnique(alloc_info); - if (result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create command buffer."; + const std::shared_ptr& pool, + std::shared_ptr fence_waiter) + : fence_waiter_(std::move(fence_waiter)), + tracked_objects_(std::make_shared(device, pool)) { + if (!fence_waiter_ || !tracked_objects_->IsValid()) { return; } vk::CommandBufferBeginInfo begin_info; begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; - if (buffers[0]->begin(begin_info) != vk::Result::eSuccess) { + if (tracked_objects_->GetCommandBuffer().begin(begin_info) != + vk::Result::eSuccess) { VALIDATION_LOG << "Could not begin command buffer."; return; } device_ = device; queue_ = queue; - command_buffer_ = std::move(buffers[0]); is_valid_ = true; } @@ -47,39 +107,40 @@ bool CommandEncoderVK::Submit() { // Success or failure, you only get to submit once. fml::ScopedCleanupClosure reset([&]() { Reset(); }); - if (command_buffer_->end() != vk::Result::eSuccess) { + InsertDebugMarker("QueueSubmit"); + + auto command_buffer = GetCommandBuffer(); + + if (command_buffer.end() != vk::Result::eSuccess) { return false; } auto [fence_result, fence] = device_.createFenceUnique({}); if (fence_result != vk::Result::eSuccess) { return false; } + vk::SubmitInfo submit_info; - submit_info.setCommandBuffers(*command_buffer_); + std::vector buffers = {command_buffer}; + submit_info.setCommandBuffers(buffers); if (queue_.submit(submit_info, *fence) != vk::Result::eSuccess) { return false; } - if (device_.waitForFences( - *fence, // fences - true, // wait all - std::numeric_limits::max() // timeout (ns) - ) != vk::Result::eSuccess) { - return false; - } - return true; + return fence_waiter_->AddFence( + std::move(fence), [tracked_objects = std::move(tracked_objects_)] { + // Nothing to do, we just drop the tracked objects on the floor. + }); } -const vk::CommandBuffer& CommandEncoderVK::GetCommandBuffer() const { - return *command_buffer_; +vk::CommandBuffer CommandEncoderVK::GetCommandBuffer() const { + if (tracked_objects_) { + return tracked_objects_->GetCommandBuffer(); + } + return {}; } void CommandEncoderVK::Reset() { - command_buffer_.reset(); - - tracked_objects_.clear(); - tracked_buffers_.clear(); - tracked_textures_.clear(); + tracked_objects_.reset(); queue_ = nullptr; device_ = nullptr; @@ -87,34 +148,82 @@ void CommandEncoderVK::Reset() { } bool CommandEncoderVK::Track(std::shared_ptr object) { - tracked_objects_.push_back(std::move(object)); + if (!IsValid()) { + return false; + } + tracked_objects_->Track(std::move(object)); return true; } bool CommandEncoderVK::Track(std::shared_ptr buffer) { - tracked_buffers_.emplace_back(std::move(buffer)); + if (!IsValid()) { + return false; + } + tracked_objects_->Track(std::move(buffer)); return true; } -bool CommandEncoderVK::Track(std::shared_ptr texture) { - tracked_textures_.emplace_back(std::move(texture)); +bool CommandEncoderVK::Track(std::shared_ptr texture) { + if (!IsValid()) { + return false; + } + tracked_objects_->Track(std::move(texture)); return true; } +bool CommandEncoderVK::Track(const std::shared_ptr& texture) { + if (!texture) { + return false; + } + return Track(TextureVK::Cast(*texture).GetTextureSource()); +} + +std::optional CommandEncoderVK::AllocateDescriptorSet( + const vk::DescriptorSetLayout& layout) { + if (!IsValid()) { + return std::nullopt; + } + return tracked_objects_->GetDescriptorPool().AllocateDescriptorSet(layout); +} + void CommandEncoderVK::PushDebugGroup(const char* label) const { - if (!vk::HasValidationLayers() || !command_buffer_) { + if (!HasValidationLayers()) { return; } vk::DebugUtilsLabelEXT label_info; label_info.pLabelName = label; - command_buffer_->beginDebugUtilsLabelEXT(label_info); + if (auto command_buffer = GetCommandBuffer()) { + command_buffer.beginDebugUtilsLabelEXT(label_info); + } + if (queue_) { + queue_.beginDebugUtilsLabelEXT(label_info); + } } void CommandEncoderVK::PopDebugGroup() const { - if (!vk::HasValidationLayers() || !command_buffer_) { + if (!HasValidationLayers()) { return; } - command_buffer_->endDebugUtilsLabelEXT(); + if (auto command_buffer = GetCommandBuffer()) { + command_buffer.endDebugUtilsLabelEXT(); + } + if (queue_) { + queue_.endDebugUtilsLabelEXT(); + } +} + +void CommandEncoderVK::InsertDebugMarker(const char* label) const { + if (!HasValidationLayers()) { + return; + } + vk::DebugUtilsLabelEXT label_info; + label_info.pLabelName = label; + if (auto command_buffer = GetCommandBuffer()) { + command_buffer.insertDebugUtilsLabelEXT(label_info); + } + if (queue_) { + queue_.insertDebugUtilsLabelEXT(label_info); + } } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.h b/impeller/renderer/backend/vulkan/command_encoder_vk.h index 66ac47f39bf68..8db33b50c1a7d 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.h +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.h @@ -4,9 +4,12 @@ #pragma once -#include +#include +#include #include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/command_pool_vk.h" +#include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h" #include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" @@ -15,6 +18,9 @@ namespace impeller { class ContextVK; class DeviceBuffer; class Texture; +class TextureSourceVK; +class TrackedObjectsVK; +class FenceWaiterVK; class CommandEncoderVK { public: @@ -28,26 +34,35 @@ class CommandEncoderVK { bool Track(std::shared_ptr buffer); - bool Track(std::shared_ptr texture); + bool Track(const std::shared_ptr& texture); - const vk::CommandBuffer& GetCommandBuffer() const; + bool Track(std::shared_ptr texture); + + vk::CommandBuffer GetCommandBuffer() const; void PushDebugGroup(const char* label) const; void PopDebugGroup() const; + void InsertDebugMarker(const char* label) const; + + std::optional AllocateDescriptorSet( + const vk::DescriptorSetLayout& layout); + private: friend class ContextVK; vk::Device device_ = {}; vk::Queue queue_ = {}; - vk::UniqueCommandBuffer command_buffer_; - std::vector> tracked_objects_; - std::vector> tracked_buffers_; - std::vector> tracked_textures_; + + std::shared_ptr fence_waiter_; + std::shared_ptr tracked_objects_; bool is_valid_ = false; - CommandEncoderVK(vk::Device device, vk::Queue queue, vk::CommandPool pool); + CommandEncoderVK(vk::Device device, + vk::Queue queue, + const std::shared_ptr& pool, + std::shared_ptr fence_waiter); void Reset(); diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.cc b/impeller/renderer/backend/vulkan/command_pool_vk.cc new file mode 100644 index 0000000000000..5ed2ed404807c --- /dev/null +++ b/impeller/renderer/backend/vulkan/command_pool_vk.cc @@ -0,0 +1,135 @@ +// 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 "impeller/renderer/backend/vulkan/command_pool_vk.h" + +#include +#include +#include + +#include "flutter/fml/thread_local.h" +#include "impeller/base/thread.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" + +namespace impeller { + +using CommandPoolMap = + std::map>; + +FML_THREAD_LOCAL fml::ThreadLocalUniquePtr tls_command_pool; + +static Mutex g_all_pools_mutex; +static std::unordered_map>> + g_all_pools IPLR_GUARDED_BY(g_all_pools_mutex); + +std::shared_ptr CommandPoolVK::GetThreadLocal( + const ContextVK* context) { + if (!context) { + return nullptr; + } + if (tls_command_pool.get() == nullptr) { + tls_command_pool.reset(new CommandPoolMap()); + } + CommandPoolMap& pool_map = *tls_command_pool.get(); + auto found = pool_map.find(context); + if (found != pool_map.end() && found->second->IsValid()) { + return found->second; + } + auto pool = std::shared_ptr(new CommandPoolVK(context)); + if (!pool->IsValid()) { + return nullptr; + } + pool_map[context] = pool; + { + Lock pool_lock(g_all_pools_mutex); + g_all_pools[context].push_back(pool); + } + return pool; +} + +void CommandPoolVK::ClearAllPools(const ContextVK* context) { + Lock pool_lock(g_all_pools_mutex); + if (auto found = g_all_pools.find(context); found != g_all_pools.end()) { + for (auto& weak_pool : found->second) { + auto pool = weak_pool.lock(); + if (!pool) { + // The pool has already died because the thread died. + continue; + } + // The pool is reset but its reference in the TLS map remains till the + // thread dies. + pool->Reset(); + } + g_all_pools.erase(found); + } +} + +CommandPoolVK::CommandPoolVK(const ContextVK* context) + : owner_id_(std::this_thread::get_id()) { + vk::CommandPoolCreateInfo pool_info; + + pool_info.queueFamilyIndex = context->GetGraphicsQueueInfo().index; + pool_info.flags = vk::CommandPoolCreateFlagBits::eTransient; + auto pool = context->GetDevice().createCommandPoolUnique(pool_info); + if (pool.result != vk::Result::eSuccess) { + return; + } + + device_ = context->GetDevice(); + graphics_pool_ = std::move(pool.value); + is_valid_ = true; +} + +CommandPoolVK::~CommandPoolVK() = default; + +bool CommandPoolVK::IsValid() const { + return is_valid_; +} + +void CommandPoolVK::Reset() { + Lock lock(buffers_to_collect_mutex_); + GarbageCollectBuffersIfAble(); + graphics_pool_.reset(); + is_valid_ = false; +} + +vk::CommandPool CommandPoolVK::GetGraphicsCommandPool() const { + return graphics_pool_.get(); +} + +vk::UniqueCommandBuffer CommandPoolVK::CreateGraphicsCommandBuffer() { + if (std::this_thread::get_id() != owner_id_) { + return {}; + } + { + Lock lock(buffers_to_collect_mutex_); + GarbageCollectBuffersIfAble(); + } + vk::CommandBufferAllocateInfo alloc_info; + alloc_info.commandPool = graphics_pool_.get(); + alloc_info.commandBufferCount = 1u; + alloc_info.level = vk::CommandBufferLevel::ePrimary; + auto [result, buffers] = device_.allocateCommandBuffersUnique(alloc_info); + if (result != vk::Result::eSuccess) { + return {}; + } + return std::move(buffers[0]); +} + +void CommandPoolVK::CollectGraphicsCommandBuffer( + vk::UniqueCommandBuffer buffer) { + Lock lock(buffers_to_collect_mutex_); + buffers_to_collect_.insert(MakeSharedVK(std::move(buffer))); + GarbageCollectBuffersIfAble(); +} + +void CommandPoolVK::GarbageCollectBuffersIfAble() { + if (std::this_thread::get_id() != owner_id_) { + return; + } + buffers_to_collect_.clear(); +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.h b/impeller/renderer/backend/vulkan/command_pool_vk.h new file mode 100644 index 0000000000000..7399e22686075 --- /dev/null +++ b/impeller/renderer/backend/vulkan/command_pool_vk.h @@ -0,0 +1,55 @@ +// 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. + +#pragma once + +#include +#include +#include + +#include "flutter/fml/macros.h" +#include "impeller/base/thread.h" +#include "impeller/renderer/backend/vulkan/shared_object_vk.h" +#include "impeller/renderer/backend/vulkan/vk.h" + +namespace impeller { + +class ContextVK; + +class CommandPoolVK { + public: + static std::shared_ptr GetThreadLocal( + const ContextVK* context); + + static void ClearAllPools(const ContextVK* context); + + ~CommandPoolVK(); + + bool IsValid() const; + + void Reset(); + + vk::CommandPool GetGraphicsCommandPool() const; + + vk::UniqueCommandBuffer CreateGraphicsCommandBuffer(); + + void CollectGraphicsCommandBuffer(vk::UniqueCommandBuffer buffer); + + private: + const std::thread::id owner_id_; + vk::Device device_ = {}; + vk::UniqueCommandPool graphics_pool_; + Mutex buffers_to_collect_mutex_; + std::set> buffers_to_collect_ + IPLR_GUARDED_BY(buffers_to_collect_mutex_); + bool is_valid_ = false; + + explicit CommandPoolVK(const ContextVK* context); + + void GarbageCollectBuffersIfAble() IPLR_REQUIRES(buffers_to_collect_mutex_); + + FML_DISALLOW_COPY_AND_ASSIGN(CommandPoolVK); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index a7974915d1f81..c394f3627b353 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -20,156 +20,30 @@ #include "impeller/renderer/backend/vulkan/capabilities_vk.h" #include "impeller/renderer/backend/vulkan/command_buffer_vk.h" #include "impeller/renderer/backend/vulkan/command_encoder_vk.h" +#include "impeller/renderer/backend/vulkan/command_pool_vk.h" +#include "impeller/renderer/backend/vulkan/debug_report_vk.h" +#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/surface_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" -#include "impeller/renderer/device_capabilities.h" +#include "impeller/renderer/capabilities.h" VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE -namespace { - -// TODO(csg): Mimic vulkan_debug_report.cc for prettier reports. -VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsMessengerCallback( - VkDebugUtilsMessageSeverityFlagBitsEXT severity, - VkDebugUtilsMessageTypeFlagsEXT type, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData) { - // There isn't stable messageIdNumber for this validation failure. - if (strstr(pCallbackData->pMessageIdName, - "CoreValidation-Shader-OutputNotConsumed") != nullptr) { - return VK_FALSE; - } - - if (pCallbackData->messageIdNumber == static_cast(0x82ae5050)) { - // This is a real error but we can't fix it due to our headers being too - // old. More more details see: - // https://vulkan.lunarg.com/doc/view/1.3.224.1/mac/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465 - // This validation error currently only trips on macOS due to the use of - // texture swizzles. - return VK_FALSE; - } - - const auto prefix = impeller::vk::to_string( - impeller::vk::DebugUtilsMessageSeverityFlagBitsEXT(severity)); - // Just so that the log doesn't say FML_DCHECK(false). - constexpr bool kVulkanValidationFailure = false; - FML_DCHECK(kVulkanValidationFailure) - << prefix << "[" << pCallbackData->messageIdNumber << "][" - << pCallbackData->pMessageIdName << "] : " << pCallbackData->pMessage; - - // The return value of this callback controls whether the Vulkan call that - // caused the validation message will be aborted or not We return VK_TRUE as - // we DO want Vulkan calls that cause a validation message to abort - return VK_TRUE; -} - -} // namespace - namespace impeller { -namespace vk { +// TODO(csg): Fix this after caps are reworked. +static bool gHasValidationLayers = false; bool HasValidationLayers() { - auto capabilities = std::make_unique(); - return capabilities->HasLayer(kKhronosValidationLayerName); -} - -} // namespace vk - -static std::set kRequiredDeviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, -#if FML_OS_MACOSX - "VK_KHR_portability_subset", // For Molten VK. No define present in header. -#endif -}; - -std::vector kRequiredWSIInstanceExtensions = { -#if FML_OS_WIN - "VK_KHR_win32_surface", -#elif FML_OS_ANDROID - "VK_KHR_android_surface", -#elif FML_OS_LINUX - "VK_KHR_xcb_surface", - "VK_KHR_xlib_surface", - "VK_KHR_wayland_surface", -#elif FML_OS_MACOSX - "VK_EXT_metal_surface", -#endif -}; - -#if FML_OS_MACOSX -static const char* MVK_MACOS_SURFACE_EXT = "VK_MVK_macos_surface"; -#endif - -static bool HasRequiredQueues(const vk::PhysicalDevice& device) { - auto present_flags = vk::QueueFlags{}; - for (const auto& queue : device.getQueueFamilyProperties()) { - if (queue.queueCount == 0) { - continue; - } - present_flags |= queue.queueFlags; - } - return static_cast(present_flags & - (vk::QueueFlagBits::eGraphics | - vk::QueueFlagBits::eCompute | - vk::QueueFlagBits::eTransfer)); -} - -static std::vector HasRequiredExtensions( - const vk::PhysicalDevice& device) { - std::set exts; - std::vector missing; - for (const auto& ext : device.enumerateDeviceExtensionProperties().value) { - exts.insert(ext.extensionName); - } - for (const auto& req_ext : kRequiredDeviceExtensions) { - if (exts.count(req_ext) != 1u) { - missing.push_back(req_ext); - } - } - return missing; -} - -static vk::PhysicalDeviceFeatures GetRequiredPhysicalDeviceFeatures() { - vk::PhysicalDeviceFeatures features; -#ifndef NDEBUG - features.setRobustBufferAccess(true); -#endif // NDEBUG - return features; -}; - -static bool HasRequiredProperties(const vk::PhysicalDevice& device) { - auto properties = device.getProperties(); - if (!(properties.limits.framebufferColorSampleCounts & - (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) { - return false; - } - return true; -} - -static bool IsPhysicalDeviceCompatible(const vk::PhysicalDevice& device) { - if (!HasRequiredQueues(device)) { - FML_LOG(ERROR) << "Device doesn't have required queues."; - return false; - } - auto missing_exts = HasRequiredExtensions(device); - if (!missing_exts.empty()) { - FML_LOG(ERROR) << "Device doesn't have required extensions: " - << fml::Join(missing_exts, ", "); - return false; - } - if (!HasRequiredProperties(device)) { - FML_LOG(ERROR) << "Device doesn't have required properties."; - return false; - } - return true; + return gHasValidationLayers; } static std::optional PickPhysicalDevice( + const CapabilitiesVK& caps, const vk::Instance& instance) { for (const auto& device : instance.enumeratePhysicalDevices().value) { - if (IsPhysicalDeviceCompatible(device)) { + if (caps.GetRequiredDeviceFeatures(device).has_value()) { return device; } } @@ -219,27 +93,37 @@ std::shared_ptr ContextVK::Create( const std::shared_ptr& pipeline_cache_data, std::shared_ptr worker_task_runner, const std::string& label) { - auto context = std::shared_ptr(new ContextVK( - proc_address_callback, // - shader_libraries_data, // - pipeline_cache_data, // - std::move(worker_task_runner), // - label // - )); + auto context = std::shared_ptr(new ContextVK()); + context->Setup(proc_address_callback, // + shader_libraries_data, // + pipeline_cache_data, // + std::move(worker_task_runner), // + label // + ); if (!context->IsValid()) { return nullptr; } return context; } -ContextVK::ContextVK( +ContextVK::ContextVK() = default; + +ContextVK::~ContextVK() { + if (device_) { + [[maybe_unused]] auto result = device_->waitIdle(); + } + CommandPoolVK::ClearAllPools(this); +} + +void ContextVK::Setup( PFN_vkGetInstanceProcAddr proc_address_callback, const std::vector>& shader_libraries_data, const std::shared_ptr& pipeline_cache_data, std::shared_ptr worker_task_runner, - const std::string& label) - : worker_task_runner_(std::move(worker_task_runner)) { - TRACE_EVENT0("impeller", "ContextVK::Create"); + const std::string& label) { + TRACE_EVENT0("impeller", "ContextVK::Setup"); + + worker_task_runner_ = std::move(worker_task_runner); if (!worker_task_runner_) { VALIDATION_LOG << "Invalid worker task runner."; @@ -249,95 +133,41 @@ ContextVK::ContextVK( auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER; dispatcher.init(proc_address_callback); - auto capabilities = std::make_unique(); + auto caps = std::shared_ptr(new CapabilitiesVK()); - vk::InstanceCreateFlags instance_flags = {}; - std::vector enabled_layers; - std::vector enabled_extensions; - -// This define may need to change into a runtime check if using SwiftShader on -// Mac. -#if FML_OS_MACOSX - //---------------------------------------------------------------------------- - /// Ensure we need any Vulkan implementations that are not fully compliant - /// with the requested Vulkan Spec. This is necessary for MoltenVK on Mac - /// (backed by Metal). - /// - if (!capabilities->HasExtension( - VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) { - VALIDATION_LOG << "On Mac: Required extension " - << VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME - << " absent."; + if (!caps->IsValid()) { + VALIDATION_LOG << "Could not determine device capabilities."; return; } - // Molten VK on Mac is not fully compliant. We opt into being OK not getting - // back a fully compliant version of a Vulkan implementation. - enabled_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR; - if (!capabilities->HasExtension( - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - VALIDATION_LOG << "On Mac: Required extension " - << VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - << " absent."; - return; - } - // This is dependency of VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME which - // is a requirement for opting into Molten VK on Mac. - enabled_extensions.push_back( - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + gHasValidationLayers = caps->AreValidationsEnabled(); - // Required for glfw macOS surfaces. - if (!capabilities->HasExtension(MVK_MACOS_SURFACE_EXT)) { - VALIDATION_LOG << "On Mac: Required extension " << MVK_MACOS_SURFACE_EXT - << " absent."; - return; - } - enabled_extensions.push_back(MVK_MACOS_SURFACE_EXT); -#endif // FML_OS_MACOSX + auto enabled_layers = caps->GetRequiredLayers(); + auto enabled_extensions = caps->GetRequiredInstanceExtensions(); - //---------------------------------------------------------------------------- - /// Even though this is a WSI responsibility, require the surface extension - /// for swapchains. - if (!capabilities->HasExtension(VK_KHR_SURFACE_EXTENSION_NAME)) { - VALIDATION_LOG << "Required extension " VK_KHR_SURFACE_EXTENSION_NAME - << " absent."; + if (!enabled_layers.has_value() || !enabled_extensions.has_value()) { + VALIDATION_LOG << "Device has insufficient capabilities."; return; } - enabled_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - //---------------------------------------------------------------------------- - /// Enable WSI Instance Extensions. Having any one of these is sufficient. - /// - bool has_wsi_extensions = false; - for (const auto& wsi_ext : kRequiredWSIInstanceExtensions) { - if (capabilities->HasExtension(wsi_ext)) { - enabled_extensions.push_back(wsi_ext.c_str()); - has_wsi_extensions = true; - } + vk::InstanceCreateFlags instance_flags = {}; + + if (std::find(enabled_extensions.value().begin(), + enabled_extensions.value().end(), + "VK_KHR_portability_enumeration") != + enabled_extensions.value().end()) { + instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR; } - if (!has_wsi_extensions) { - VALIDATION_LOG - << "Instance doesn't have any of the required WSI extensions: " - << fml::Join(kRequiredWSIInstanceExtensions, ", "); - return; + + std::vector enabled_layers_c; + std::vector enabled_extensions_c; + + for (const auto& layer : enabled_layers.value()) { + enabled_layers_c.push_back(layer.c_str()); } - //---------------------------------------------------------------------------- - /// Enable any and all validation as well as debug toggles. - /// - auto has_debug_utils = false; - if (vk::HasValidationLayers()) { - enabled_layers.push_back(vk::kKhronosValidationLayerName); - if (capabilities->HasLayerExtension(vk::kKhronosValidationLayerName, - VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { - enabled_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - has_debug_utils = true; - } else { - FML_LOG(ERROR) << "Vulkan debug utils are absent."; - } - } else { - FML_LOG(ERROR) << "Vulkan validation layers are absent."; + for (const auto& ext : enabled_extensions.value()) { + enabled_extensions_c.push_back(ext.c_str()); } vk::ApplicationInfo application_info; @@ -347,52 +177,50 @@ ContextVK::ContextVK( application_info.setPEngineName("Impeller"); application_info.setPApplicationName("Impeller"); + std::vector enabled_validations = { + // vk::ValidationFeatureEnableEXT::eBestPractices, + // vk::ValidationFeatureEnableEXT::eSynchronizationValidation, + }; + + vk::ValidationFeaturesEXT validation; + validation.setEnabledValidationFeatures(enabled_validations); + vk::InstanceCreateInfo instance_info; - instance_info.setPEnabledLayerNames(enabled_layers); - instance_info.setPEnabledExtensionNames(enabled_extensions); + if (caps->AreValidationsEnabled()) { + instance_info.pNext = &validation; + } + instance_info.setPEnabledLayerNames(enabled_layers_c); + instance_info.setPEnabledExtensionNames(enabled_extensions_c); instance_info.setPApplicationInfo(&application_info); instance_info.setFlags(instance_flags); auto instance = vk::createInstanceUnique(instance_info); if (instance.result != vk::Result::eSuccess) { - FML_LOG(ERROR) << "Could not create instance: " + VALIDATION_LOG << "Could not create instance: " << vk::to_string(instance.result); return; } dispatcher.init(instance.value.get()); - vk::UniqueDebugUtilsMessengerEXT debug_messenger; - - if (has_debug_utils) { - vk::DebugUtilsMessengerCreateInfoEXT debug_messenger_info; - debug_messenger_info.messageSeverity = - vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | - vk::DebugUtilsMessageSeverityFlagBitsEXT::eError; - debug_messenger_info.messageType = - vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | - vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | - vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation; - debug_messenger_info.pUserData = nullptr; - debug_messenger_info.pfnUserCallback = DebugUtilsMessengerCallback; - - auto debug_messenger_result = - instance.value->createDebugUtilsMessengerEXTUnique( - debug_messenger_info); - - if (debug_messenger_result.result != vk::Result::eSuccess) { - FML_LOG(ERROR) << "Could not create debug messenger: " - << vk::to_string(debug_messenger_result.result); - return; - } + //---------------------------------------------------------------------------- + /// Setup the debug report. + /// + /// Do this as early as possible since we could use the debug report from + /// initialization issues. + /// + auto debug_report = + std::make_unique(*caps, instance.value.get()); - debug_messenger = std::move(debug_messenger_result.value); + if (!debug_report->IsValid()) { + VALIDATION_LOG << "Could not setup debug report."; + return; } //---------------------------------------------------------------------------- /// Pick the physical device. /// - auto physical_device = PickPhysicalDevice(instance.value.get()); + auto physical_device = PickPhysicalDevice(*caps, instance.value.get()); if (!physical_device.has_value()) { VALIDATION_LOG << "No valid Vulkan device found."; return; @@ -408,29 +236,44 @@ ContextVK::ContextVK( auto compute_queue = PickQueue(physical_device.value(), vk::QueueFlagBits::eCompute); - physical_device_ = physical_device.value(); - if (!graphics_queue.has_value() || !transfer_queue.has_value() || !compute_queue.has_value()) { VALIDATION_LOG << "Could not pick device queues."; return; } - std::vector required_extensions; - for (const auto& ext : kRequiredDeviceExtensions) { - required_extensions.push_back(ext.data()); + //---------------------------------------------------------------------------- + /// Create the logical device. + /// + auto enabled_device_extensions = + caps->GetRequiredDeviceExtensions(physical_device.value()); + if (!enabled_device_extensions.has_value()) { + // This shouldn't happen since we already did device selection. But doesn't + // hurt to check again. + return; + } + + std::vector enabled_device_extensions_c; + for (const auto& ext : enabled_device_extensions.value()) { + enabled_device_extensions_c.push_back(ext.c_str()); } const auto queue_create_infos = GetQueueCreateInfos( {graphics_queue.value(), compute_queue.value(), transfer_queue.value()}); - const auto required_features = GetRequiredPhysicalDeviceFeatures(); + const auto required_features = + caps->GetRequiredDeviceFeatures(physical_device.value()); + if (!required_features.has_value()) { + // This shouldn't happen since the device can't be picked if this was not + // true. But doesn't hurt to check. + return; + } vk::DeviceCreateInfo device_info; device_info.setQueueCreateInfos(queue_create_infos); - device_info.setPEnabledExtensionNames(required_extensions); - device_info.setPEnabledFeatures(&required_features); + device_info.setPEnabledExtensionNames(enabled_device_extensions_c); + device_info.setPEnabledFeatures(&required_features.value()); // Device layers are deprecated and ignored. auto device = physical_device->createDeviceUnique(device_info); @@ -439,6 +282,14 @@ ContextVK::ContextVK( return; } + if (!caps->SetDevice(physical_device.value())) { + VALIDATION_LOG << "Capabilities could not be updated."; + return; + } + + //---------------------------------------------------------------------------- + /// Create the allocator. + /// auto allocator = std::shared_ptr(new AllocatorVK( weak_from_this(), // application_info.apiVersion, // @@ -479,6 +330,9 @@ ContextVK::ContextVK( return; } + //---------------------------------------------------------------------------- + /// Setup the work queues. + /// auto work_queue = WorkQueueCommon::Create(); if (!work_queue) { @@ -487,47 +341,12 @@ ContextVK::ContextVK( } //---------------------------------------------------------------------------- - /// Setup the command pool. + /// Create the fence waiter. /// - vk::CommandPoolCreateInfo graphics_command_pool_info; - graphics_command_pool_info.queueFamilyIndex = graphics_queue->index; - graphics_command_pool_info.flags = vk::CommandPoolCreateFlagBits::eTransient; - auto graphics_command_pool = - device.value->createCommandPoolUnique(graphics_command_pool_info); - if (graphics_command_pool.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create graphics command pool."; - return; - } - - //---------------------------------------------------------------------------- - /// Setup the descriptor pool. This needs to be dynamic but we just allocate a - /// jumbo pool and hope for the best. - /// - constexpr size_t kPoolSize = 1024 * 3; - - std::vector pool_sizes = { - {vk::DescriptorType::eSampler, kPoolSize}, - {vk::DescriptorType::eCombinedImageSampler, kPoolSize}, - {vk::DescriptorType::eSampledImage, kPoolSize}, - {vk::DescriptorType::eStorageImage, kPoolSize}, - {vk::DescriptorType::eUniformTexelBuffer, kPoolSize}, - {vk::DescriptorType::eStorageTexelBuffer, kPoolSize}, - {vk::DescriptorType::eUniformBuffer, kPoolSize}, - {vk::DescriptorType::eStorageBuffer, kPoolSize}, - {vk::DescriptorType::eUniformBufferDynamic, kPoolSize}, - {vk::DescriptorType::eStorageBufferDynamic, kPoolSize}, - {vk::DescriptorType::eInputAttachment, kPoolSize}, - }; - vk::DescriptorPoolCreateInfo pool_info = { - vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, // flags - static_cast(pool_sizes.size() * kPoolSize), // max sets - static_cast(pool_sizes.size()), // pool sizes count - pool_sizes.data() // pool sizes - }; - - auto descriptor_pool = device.value->createDescriptorPoolUnique(pool_info); - if (descriptor_pool.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Unable to create a descriptor pool"; + auto fence_waiter = + std::shared_ptr(new FenceWaiterVK(device.value.get())); + if (!fence_waiter->IsValid()) { + VALIDATION_LOG << "Could not create fence waiter."; return; } @@ -535,7 +354,8 @@ ContextVK::ContextVK( /// All done! /// instance_ = std::move(instance.value); - debug_messenger_ = std::move(debug_messenger); + debug_report_ = std::move(debug_report); + physical_device_ = physical_device.value(); device_ = std::move(device.value); allocator_ = std::move(allocator); shader_library_ = std::move(shader_library); @@ -548,27 +368,21 @@ ContextVK::ContextVK( device_->getQueue(compute_queue->family, compute_queue->index); transfer_queue_ = device_->getQueue(transfer_queue->family, transfer_queue->index); - device_capabilities_ = - DeviceCapabilitiesBuilder() - .SetHasThreadingRestrictions(false) - .SetSupportsOffscreenMSAA(true) - .SetSupportsSSBO(false) - .SetSupportsTextureToTextureBlits(true) - .SetSupportsFramebufferFetch(false) - .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) - .SetDefaultStencilFormat(PixelFormat::kS8UInt) - // TODO(110622): detect this and enable. - .SetSupportsCompute(false, false) - .Build(); - graphics_command_pool_ = std::move(graphics_command_pool.value); - descriptor_pool_ = std::move(descriptor_pool.value); + graphics_queue_info_ = graphics_queue.value(); + compute_queue_info_ = compute_queue.value(); + transfer_queue_info_ = transfer_queue.value(); + device_capabilities_ = std::move(caps); + fence_waiter_ = std::move(fence_waiter); is_valid_ = true; -} -ContextVK::~ContextVK() { - if (device_) { - [[maybe_unused]] auto result = device_->waitIdle(); - } + //---------------------------------------------------------------------------- + /// Label all the relevant objects. This happens after setup so that the debug + /// messengers have had a chance to be setup. + /// + SetDebugName(device_.get(), device_.get(), "ImpellerDevice"); + SetDebugName(device_.get(), graphics_queue_, "ImpellerGraphicsQ"); + SetDebugName(device_.get(), compute_queue_, "ImpellerComputeQ"); + SetDebugName(device_.get(), transfer_queue_, "ImpellerTransferQ"); } bool ContextVK::IsValid() const { @@ -597,9 +411,13 @@ std::shared_ptr ContextVK::GetWorkQueue() const { } std::shared_ptr ContextVK::CreateCommandBuffer() const { + auto encoder = CreateGraphicsCommandEncoder(); + if (!encoder) { + return nullptr; + } return std::shared_ptr( - new CommandBufferVK(shared_from_this(), // - CreateGraphicsCommandEncoder()) // + new CommandBufferVK(shared_from_this(), // + std::move(encoder)) // ); } @@ -646,37 +464,37 @@ bool ContextVK::SetWindowSurface(vk::UniqueSurfaceKHR surface) { return true; } -PixelFormat ContextVK::GetColorAttachmentPixelFormat() const { - return swapchain_ ? ToPixelFormat(swapchain_->GetSurfaceFormat()) - : PixelFormat::kB8G8R8A8UNormInt; -} - -const IDeviceCapabilities& ContextVK::GetDeviceCapabilities() const { - return *device_capabilities_; +const std::shared_ptr& ContextVK::GetCapabilities() const { + return device_capabilities_; } vk::Queue ContextVK::GetGraphicsQueue() const { return graphics_queue_; } -vk::CommandPool ContextVK::GetGraphicsCommandPool() const { - return *graphics_command_pool_; -} - -vk::DescriptorPool ContextVK::GetDescriptorPool() const { - return *descriptor_pool_; +QueueVK ContextVK::GetGraphicsQueueInfo() const { + return graphics_queue_info_; } vk::PhysicalDevice ContextVK::GetPhysicalDevice() const { return physical_device_; } +std::shared_ptr ContextVK::GetFenceWaiter() const { + return fence_waiter_; +} + std::unique_ptr ContextVK::CreateGraphicsCommandEncoder() const { + auto tls_pool = CommandPoolVK::GetThreadLocal(this); + if (!tls_pool) { + return nullptr; + } auto encoder = std::unique_ptr(new CommandEncoderVK( - *device_, // - graphics_queue_, // - *graphics_command_pool_ // + *device_, // + graphics_queue_, // + tls_pool, // + fence_waiter_ // )); if (!encoder->IsValid()) { return nullptr; diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 3cd22bb490b2b..089417971b960 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -15,24 +15,18 @@ #include "impeller/renderer/backend/vulkan/shader_library_vk.h" #include "impeller/renderer/backend/vulkan/swapchain_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" +#include "impeller/renderer/capabilities.h" #include "impeller/renderer/context.h" -#include "impeller/renderer/device_capabilities.h" #include "impeller/renderer/formats.h" #include "impeller/renderer/surface.h" namespace impeller { -namespace vk { - -// TODO(csg): Move this to its own TU for validations. -constexpr const char* kKhronosValidationLayerName = - "VK_LAYER_KHRONOS_validation"; - bool HasValidationLayers(); -} // namespace vk - class CommandEncoderVK; +class DebugReportVK; +class FenceWaiterVK; class ContextVK final : public Context, public BackendCast { public: @@ -64,14 +58,11 @@ class ContextVK final : public Context, public BackendCast { // |Context| std::shared_ptr CreateCommandBuffer() const override; - // |Context| - PixelFormat GetColorAttachmentPixelFormat() const override; - // |Context| std::shared_ptr GetWorkQueue() const override; // |Context| - const IDeviceCapabilities& GetDeviceCapabilities() const override; + const std::shared_ptr& GetCapabilities() const override; template bool SetDebugName(T handle, std::string_view label) const { @@ -82,22 +73,19 @@ class ContextVK final : public Context, public BackendCast { static bool SetDebugName(vk::Device device, T handle, std::string_view label) { - if (!vk::HasValidationLayers()) { + if (!HasValidationLayers()) { // No-op if validation layers are not enabled. return true; } - uint64_t handle_ptr = - reinterpret_cast(static_cast(handle)); + auto c_handle = static_cast(handle); - std::string label_str = std::string(label); - auto ret = device.setDebugUtilsObjectNameEXT( - vk::DebugUtilsObjectNameInfoEXT() - .setObjectType(T::objectType) - .setObjectHandle(handle_ptr) - .setPObjectName(label_str.c_str())); + vk::DebugUtilsObjectNameInfoEXT info; + info.objectType = T::objectType; + info.pObjectName = label.data(); + info.objectHandle = reinterpret_cast(c_handle); - if (ret != vk::Result::eSuccess) { + if (device.setDebugUtilsObjectNameEXT(info) != vk::Result::eSuccess) { VALIDATION_LOG << "Unable to set debug name: " << label; return false; } @@ -119,16 +107,16 @@ class ContextVK final : public Context, public BackendCast { vk::Queue GetGraphicsQueue() const; - vk::CommandPool GetGraphicsCommandPool() const; - - vk::DescriptorPool GetDescriptorPool() const; + QueueVK GetGraphicsQueueInfo() const; vk::PhysicalDevice GetPhysicalDevice() const; + std::shared_ptr GetFenceWaiter() const; + private: std::shared_ptr worker_task_runner_; vk::UniqueInstance instance_; - vk::UniqueDebugUtilsMessengerEXT debug_messenger_; + std::unique_ptr debug_report_; vk::PhysicalDevice physical_device_; vk::UniqueDevice device_; std::shared_ptr allocator_; @@ -138,14 +126,19 @@ class ContextVK final : public Context, public BackendCast { vk::Queue graphics_queue_ = {}; vk::Queue compute_queue_ = {}; vk::Queue transfer_queue_ = {}; + QueueVK graphics_queue_info_ = {}; + QueueVK compute_queue_info_ = {}; + QueueVK transfer_queue_info_ = {}; std::shared_ptr swapchain_; std::shared_ptr work_queue_; - std::unique_ptr device_capabilities_; - vk::UniqueCommandPool graphics_command_pool_; - vk::UniqueDescriptorPool descriptor_pool_; + std::shared_ptr device_capabilities_; + std::shared_ptr fence_waiter_; + bool is_valid_ = false; - ContextVK( + ContextVK(); + + void Setup( PFN_vkGetInstanceProcAddr proc_address_callback, const std::vector>& shader_libraries_data, const std::shared_ptr& pipeline_cache_data, diff --git a/impeller/renderer/backend/vulkan/debug_report_vk.cc b/impeller/renderer/backend/vulkan/debug_report_vk.cc new file mode 100644 index 0000000000000..c538245aba50d --- /dev/null +++ b/impeller/renderer/backend/vulkan/debug_report_vk.cc @@ -0,0 +1,189 @@ +// 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 "impeller/renderer/backend/vulkan/debug_report_vk.h" + +#include "impeller/renderer/backend/vulkan/capabilities_vk.h" + +namespace impeller { + +DebugReportVK::DebugReportVK(const CapabilitiesVK& caps, + const vk::Instance& instance) { + if (!caps.AreValidationsEnabled()) { + is_valid_ = true; + return; + } + + vk::DebugUtilsMessengerCreateInfoEXT messenger_info; + messenger_info.messageSeverity = + vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | + vk::DebugUtilsMessageSeverityFlagBitsEXT::eError; + messenger_info.messageType = + vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | + vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | + vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation; + messenger_info.pUserData = this; + messenger_info.pfnUserCallback = DebugUtilsMessengerCallback; + + auto messenger = instance.createDebugUtilsMessengerEXTUnique(messenger_info); + + if (messenger.result != vk::Result::eSuccess) { + FML_LOG(ERROR) << "Could not create debug messenger: " + << vk::to_string(messenger.result); + return; + } + + messenger_ = std::move(messenger.value); + is_valid_ = true; +} + +DebugReportVK::~DebugReportVK() = default; + +bool DebugReportVK::IsValid() const { + return is_valid_; +} + +static std::string JoinLabels(const VkDebugUtilsLabelEXT* labels, + size_t count) { + std::stringstream stream; + for (size_t i = 0u; i < count; i++) { + stream << labels[i].pLabelName; + if (i != count - 1u) { + stream << ", "; + } + } + return stream.str(); +} + +static std::string JoinVKDebugUtilsObjectNameInfoEXT( + const VkDebugUtilsObjectNameInfoEXT* names, + size_t count) { + std::stringstream stream; + for (size_t i = 0u; i < count; i++) { + stream << vk::to_string(vk::ObjectType(names[i].objectType)) << " [" + << names[i].objectHandle << "] ["; + if (names[i].pObjectName != nullptr) { + stream << names[i].pObjectName; + } else { + stream << "UNNAMED"; + } + stream << "]"; + if (i != count - 1u) { + stream << ", "; + } + } + return stream.str(); +} + +VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportVK::DebugUtilsMessengerCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT type, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* debug_report) { + auto result = + reinterpret_cast(debug_report) + ->OnDebugCallback( + static_cast( + severity), // + static_cast(type), // + callback_data // + ); + switch (result) { + case Result::kContinue: + return VK_FALSE; + case Result::kAbort: + return VK_TRUE; + } + return VK_FALSE; +} + +DebugReportVK::Result DebugReportVK::OnDebugCallback( + vk::DebugUtilsMessageSeverityFlagBitsEXT severity, + vk::DebugUtilsMessageTypeFlagsEXT type, + const VkDebugUtilsMessengerCallbackDataEXT* data) { + // Issue in older versions of the SDK. + // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/3554 + if (strstr(data->pMessageIdName, "CoreValidation-Shader-OutputNotConsumed") != + nullptr) { + return Result::kContinue; + } + + // This is a real error but we can't fix it due to our headers being too + // old. More more details see: + // https://vulkan.lunarg.com/doc/view/1.3.224.1/mac/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465 + // This validation error currently only trips on macOS due to the use of + // texture swizzles. + if (data->messageIdNumber == static_cast(0x82ae5050)) { + return Result::kContinue; + } + + std::vector> items; + + items.emplace_back("Severity", vk::to_string(severity)); + + items.emplace_back("Type", vk::to_string(type)); + + if (data->pMessageIdName) { + items.emplace_back("ID Name", data->pMessageIdName); + } + + items.emplace_back("ID Number", std::to_string(data->messageIdNumber)); + + if (auto queues = JoinLabels(data->pQueueLabels, data->queueLabelCount); + !queues.empty()) { + items.emplace_back("Queue Breadcrumbs", std::move(queues)); + } else { + items.emplace_back("Queue Breadcrumbs", "[NONE]"); + } + + if (auto cmd_bufs = JoinLabels(data->pCmdBufLabels, data->cmdBufLabelCount); + !cmd_bufs.empty()) { + items.emplace_back("CMD Buffer Breadcrumbs", std::move(cmd_bufs)); + } else { + items.emplace_back("CMD Buffer Breadcrumbs", "[NONE]"); + } + + if (auto related = + JoinVKDebugUtilsObjectNameInfoEXT(data->pObjects, data->objectCount); + !related.empty()) { + items.emplace_back("Related Objects", std::move(related)); + } + + if (data->pMessage) { + items.emplace_back("Trigger", data->pMessage); + } + + size_t padding = 0; + + for (const auto& item : items) { + padding = std::max(padding, item.first.size()); + } + + padding += 1; + + std::stringstream stream; + + stream << std::endl; + + stream << "--- Vulkan Debug Report ----------------------------------------"; + + stream << std::endl; + + for (const auto& item : items) { + stream << "| " << std::setw(static_cast(padding)) << item.first + << std::setw(0) << ": " << item.second << std::endl; + } + + stream << "-----------------------------------------------------------------"; + + if (type == vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance) { + FML_LOG(INFO) << stream.str(); + } else { + VALIDATION_LOG << stream.str(); + } + + return Result::kAbort; +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/debug_report_vk.h b/impeller/renderer/backend/vulkan/debug_report_vk.h new file mode 100644 index 0000000000000..387d7f6d28c20 --- /dev/null +++ b/impeller/renderer/backend/vulkan/debug_report_vk.h @@ -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. + +#pragma once + +#include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/vk.h" + +namespace impeller { + +class CapabilitiesVK; + +class DebugReportVK { + public: + DebugReportVK(const CapabilitiesVK& caps, const vk::Instance& instance); + + ~DebugReportVK(); + + bool IsValid() const; + + private: + vk::UniqueDebugUtilsMessengerEXT messenger_; + bool is_valid_ = false; + + enum class Result { + kContinue, + kAbort, + }; + + Result OnDebugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity, + vk::DebugUtilsMessageTypeFlagsEXT type, + const VkDebugUtilsMessengerCallbackDataEXT* data); + + static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsMessengerCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT type, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* user_data); + + FML_DISALLOW_COPY_AND_ASSIGN(DebugReportVK); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc b/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc new file mode 100644 index 0000000000000..5fb1ef74fdcd9 --- /dev/null +++ b/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc @@ -0,0 +1,74 @@ +// 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 "impeller/renderer/backend/vulkan/descriptor_pool_vk.h" + +#include "flutter/fml/trace_event.h" +#include "impeller/base/allocation.h" + +namespace impeller { + +DescriptorPoolVK::DescriptorPoolVK(vk::Device device) : device_(device) {} + +DescriptorPoolVK::~DescriptorPoolVK() = default; + +static vk::UniqueDescriptorPool CreatePool(const vk::Device& device, + uint32_t pool_count) { + TRACE_EVENT0("impeller", "CreateDescriptorPool"); + std::vector pools = { + {vk::DescriptorType::eCombinedImageSampler, pool_count}, + {vk::DescriptorType::eUniformBuffer, pool_count}, + }; + + vk::DescriptorPoolCreateInfo pool_info; + pool_info.setMaxSets(pools.size() * pool_count); + pool_info.setPoolSizes(pools); + + auto [result, pool] = device.createDescriptorPoolUnique(pool_info); + if (result != vk::Result::eSuccess) { + VALIDATION_LOG << "Unable to create a descriptor pool"; + } + return std::move(pool); +} + +std::optional DescriptorPoolVK::AllocateDescriptorSet( + const vk::DescriptorSetLayout& layout) { + auto pool = GetDescriptorPool(); + if (!pool) { + return std::nullopt; + } + vk::DescriptorSetAllocateInfo set_info; + set_info.setDescriptorPool(pool.value()); + set_info.setSetLayouts(layout); + auto [result, sets] = device_.allocateDescriptorSets(set_info); + if (result == vk::Result::eErrorOutOfPoolMemory) { + return GrowPool() ? AllocateDescriptorSet(layout) : std::nullopt; + } + if (result != vk::Result::eSuccess) { + VALIDATION_LOG << "Could not allocate descriptor sets: " + << vk::to_string(result); + return std::nullopt; + } + return sets[0]; +} + +std::optional DescriptorPoolVK::GetDescriptorPool() { + if (pools_.empty()) { + return GrowPool() ? GetDescriptorPool() : std::nullopt; + } + return *pools_.back(); +} + +bool DescriptorPoolVK::GrowPool() { + const auto new_pool_size = Allocation::NextPowerOfTwoSize(pool_size_ + 1u); + auto new_pool = CreatePool(device_, new_pool_size); + if (!new_pool) { + return false; + } + pool_size_ = new_pool_size; + pools_.push(std::move(new_pool)); + return true; +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/descriptor_pool_vk.h b/impeller/renderer/backend/vulkan/descriptor_pool_vk.h new file mode 100644 index 0000000000000..4af9c0bc8b13a --- /dev/null +++ b/impeller/renderer/backend/vulkan/descriptor_pool_vk.h @@ -0,0 +1,48 @@ +// 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. + +#pragma once + +#include +#include + +#include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/vk.h" + +namespace impeller { + +//------------------------------------------------------------------------------ +/// @brief A short-lived dynamically-sized descriptor pool. Descriptors +/// from this pool don't need to be freed individually. Instead, the +/// pool must be collected after all the descriptors allocated from +/// it are done being used. +/// +/// The pool or it's descriptors may not be accessed from multiple +/// threads. +/// +/// Encoders create pools as necessary as they have the same +/// threading and lifecycle restrictions. +/// +class DescriptorPoolVK { + public: + explicit DescriptorPoolVK(vk::Device device); + + ~DescriptorPoolVK(); + + std::optional AllocateDescriptorSet( + const vk::DescriptorSetLayout& layout); + + private: + const vk::Device device_; + uint32_t pool_size_ = 31u; + std::queue pools_; + + std::optional GetDescriptorPool(); + + bool GrowPool(); + + FML_DISALLOW_COPY_AND_ASSIGN(DescriptorPoolVK); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.cc b/impeller/renderer/backend/vulkan/device_buffer_vk.cc index e38c63fa688fc..e9859ff9390a5 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.cc @@ -67,7 +67,7 @@ bool DeviceBufferVK::SetLabel(const std::string& label, Range range) { return SetLabel(label); } -vk::Buffer DeviceBufferVK::GetVKBufferHandle() const { +vk::Buffer DeviceBufferVK::GetBuffer() const { return buffer_; } diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.h b/impeller/renderer/backend/vulkan/device_buffer_vk.h index 132be608c3617..2f579c13a1e9c 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.h +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.h @@ -26,7 +26,7 @@ class DeviceBufferVK final : public DeviceBuffer, // |DeviceBuffer| ~DeviceBufferVK() override; - vk::Buffer GetVKBufferHandle() const; + vk::Buffer GetBuffer() const; private: friend class AllocatorVK; diff --git a/impeller/renderer/backend/vulkan/fence_waiter_vk.cc b/impeller/renderer/backend/vulkan/fence_waiter_vk.cc new file mode 100644 index 0000000000000..06c4c094cbf67 --- /dev/null +++ b/impeller/renderer/backend/vulkan/fence_waiter_vk.cc @@ -0,0 +1,108 @@ +// 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 "impeller/renderer/backend/vulkan/fence_waiter_vk.h" + +#include + +#include "flutter/fml/thread.h" + +namespace impeller { + +FenceWaiterVK::FenceWaiterVK(vk::Device device) : device_(device) { + waiter_thread_ = std::make_unique([&]() { Main(); }); + is_valid_ = true; +} + +FenceWaiterVK::~FenceWaiterVK() { + Terminate(); + if (waiter_thread_) { + waiter_thread_->join(); + } +} + +bool FenceWaiterVK::IsValid() const { + return is_valid_; +} + +bool FenceWaiterVK::AddFence(vk::UniqueFence fence, + const fml::closure& callback) { + if (!IsValid() || !fence || !callback) { + return false; + } + { + std::scoped_lock lock(wait_set_mutex_); + wait_set_[MakeSharedVK(std::move(fence))] = callback; + } + wait_set_cv_.notify_one(); + return true; +} + +void FenceWaiterVK::Main() { + fml::Thread::SetCurrentThreadName( + fml::Thread::ThreadConfig{"io.flutter.impeller.fence_waiter"}); + + using namespace std::literals::chrono_literals; + + while (true) { + std::unique_lock lock(wait_set_mutex_); + + wait_set_cv_.wait(lock, [&]() { return !wait_set_.empty() || terminate_; }); + + auto wait_set = TrimAndCreateWaitSetLocked(); + + lock.unlock(); + + if (!wait_set.has_value()) { + break; + } + if (wait_set->empty()) { + continue; + } + + auto result = device_.waitForFences( + wait_set->size(), // fences count + wait_set->data(), // fences + false, // wait for all + std::chrono::nanoseconds{100ms}.count() // timeout (ns) + ); + if (!(result == vk::Result::eSuccess || result == vk::Result::eTimeout)) { + break; + } + } +} + +std::optional> +FenceWaiterVK::TrimAndCreateWaitSetLocked() { + if (terminate_) { + return std::nullopt; + } + std::vector fences; + fences.reserve(wait_set_.size()); + for (auto it = wait_set_.begin(); it != wait_set_.end();) { + switch (device_.getFenceStatus(it->first->Get())) { + case vk::Result::eSuccess: // Signalled. + it->second(); + it = wait_set_.erase(it); + break; + case vk::Result::eNotReady: // Un-signalled. + fences.push_back(it->first->Get()); + it++; + break; + default: + return std::nullopt; + } + } + return fences; +} + +void FenceWaiterVK::Terminate() { + { + std::scoped_lock lock(wait_set_mutex_); + terminate_ = true; + } + wait_set_cv_.notify_one(); +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/fence_waiter_vk.h b/impeller/renderer/backend/vulkan/fence_waiter_vk.h new file mode 100644 index 0000000000000..0f5087f0d2514 --- /dev/null +++ b/impeller/renderer/backend/vulkan/fence_waiter_vk.h @@ -0,0 +1,53 @@ +// 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. + +#pragma once + +#include +#include +#include +#include +#include + +#include "flutter/fml/closure.h" +#include "flutter/fml/macros.h" +#include "impeller/base/thread.h" +#include "impeller/renderer/backend/vulkan/shared_object_vk.h" +#include "impeller/renderer/backend/vulkan/vk.h" + +namespace impeller { + +class ContextVK; + +class FenceWaiterVK { + public: + ~FenceWaiterVK(); + + bool IsValid() const; + + void Terminate(); + + bool AddFence(vk::UniqueFence fence, const fml::closure& callback); + + private: + friend class ContextVK; + + const vk::Device device_; + std::unique_ptr waiter_thread_; + std::mutex wait_set_mutex_; + std::condition_variable wait_set_cv_; + std::unordered_map, fml::closure> wait_set_; + bool terminate_ = false; + bool is_valid_ = false; + + explicit FenceWaiterVK(vk::Device device); + + void Main(); + + std::optional> TrimAndCreateWaitSetLocked(); + + FML_DISALLOW_COPY_AND_ASSIGN(FenceWaiterVK); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/formats_vk.h b/impeller/renderer/backend/vulkan/formats_vk.h index 83ea4acc463b0..64e8f5a6c447d 100644 --- a/impeller/renderer/backend/vulkan/formats_vk.h +++ b/impeller/renderer/backend/vulkan/formats_vk.h @@ -6,7 +6,6 @@ #include "flutter/fml/macros.h" #include "impeller/renderer/backend/vulkan/vk.h" -#include "impeller/renderer/descriptor_set_layout.h" #include "impeller/renderer/formats.h" #include "impeller/renderer/shader_types.h" #include "vulkan/vulkan_enums.hpp" @@ -205,6 +204,8 @@ constexpr vk::SampleCountFlagBits ToVKSampleCount(SampleCount sample_count) { case SampleCount::kCount4: return vk::SampleCountFlagBits::e4; } + + FML_UNREACHABLE(); } constexpr vk::Filter ToVKSamplerMinMagFilter(MinMagFilter filter) { @@ -269,7 +270,7 @@ constexpr vk::DescriptorSetLayoutBinding ToVKDescriptorSetLayoutBinding( const DescriptorSetLayout& layout) { vk::DescriptorSetLayoutBinding binding; binding.binding = layout.binding; - binding.descriptorCount = layout.descriptor_count; + binding.descriptorCount = 1u; vk::DescriptorType desc_type = vk::DescriptorType(); switch (layout.descriptor_type) { case DescriptorType::kSampledImage: @@ -546,9 +547,60 @@ constexpr uint32_t ToArrayLayerCount(TextureType type) { FML_UNREACHABLE(); } +constexpr vk::ImageViewType ToVKImageViewType(TextureType type) { + switch (type) { + case TextureType::kTexture2D: + case TextureType::kTexture2DMultisample: + return vk::ImageViewType::e2D; + case TextureType::kTextureCube: + return vk::ImageViewType::eCube; + } + FML_UNREACHABLE(); +} + +constexpr vk::ImageCreateFlags ToVKImageCreateFlags(TextureType type) { + switch (type) { + case TextureType::kTexture2D: + case TextureType::kTexture2DMultisample: + return {}; + case TextureType::kTextureCube: + return vk::ImageCreateFlagBits::eCubeCompatible; + } + FML_UNREACHABLE(); +} + vk::PipelineDepthStencilStateCreateInfo ToVKPipelineDepthStencilStateCreateInfo( std::optional depth, std::optional front, std::optional back); +constexpr vk::ImageAspectFlags ToImageAspectFlags(vk::ImageLayout layout) { + switch (layout) { + case vk::ImageLayout::eColorAttachmentOptimal: + case vk::ImageLayout::eShaderReadOnlyOptimal: + case vk::ImageLayout::eTransferSrcOptimal: + case vk::ImageLayout::eTransferDstOptimal: + case vk::ImageLayout::ePresentSrcKHR: + return vk::ImageAspectFlagBits::eColor; + case vk::ImageLayout::eDepthAttachmentOptimal: + return vk::ImageAspectFlagBits::eDepth; + case vk::ImageLayout::eStencilAttachmentOptimal: + return vk::ImageAspectFlagBits::eStencil; + default: + FML_DLOG(INFO) << "Unknown layout to determine aspect: " + << vk::to_string(layout); + return vk::ImageAspectFlagBits::eNone; + } + FML_UNREACHABLE(); +} + +struct LayoutTransition { + vk::CommandBuffer cmd_buffer = {}; + vk::ImageLayout new_layout = vk::ImageLayout::eUndefined; + vk::PipelineStageFlags src_stage = vk::PipelineStageFlagBits::eNone; + vk::AccessFlags src_access = vk::AccessFlagBits::eNone; + vk::PipelineStageFlags dst_stage = vk::PipelineStageFlagBits::eNone; + vk::AccessFlags dst_access = vk::AccessFlagBits::eNone; +}; + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc index 1cc9e2303612d..6016a5bd59836 100644 --- a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc +++ b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc @@ -53,54 +53,6 @@ bool PipelineLibraryVK::IsValid() const { return is_valid_; } -// |PipelineLibrary| -PipelineFuture PipelineLibraryVK::GetPipeline( - PipelineDescriptor descriptor) { - Lock lock(pipelines_mutex_); - if (auto found = pipelines_.find(descriptor); found != pipelines_.end()) { - return found->second; - } - - if (!IsValid()) { - return { - descriptor, - RealizedFuture>>(nullptr)}; - } - - auto promise = std::make_shared< - std::promise>>>(); - auto pipeline_future = - PipelineFuture{descriptor, promise->get_future()}; - pipelines_[descriptor] = pipeline_future; - - auto weak_this = weak_from_this(); - - worker_task_runner_->PostTask([descriptor, weak_this, promise]() { - auto thiz = weak_this.lock(); - if (!thiz) { - promise->set_value(nullptr); - VALIDATION_LOG << "Pipeline library was collected before the pipeline " - "could be created."; - return; - } - auto pipeline_create_info = - PipelineLibraryVK::Cast(thiz.get())->CreatePipeline(descriptor); - promise->set_value(std::make_shared( - weak_this, descriptor, std::move(pipeline_create_info))); - }); - - return pipeline_future; -} - -// |PipelineLibrary| -PipelineFuture PipelineLibraryVK::GetPipeline( - ComputePipelineDescriptor descriptor) { - auto promise = std::make_shared< - std::promise>>>(); - promise->set_value(nullptr); - return {descriptor, promise->get_future()}; -} - //------------------------------------------------------------------------------ /// @brief Creates an attachment description that does just enough to /// ensure render pass compatibility with the pass associated later @@ -123,17 +75,6 @@ static vk::AttachmentDescription CreatePlaceholderAttachmentDescription( ); } -// |PipelineLibrary| -void PipelineLibraryVK::RemovePipelinesWithEntryPoint( - std::shared_ptr function) { - Lock lock(pipelines_mutex_); - - fml::erase_if(pipelines_, [&](auto item) { - return item->first.GetEntrypointForStage(function->GetStage()) - ->IsEqual(*function); - }); -} - //---------------------------------------------------------------------------- /// Render Pass /// We are NOT going to use the same render pass with the framebuffer (later) @@ -145,8 +86,8 @@ void PipelineLibraryVK::RemovePipelinesWithEntryPoint( /// StencilAttachmentDescriptor, and, DepthAttachmentDescriptor. /// Right now, these are placeholders. /// -vk::UniqueRenderPass PipelineLibraryVK::CreateRenderPass( - const PipelineDescriptor& desc) { +static vk::UniqueRenderPass CreateRenderPass(const vk::Device& device, + const PipelineDescriptor& desc) { std::vector attachments; std::vector color_refs; @@ -190,7 +131,7 @@ vk::UniqueRenderPass PipelineLibraryVK::CreateRenderPass( render_pass_desc.setPSubpasses(&subpass_desc); render_pass_desc.setSubpassCount(1u); - auto [result, pass] = device_.createRenderPassUnique(render_pass_desc); + auto [result, pass] = device.createRenderPassUnique(render_pass_desc); if (result != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to create render pass for pipeline '" << desc.GetLabel() << "'. Error: " << vk::to_string(result); @@ -210,7 +151,7 @@ constexpr vk::FrontFace ToVKFrontFace(WindingOrder order) { FML_UNREACHABLE(); } -std::unique_ptr PipelineLibraryVK::CreatePipeline( +std::unique_ptr PipelineLibraryVK::CreatePipeline( const PipelineDescriptor& desc) { TRACE_EVENT0("flutter", __FUNCTION__); vk::GraphicsPipelineCreateInfo pipeline_info; @@ -298,7 +239,7 @@ std::unique_ptr PipelineLibraryVK::CreatePipeline( blend_state.setAttachments(attachment_blend_state); pipeline_info.setPColorBlendState(&blend_state); - auto render_pass = CreateRenderPass(desc); + auto render_pass = CreateRenderPass(device_, desc); if (render_pass) { pipeline_info.setBasePipelineHandle(VK_NULL_HANDLE); pipeline_info.setSubpass(0); @@ -341,33 +282,31 @@ std::unique_ptr PipelineLibraryVK::CreatePipeline( //---------------------------------------------------------------------------- /// Pipeline Layout a.k.a the descriptor sets and uniforms. /// - std::vector bindings = {}; + std::vector desc_bindings; for (auto layout : desc.GetVertexDescriptor()->GetDescriptorSetLayouts()) { auto vk_desc_layout = ToVKDescriptorSetLayoutBinding(layout); - bindings.push_back(vk_desc_layout); + desc_bindings.push_back(vk_desc_layout); } - vk::DescriptorSetLayoutCreateInfo descriptor_set_create; - descriptor_set_create.setBindings(bindings); + vk::DescriptorSetLayoutCreateInfo descs_layout_info; + descs_layout_info.setBindings(desc_bindings); - auto descriptor_set_create_res = - device_.createDescriptorSetLayoutUnique(descriptor_set_create); - if (descriptor_set_create_res.result != vk::Result::eSuccess) { + auto [descs_result, descs_layout] = + device_.createDescriptorSetLayoutUnique(descs_layout_info); + if (descs_result != vk::Result::eSuccess) { VALIDATION_LOG << "unable to create uniform descriptors"; return nullptr; } - vk::UniqueDescriptorSetLayout descriptor_set_layout = - std::move(descriptor_set_create_res.value); - ContextVK::SetDebugName(device_, descriptor_set_layout.get(), - "Descriptor Set Layout" + desc.GetLabel()); + ContextVK::SetDebugName(device_, descs_layout.get(), + "Descriptor Set Layout " + desc.GetLabel()); //---------------------------------------------------------------------------- /// Create the pipeline layout. /// vk::PipelineLayoutCreateInfo pipeline_layout_info; - pipeline_layout_info.setSetLayouts(descriptor_set_layout.get()); + pipeline_layout_info.setSetLayouts(descs_layout.get()); auto pipeline_layout = device_.createPipelineLayoutUnique(pipeline_layout_info); if (pipeline_layout.result != vk::Result::eSuccess) { @@ -402,13 +341,81 @@ std::unique_ptr PipelineLibraryVK::CreatePipeline( } ContextVK::SetDebugName(device_, *pipeline_layout.value, - "Pipeline Layout" + desc.GetLabel()); + "Pipeline Layout " + desc.GetLabel()); ContextVK::SetDebugName(device_, *pipeline.value, - "Pipeline" + desc.GetLabel()); + "Pipeline " + desc.GetLabel()); + + return std::make_unique(weak_from_this(), // + desc, // + std::move(pipeline.value), // + std::move(render_pass), // + std::move(pipeline_layout.value), // + std::move(descs_layout) // + ); +} - return std::make_unique( - std::move(pipeline.value), std::move(render_pass), - std::move(pipeline_layout.value), std::move(descriptor_set_layout)); +// |PipelineLibrary| +PipelineFuture PipelineLibraryVK::GetPipeline( + PipelineDescriptor descriptor) { + Lock lock(pipelines_mutex_); + if (auto found = pipelines_.find(descriptor); found != pipelines_.end()) { + return found->second; + } + + if (!IsValid()) { + return { + descriptor, + RealizedFuture>>(nullptr)}; + } + + auto promise = std::make_shared< + std::promise>>>(); + auto pipeline_future = + PipelineFuture{descriptor, promise->get_future()}; + pipelines_[descriptor] = pipeline_future; + + auto weak_this = weak_from_this(); + + worker_task_runner_->PostTask([descriptor, weak_this, promise]() { + auto thiz = weak_this.lock(); + if (!thiz) { + promise->set_value(nullptr); + VALIDATION_LOG << "Pipeline library was collected before the pipeline " + "could be created."; + return; + } + + auto pipeline = PipelineLibraryVK::Cast(*thiz).CreatePipeline(descriptor); + if (!pipeline) { + promise->set_value(nullptr); + VALIDATION_LOG << "Could not create pipeline: " << descriptor.GetLabel(); + return; + } + + promise->set_value(std::move(pipeline)); + }); + + return pipeline_future; +} + +// |PipelineLibrary| +PipelineFuture PipelineLibraryVK::GetPipeline( + ComputePipelineDescriptor descriptor) { + auto promise = std::make_shared< + std::promise>>>(); + promise->set_value(nullptr); + return {descriptor, promise->get_future()}; +} + +// |PipelineLibrary| +void PipelineLibraryVK::RemovePipelinesWithEntryPoint( + std::shared_ptr function) { + Lock lock(pipelines_mutex_); + + fml::erase_if(pipelines_, [&](auto item) { + return item->first.GetEntrypointForStage(function->GetStage()) + ->IsEqual(*function); + }); } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/pipeline_library_vk.h b/impeller/renderer/backend/vulkan/pipeline_library_vk.h index f4cd10b76ffd8..6892ac126d17b 100644 --- a/impeller/renderer/backend/vulkan/pipeline_library_vk.h +++ b/impeller/renderer/backend/vulkan/pipeline_library_vk.h @@ -62,10 +62,7 @@ class PipelineLibraryVK final void RemovePipelinesWithEntryPoint( std::shared_ptr function) override; - std::unique_ptr CreatePipeline( - const PipelineDescriptor& desc); - - vk::UniqueRenderPass CreateRenderPass(const PipelineDescriptor& desc); + std::unique_ptr CreatePipeline(const PipelineDescriptor& desc); FML_DISALLOW_COPY_AND_ASSIGN(PipelineLibraryVK); }; diff --git a/impeller/renderer/backend/vulkan/pipeline_vk.cc b/impeller/renderer/backend/vulkan/pipeline_vk.cc index 87f65c9c99da6..208d63ae99fd8 100644 --- a/impeller/renderer/backend/vulkan/pipeline_vk.cc +++ b/impeller/renderer/backend/vulkan/pipeline_vk.cc @@ -6,53 +6,40 @@ namespace impeller { -PipelineCreateInfoVK::PipelineCreateInfoVK( - vk::UniquePipeline pipeline, - vk::UniqueRenderPass render_pass, - vk::UniquePipelineLayout layout, - vk::UniqueDescriptorSetLayout descriptor_set_layout) - : pipeline_(std::move(pipeline)), +PipelineVK::PipelineVK(std::weak_ptr library, + const PipelineDescriptor& desc, + vk::UniquePipeline pipeline, + vk::UniqueRenderPass render_pass, + vk::UniquePipelineLayout layout, + vk::UniqueDescriptorSetLayout descriptor_set_layout) + : Pipeline(std::move(library), desc), + pipeline_(std::move(pipeline)), render_pass_(std::move(render_pass)), - pipeline_layout_(std::move(layout)), + layout_(std::move(layout)), descriptor_set_layout_(std::move(descriptor_set_layout)) { - is_valid_ = - pipeline_ && render_pass_ && pipeline_layout_ && descriptor_set_layout_; + is_valid_ = pipeline_ && render_pass_ && layout_ && descriptor_set_layout_; } -bool PipelineCreateInfoVK::IsValid() const { +PipelineVK::~PipelineVK() = default; + +bool PipelineVK::IsValid() const { return is_valid_; } -const vk::Pipeline& PipelineCreateInfoVK::GetVKPipeline() const { +const vk::Pipeline& PipelineVK::GetPipeline() const { return *pipeline_; } -vk::RenderPass PipelineCreateInfoVK::GetRenderPass() const { +const vk::RenderPass& PipelineVK::GetRenderPass() const { return *render_pass_; } -vk::PipelineLayout PipelineCreateInfoVK::GetPipelineLayout() const { - return *pipeline_layout_; +const vk::PipelineLayout& PipelineVK::GetPipelineLayout() const { + return *layout_; } -vk::DescriptorSetLayout PipelineCreateInfoVK::GetDescriptorSetLayout() const { +const vk::DescriptorSetLayout& PipelineVK::GetDescriptorSetLayout() const { return *descriptor_set_layout_; } -PipelineVK::PipelineVK(std::weak_ptr library, - const PipelineDescriptor& desc, - std::unique_ptr create_info) - : Pipeline(std::move(library), desc), - pipeline_info_(std::move(create_info)) {} - -PipelineVK::~PipelineVK() = default; - -bool PipelineVK::IsValid() const { - return pipeline_info_->IsValid(); -} - -PipelineCreateInfoVK* PipelineVK::GetCreateInfo() const { - return pipeline_info_.get(); -} - } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/pipeline_vk.h b/impeller/renderer/backend/vulkan/pipeline_vk.h index a10e31e12f176..7135dcf03eb5f 100644 --- a/impeller/renderer/backend/vulkan/pipeline_vk.h +++ b/impeller/renderer/backend/vulkan/pipeline_vk.h @@ -13,51 +13,41 @@ namespace impeller { -class PipelineCreateInfoVK { - public: - PipelineCreateInfoVK(vk::UniquePipeline pipeline, - vk::UniqueRenderPass render_pass, - vk::UniquePipelineLayout pipeline_layout, - vk::UniqueDescriptorSetLayout descriptor_set_layout); - - bool IsValid() const; - - const vk::Pipeline& GetVKPipeline() const; - - vk::RenderPass GetRenderPass() const; - - vk::PipelineLayout GetPipelineLayout() const; - - vk::DescriptorSetLayout GetDescriptorSetLayout() const; - - private: - bool is_valid_ = false; - vk::UniquePipeline pipeline_; - vk::UniqueRenderPass render_pass_; - vk::UniquePipelineLayout pipeline_layout_; - vk::UniqueDescriptorSetLayout descriptor_set_layout_; -}; - class PipelineVK final : public Pipeline, public BackendCast> { public: PipelineVK(std::weak_ptr library, const PipelineDescriptor& desc, - std::unique_ptr create_info); + vk::UniquePipeline pipeline, + vk::UniqueRenderPass render_pass, + vk::UniquePipelineLayout layout, + vk::UniqueDescriptorSetLayout descriptor_set_layout); // |Pipeline| ~PipelineVK() override; - PipelineCreateInfoVK* GetCreateInfo() const; + const vk::Pipeline& GetPipeline() const; + + const vk::RenderPass& GetRenderPass() const; + + const vk::PipelineLayout& GetPipelineLayout() const; + + const vk::DescriptorSetLayout& GetDescriptorSetLayout() const; private: friend class PipelineLibraryVK; + const vk::UniquePipeline pipeline_; + const vk::UniqueRenderPass render_pass_; + const vk::UniquePipelineLayout layout_; + const vk::UniqueDescriptorSetLayout descriptor_set_layout_; + bool is_valid_ = false; + // |Pipeline| bool IsValid() const override; - std::unique_ptr pipeline_info_; + std::unique_ptr CreatePipeline(const PipelineDescriptor& desc); FML_DISALLOW_COPY_AND_ASSIGN(PipelineVK); }; diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index b929e647e2594..091ad5251b127 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -6,9 +6,11 @@ #include #include +#include #include -#include "fml/logging.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/trace_event.h" #include "impeller/base/validation.h" #include "impeller/renderer/backend/vulkan/command_encoder_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" @@ -40,8 +42,9 @@ static vk::AttachmentDescription CreateAttachmentDescription( ); } -static vk::UniqueRenderPass CreateVKRenderPass(const vk::Device& device, - const RenderTarget& target) { +static SharedHandleVK CreateVKRenderPass( + const vk::Device& device, + const RenderTarget& target) { std::vector attachments; std::vector color_refs; @@ -108,7 +111,7 @@ static vk::UniqueRenderPass CreateVKRenderPass(const vk::Device& device, return {}; } - return std::move(pass); + return MakeSharedVK(std::move(pass)); } RenderPassVK::RenderPassVK(const std::shared_ptr& context, @@ -135,7 +138,7 @@ void RenderPassVK::OnSetLabel(std::string label) { if (!context) { return; } - ContextVK::Cast(*context).SetDebugName(*render_pass_, label.c_str()); + ContextVK::Cast(*context).SetDebugName(render_pass_->Get(), label.c_str()); debug_label_ = std::move(label); } @@ -225,34 +228,60 @@ static vk::UniqueFramebuffer CreateFramebuffer(const vk::Device& device, return std::move(framebuffer); } -static bool ConfigureRenderTargetAttachmentLayouts( - const RenderTarget& target, - const vk::CommandBuffer& command_buffer) { +static bool ConfigureAttachments(const RenderTarget& target, + const vk::CommandBuffer& command_buffer, + CommandEncoderVK& encoder) { for (const auto& [_, color] : target.GetColorAttachments()) { - if (!TextureVK::Cast(*color.texture) - .SetLayout(vk::ImageLayout::eColorAttachmentOptimal, - command_buffer)) { + const auto& color_tex = color.texture; + const auto& color_resolve_tex = color.resolve_texture; + + LayoutTransition color_tran; + color_tran.cmd_buffer = command_buffer; + color_tran.src_access = vk::AccessFlagBits::eColorAttachmentWrite | + vk::AccessFlagBits::eShaderWrite | + vk::AccessFlagBits::eTransferWrite; + color_tran.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput | + vk::PipelineStageFlagBits::eFragmentShader | + vk::PipelineStageFlagBits::eTransfer; + color_tran.dst_access = vk::AccessFlagBits::eShaderRead; + color_tran.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; + + color_tran.new_layout = vk::ImageLayout::eColorAttachmentOptimal; + + // Transition and track the color texture. + if (!TextureVK::Cast(*color_tex).SetLayout(color_tran) || + !encoder.Track(color_tex)) { return false; } - if (color.resolve_texture) { - if (!TextureVK::Cast(*color.resolve_texture) - .SetLayout(vk::ImageLayout::eColorAttachmentOptimal, - command_buffer)) { + + // Transition and track the resolve texture, if there is one. + if (color_resolve_tex) { + if (!TextureVK::Cast(*color_resolve_tex).SetLayout(color_tran) || + !encoder.Track(color_resolve_tex)) { return false; } } } + + LayoutTransition depth_stencil_tran; + depth_stencil_tran.cmd_buffer = command_buffer; + depth_stencil_tran.src_access = {}; + depth_stencil_tran.src_stage = vk::PipelineStageFlagBits::eTopOfPipe; + depth_stencil_tran.dst_access = vk::AccessFlagBits::eShaderRead; + depth_stencil_tran.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; + + depth_stencil_tran.new_layout = vk::ImageLayout::eDepthAttachmentOptimal; if (auto depth = target.GetDepthAttachment(); depth.has_value()) { - if (!TextureVK::Cast(*depth->texture) - .SetLayout(vk::ImageLayout::eDepthAttachmentOptimal, - command_buffer)) { + if (!TextureVK::Cast(*depth->texture).SetLayout(depth_stencil_tran) || + !encoder.Track(depth->texture)) { return false; } } + + depth_stencil_tran.new_layout = vk::ImageLayout::eStencilAttachmentOptimal; if (auto stencil = target.GetStencilAttachment(); stencil.has_value()) { - if (!TextureVK::Cast(*stencil->texture) - .SetLayout(vk::ImageLayout::eStencilAttachmentOptimal, - command_buffer)) { + if (!TextureVK::Cast(*stencil->texture).SetLayout(depth_stencil_tran) || + !encoder.Track(stencil->texture)) { return false; } } @@ -261,9 +290,19 @@ static bool ConfigureRenderTargetAttachmentLayouts( static bool UpdateBindingLayouts(const Bindings& bindings, const vk::CommandBuffer& buffer) { + LayoutTransition transition; + transition.cmd_buffer = buffer; + transition.src_access = vk::AccessFlagBits::eColorAttachmentWrite | + vk::AccessFlagBits::eTransferWrite; + transition.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput | + vk::PipelineStageFlagBits::eTransfer; + transition.dst_access = vk::AccessFlagBits::eShaderRead; + transition.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; + + transition.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal; + for (const auto& [_, texture] : bindings.textures) { - if (!TextureVK::Cast(*texture.resource) - .SetLayout(vk::ImageLayout::eShaderReadOnlyOptimal, buffer)) { + if (!TextureVK::Cast(*texture.resource).SetLayout(transition)) { return false; } } @@ -286,160 +325,124 @@ static bool UpdateBindingLayouts(const std::vector& commands, return true; } -static bool UpdateDescriptorSets(vk::Device device, - const Bindings& bindings, - Allocator& allocator, - vk::DescriptorSet desc_set, - CommandEncoderVK& encoder) { - std::vector writes; - - //---------------------------------------------------------------------------- - /// Setup buffer descriptors. - /// - std::vector buffer_desc; - for (const auto& [buffer_index, view] : bindings.buffers) { - const auto& buffer_view = view.resource.buffer; - - auto device_buffer = buffer_view->GetDeviceBuffer(allocator); - if (!device_buffer) { - VALIDATION_LOG << "Failed to get device buffer for vertex binding"; - return false; - } - - auto buffer = DeviceBufferVK::Cast(*device_buffer).GetVKBufferHandle(); - if (!buffer) { - return false; - } - - // Reserved index used for per-vertex data. - if (buffer_index == VertexDescriptor::kReservedVertexBufferIndex) { - continue; - } +static bool AllocateAndBindDescriptorSets(const ContextVK& context, + const Command& command, + CommandEncoderVK& encoder, + const PipelineVK& pipeline) { + auto desc_set = + encoder.AllocateDescriptorSet(pipeline.GetDescriptorSetLayout()); + if (!desc_set) { + return false; + } - if (!encoder.Track(device_buffer)) { - return false; - } + auto& allocator = *context.GetResourceAllocator(); - uint32_t offset = view.resource.range.offset; + std::unordered_map buffers; + std::unordered_map images; + std::vector writes; - vk::DescriptorBufferInfo desc_buffer_info; - desc_buffer_info.setBuffer(buffer); - desc_buffer_info.setOffset(offset); - desc_buffer_info.setRange(view.resource.range.length); - buffer_desc.push_back(desc_buffer_info); + auto bind_images = [&encoder, // + &images, // + &writes, // + &desc_set // + ](const Bindings& bindings) -> bool { + for (const auto& [index, sampler_handle] : bindings.samplers) { + if (bindings.textures.find(index) == bindings.textures.end()) { + return false; + } - const ShaderUniformSlot& uniform = bindings.uniforms.at(buffer_index); + auto texture = bindings.textures.at(index).resource; + const auto& texture_vk = TextureVK::Cast(*texture); + const SamplerVK& sampler = SamplerVK::Cast(*sampler_handle.resource); - vk::WriteDescriptorSet write_set; - write_set.setDstSet(desc_set); - write_set.setDstBinding(uniform.binding); - write_set.setDescriptorCount(1); - write_set.setDescriptorType(vk::DescriptorType::eUniformBuffer); - write_set.setPBufferInfo(&buffer_desc.back()); + if (!encoder.Track(texture) || + !encoder.Track(sampler.GetSharedSampler())) { + return false; + } - writes.push_back(write_set); - } + const SampledImageSlot& slot = bindings.sampled_images.at(index); - //---------------------------------------------------------------------------- - /// Setup image descriptors. - /// - std::vector image_descs; - for (const auto& [index, sampler_handle] : bindings.samplers) { - if (bindings.textures.find(index) == bindings.textures.end()) { - VALIDATION_LOG << "Missing texture for sampler: " << index; - return false; - } + vk::DescriptorImageInfo image_info; + image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal; + image_info.sampler = sampler.GetSampler(); + image_info.imageView = texture_vk.GetImageView(); - auto texture = bindings.textures.at(index).resource; - const auto& texture_vk = TextureVK::Cast(*texture); - const SamplerVK& sampler = SamplerVK::Cast(*sampler_handle.resource); + vk::WriteDescriptorSet write_set; + write_set.dstSet = desc_set.value(); + write_set.dstBinding = slot.binding; + write_set.descriptorCount = 1u; + write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler; + write_set.pImageInfo = &(images[slot.binding] = image_info); - if (!encoder.Track(texture) || !encoder.Track(sampler.GetSharedSampler())) { - return false; + writes.push_back(write_set); } - const SampledImageSlot& slot = bindings.sampled_images.at(index); + return true; + }; - vk::DescriptorImageInfo desc_image_info; - desc_image_info.setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal); - desc_image_info.setSampler(sampler.GetSamplerVK()); - desc_image_info.setImageView(texture_vk.GetImageView()); - image_descs.push_back(desc_image_info); + auto bind_buffers = [&allocator, // + &encoder, // + &buffers, // + &writes, // + &desc_set // + ](const Bindings& bindings) -> bool { + for (const auto& [buffer_index, view] : bindings.buffers) { + const auto& buffer_view = view.resource.buffer; + + auto device_buffer = buffer_view->GetDeviceBuffer(allocator); + if (!device_buffer) { + VALIDATION_LOG << "Failed to get device buffer for vertex binding"; + return false; + } - vk::WriteDescriptorSet write_set; - write_set.setDstSet(desc_set); - write_set.setDstBinding(slot.binding); - write_set.setDescriptorCount(1); - write_set.setDescriptorType(vk::DescriptorType::eCombinedImageSampler); - write_set.setPImageInfo(&image_descs.back()); + auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer(); + if (!buffer) { + return false; + } - writes.push_back(write_set); - } + // Reserved index used for per-vertex data. + if (buffer_index == VertexDescriptor::kReservedVertexBufferIndex) { + continue; + } - if (writes.empty()) { - return true; - } - device.updateDescriptorSets(writes, {}); - return true; -} + if (!encoder.Track(device_buffer)) { + return false; + } -static bool AllocateAndBindDescriptorSets( - const ContextVK& context, - const Command& command, - CommandEncoderVK& encoder, - PipelineCreateInfoVK* pipeline_create_info) { - auto& allocator = *context.GetResourceAllocator(); - vk::PipelineLayout pipeline_layout = - pipeline_create_info->GetPipelineLayout(); + uint32_t offset = view.resource.range.offset; - vk::DescriptorSetAllocateInfo alloc_info; - std::array dsls = { - pipeline_create_info->GetDescriptorSetLayout(), - }; + vk::DescriptorBufferInfo buffer_info; + buffer_info.buffer = buffer; + buffer_info.offset = offset; + buffer_info.range = view.resource.range.length; - alloc_info.setDescriptorPool(context.GetDescriptorPool()); - alloc_info.setSetLayouts(dsls); + const ShaderUniformSlot& uniform = bindings.uniforms.at(buffer_index); - auto [sets_result, sets] = - context.GetDevice().allocateDescriptorSetsUnique(alloc_info); - if (sets_result != vk::Result::eSuccess) { - VALIDATION_LOG << "Failed to allocate descriptor sets: " - << vk::to_string(sets_result); - return false; - } + vk::WriteDescriptorSet write_set; + write_set.dstSet = desc_set.value(); + write_set.dstBinding = uniform.binding; + write_set.descriptorCount = 1u; + write_set.descriptorType = vk::DescriptorType::eUniformBuffer; + write_set.pBufferInfo = &(buffers[uniform.binding] = buffer_info); - const auto set = MakeSharedVK(std::move(sets[0])); + writes.push_back(write_set); + } + return true; + }; - if (!encoder.Track(set)) { + if (!bind_buffers(command.vertex_bindings) || + !bind_buffers(command.fragment_bindings) || + !bind_images(command.fragment_bindings)) { return false; } - bool update_vertex_descriptors = - UpdateDescriptorSets(context.GetDevice(), // - command.vertex_bindings, // - allocator, // - *set, // - encoder // - ); - if (!update_vertex_descriptors) { - return false; - } - bool update_frag_descriptors = - UpdateDescriptorSets(context.GetDevice(), // - command.fragment_bindings, // - allocator, // - *set, // - encoder // - ); - if (!update_frag_descriptors) { - return false; - } + context.GetDevice().updateDescriptorSets(writes, {}); encoder.GetCommandBuffer().bindDescriptorSets( vk::PipelineBindPoint::eGraphics, // bind point - pipeline_layout, // layout + pipeline.GetPipelineLayout(), // layout 0, // first set - {vk::DescriptorSet{*set}}, // sets + {vk::DescriptorSet{*desc_set}}, // sets nullptr // offsets ); return true; @@ -486,19 +489,18 @@ static bool EncodeCommand(const Context& context, const auto& cmd_buffer = encoder.GetCommandBuffer(); - auto& pipeline_vk = PipelineVK::Cast(*command.pipeline); - PipelineCreateInfoVK* pipeline_create_info = pipeline_vk.GetCreateInfo(); + const auto& pipeline_vk = PipelineVK::Cast(*command.pipeline); if (!AllocateAndBindDescriptorSets(ContextVK::Cast(context), // command, // encoder, // - pipeline_create_info // + pipeline_vk // )) { return false; } cmd_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, - pipeline_create_info->GetVKPipeline()); + pipeline_vk.GetPipeline()); // Set the viewport and scissors. SetViewportAndScissor(command, cmd_buffer, target_size); @@ -532,15 +534,13 @@ static bool EncodeCommand(const Context& context, } // Bind the vertex buffer. - auto vertex_buffer_handle = - DeviceBufferVK::Cast(*vertex_buffer).GetVKBufferHandle(); + auto vertex_buffer_handle = DeviceBufferVK::Cast(*vertex_buffer).GetBuffer(); vk::Buffer vertex_buffers[] = {vertex_buffer_handle}; vk::DeviceSize vertex_buffer_offsets[] = {vertex_buffer_view.range.offset}; cmd_buffer.bindVertexBuffers(0u, 1u, vertex_buffers, vertex_buffer_offsets); // Bind the index buffer. - auto index_buffer_handle = - DeviceBufferVK::Cast(*index_buffer).GetVKBufferHandle(); + auto index_buffer_handle = DeviceBufferVK::Cast(*index_buffer).GetBuffer(); cmd_buffer.bindIndexBuffer(index_buffer_handle, index_buffer_view.range.offset, ToVKIndexType(command.index_type)); @@ -556,14 +556,11 @@ static bool EncodeCommand(const Context& context, } bool RenderPassVK::OnEncodeCommands(const Context& context) const { + TRACE_EVENT0("impeller", "RenderPassVK::OnEncodeCommands"); if (!IsValid()) { return false; } - if (commands_.empty()) { - return true; - } - const auto& vk_context = ContextVK::Cast(context); const auto& render_target = GetRenderTarget(); @@ -593,16 +590,23 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { return false; } - if (!ConfigureRenderTargetAttachmentLayouts(render_target, cmd_buffer)) { + if (!ConfigureAttachments(render_target, cmd_buffer, *encoder)) { VALIDATION_LOG << "Could not complete attachment layout transitions."; return false; } + if (commands_.empty()) { + // All the necessary layout transitions of the attchments have been + // completed by this point. If there are no commands, there is nothing + // further to do. + return true; + } + const auto& target_size = render_target.GetRenderTargetSize(); auto framebuffer = MakeSharedVK( CreateFramebuffer(vk_context.GetDevice(), render_target_, *render_pass_)); - if (!encoder->Track(framebuffer)) { + if (!encoder->Track(framebuffer) || !encoder->Track(render_pass_)) { return false; } @@ -617,6 +621,7 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { pass_info.setClearValues(clear_values); { + TRACE_EVENT0("impeller", "EncodeRenderPassCommands"); cmd_buffer.beginRenderPass(pass_info, vk::SubpassContents::eInline); fml::ScopedCleanupClosure end_render_pass( diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.h b/impeller/renderer/backend/vulkan/render_pass_vk.h index eae656062c299..ebb42d15dbafe 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.h +++ b/impeller/renderer/backend/vulkan/render_pass_vk.h @@ -6,6 +6,7 @@ #include "flutter/fml/macros.h" #include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/backend/vulkan/texture_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/command.h" @@ -22,7 +23,7 @@ class RenderPassVK final : public RenderPass { private: friend class CommandBufferVK; - vk::UniqueRenderPass render_pass_; + SharedHandleVK render_pass_; std::weak_ptr encoder_; std::string debug_label_; bool is_valid_ = false; diff --git a/impeller/renderer/backend/vulkan/sampler_library_vk.cc b/impeller/renderer/backend/vulkan/sampler_library_vk.cc index 149c1ae957d4c..b62549eb88ad5 100644 --- a/impeller/renderer/backend/vulkan/sampler_library_vk.cc +++ b/impeller/renderer/backend/vulkan/sampler_library_vk.cc @@ -4,6 +4,7 @@ #include "impeller/renderer/backend/vulkan/sampler_library_vk.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/sampler_vk.h" @@ -51,6 +52,11 @@ std::shared_ptr SamplerLibraryVK::GetSampler( if (!sampler->IsValid()) { return nullptr; } + + if (!desc.label.empty()) { + ContextVK::SetDebugName(device_, sampler->GetSampler(), desc.label.c_str()); + } + samplers_[desc] = sampler; return sampler; } diff --git a/impeller/renderer/backend/vulkan/sampler_vk.cc b/impeller/renderer/backend/vulkan/sampler_vk.cc index 7d2f9bb5c94d4..5b706ce92edca 100644 --- a/impeller/renderer/backend/vulkan/sampler_vk.cc +++ b/impeller/renderer/backend/vulkan/sampler_vk.cc @@ -14,7 +14,7 @@ SamplerVK::SamplerVK(SamplerDescriptor desc, vk::UniqueSampler sampler) SamplerVK::~SamplerVK() = default; -vk::Sampler SamplerVK::GetSamplerVK() const { +vk::Sampler SamplerVK::GetSampler() const { return *sampler_; } diff --git a/impeller/renderer/backend/vulkan/sampler_vk.h b/impeller/renderer/backend/vulkan/sampler_vk.h index d0268ced3819a..bf78d63a1b271 100644 --- a/impeller/renderer/backend/vulkan/sampler_vk.h +++ b/impeller/renderer/backend/vulkan/sampler_vk.h @@ -22,7 +22,7 @@ class SamplerVK final : public Sampler, public BackendCast { // |Sampler| ~SamplerVK() override; - vk::Sampler GetSamplerVK() const; + vk::Sampler GetSampler() const; const std::shared_ptr>& GetSharedSampler() const; diff --git a/impeller/renderer/backend/vulkan/shared_object_vk.h b/impeller/renderer/backend/vulkan/shared_object_vk.h index d3c42a50a04ef..fa87547fc9c67 100644 --- a/impeller/renderer/backend/vulkan/shared_object_vk.h +++ b/impeller/renderer/backend/vulkan/shared_object_vk.h @@ -25,10 +25,14 @@ class SharedObjectVKT : public SharedObjectVK { explicit SharedObjectVKT(UniqueResource res) : resource_(std::move(res)) {} - operator Resource() const { return *resource_; } + operator Resource() const { return Get(); } + + const Resource& Get() const { return *resource_; } private: UniqueResource resource_; + + FML_DISALLOW_COPY_AND_ASSIGN(SharedObjectVKT); }; template @@ -40,4 +44,7 @@ auto MakeSharedVK( return std::make_shared>(std::move(handle)); } +template +using SharedHandleVK = std::shared_ptr>; + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/surface_vk.cc b/impeller/renderer/backend/vulkan/surface_vk.cc index a1f09a42b3c76..02992a35ebc0f 100644 --- a/impeller/renderer/backend/vulkan/surface_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_vk.cc @@ -43,9 +43,8 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( resolve_tex_desc.storage_mode = StorageMode::kDevicePrivate; std::shared_ptr resolve_tex = - std::make_shared(resolve_tex_desc, // - context, // - swapchain_image // + std::make_shared(context, // + swapchain_image // ); if (!resolve_tex) { @@ -65,8 +64,7 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( stencil0_tex.storage_mode = StorageMode::kDeviceTransient; stencil0_tex.type = TextureType::kTexture2D; stencil0_tex.sample_count = SampleCount::kCount4; - stencil0_tex.format = - context->GetDeviceCapabilities().GetDefaultStencilFormat(); + stencil0_tex.format = context->GetCapabilities()->GetDefaultStencilFormat(); stencil0_tex.size = msaa_tex_desc.size; stencil0_tex.usage = static_cast(TextureUsage::kRenderTarget); diff --git a/impeller/renderer/backend/vulkan/swapchain_image_vk.cc b/impeller/renderer/backend/vulkan/swapchain_image_vk.cc index 843f0b44a8bbd..c87797df753ab 100644 --- a/impeller/renderer/backend/vulkan/swapchain_image_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain_image_vk.cc @@ -6,25 +6,22 @@ namespace impeller { -SwapchainImageVK::SwapchainImageVK(vk::Device device, - vk::Image image, - PixelFormat image_format, - ISize image_size) - : image_(image), image_format_(image_format), image_size_(image_size) { +SwapchainImageVK::SwapchainImageVK(TextureDescriptor desc, + vk::Device device, + vk::Image image) + : TextureSourceVK(desc), image_(image) { vk::ImageViewCreateInfo view_info; view_info.image = image_; view_info.viewType = vk::ImageViewType::e2D; - view_info.format = ToVKImageFormat(image_format_); + view_info.format = ToVKImageFormat(desc.format); view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; view_info.subresourceRange.baseMipLevel = 0u; - view_info.subresourceRange.levelCount = 1u; view_info.subresourceRange.baseArrayLayer = 0u; - view_info.subresourceRange.layerCount = 1u; + view_info.subresourceRange.levelCount = desc.mip_count; + view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type); auto [view_result, view] = device.createImageViewUnique(view_info); if (view_result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create image view: " - << vk::to_string(view_result); return; } @@ -39,20 +36,20 @@ bool SwapchainImageVK::IsValid() const { } PixelFormat SwapchainImageVK::GetPixelFormat() const { - return image_format_; + return desc_.format; } ISize SwapchainImageVK::GetSize() const { - return image_size_; + return desc_.size; } // |TextureSourceVK| -vk::Image SwapchainImageVK::GetVKImage() const { +vk::Image SwapchainImageVK::GetImage() const { return image_; } // |TextureSourceVK| -vk::ImageView SwapchainImageVK::GetVKImageView() const { +vk::ImageView SwapchainImageVK::GetImageView() const { return image_view_.get(); } diff --git a/impeller/renderer/backend/vulkan/swapchain_image_vk.h b/impeller/renderer/backend/vulkan/swapchain_image_vk.h index 9869b689aaa3d..db905e834948c 100644 --- a/impeller/renderer/backend/vulkan/swapchain_image_vk.h +++ b/impeller/renderer/backend/vulkan/swapchain_image_vk.h @@ -14,10 +14,7 @@ namespace impeller { class SwapchainImageVK final : public TextureSourceVK { public: - SwapchainImageVK(vk::Device device, - vk::Image image, - PixelFormat image_format, - ISize image_size); + SwapchainImageVK(TextureDescriptor desc, vk::Device device, vk::Image image); // |TextureSourceVK| ~SwapchainImageVK() override; @@ -29,15 +26,13 @@ class SwapchainImageVK final : public TextureSourceVK { ISize GetSize() const; // |TextureSourceVK| - vk::Image GetVKImage() const override; + vk::Image GetImage() const override; // |TextureSourceVK| - vk::ImageView GetVKImageView() const override; + vk::ImageView GetImageView() const override; private: vk::Image image_ = VK_NULL_HANDLE; - PixelFormat image_format_ = PixelFormat::kUnknown; - ISize image_size_; vk::UniqueImageView image_view_ = {}; bool is_valid_ = false; diff --git a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc b/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc index ff40400c657a7..b4e4f2f899d53 100644 --- a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc @@ -150,7 +150,7 @@ SwapchainImplVK::SwapchainImplVK(const std::shared_ptr& context, } const auto format = ChooseSurfaceFormat( - formats, vk_context.GetDeviceCapabilities().GetDefaultColorFormat()); + formats, vk_context.GetCapabilities()->GetDefaultColorFormat()); if (!format.has_value()) { VALIDATION_LOG << "Swapchain has no supported formats."; return; @@ -213,19 +213,33 @@ SwapchainImplVK::SwapchainImplVK(const std::shared_ptr& context, return; } + TextureDescriptor texture_desc; + texture_desc.usage = + static_cast(TextureUsage::kRenderTarget); + texture_desc.storage_mode = StorageMode::kDevicePrivate; + texture_desc.format = ToPixelFormat(swapchain_info.imageFormat); + texture_desc.size = ISize::MakeWH(swapchain_info.imageExtent.width, + swapchain_info.imageExtent.height); + std::vector> swapchain_images; for (const auto& image : images) { - auto swapchain_image = std::make_shared( - vk_context.GetDevice(), // - image, // - ToPixelFormat(swapchain_info.imageFormat), // - ISize::MakeWH(swapchain_info.imageExtent.width, - swapchain_info.imageExtent.height) // - ); + auto swapchain_image = + std::make_shared(texture_desc, // texture descriptor + vk_context.GetDevice(), // device + image // image + ); if (!swapchain_image->IsValid()) { VALIDATION_LOG << "Could not create swapchain image."; return; } + + ContextVK::SetDebugName( + vk_context.GetDevice(), swapchain_image->GetImage(), + "SwapchainImage" + std::to_string(swapchain_images.size())); + ContextVK::SetDebugName( + vk_context.GetDevice(), swapchain_image->GetImageView(), + "SwapchainImageView" + std::to_string(swapchain_images.size())); + swapchain_images.emplace_back(swapchain_image); } @@ -366,24 +380,19 @@ bool SwapchainImplVK::Present(const std::shared_ptr& image, auto vk_cmd_buffer = CommandBufferVK::Cast(*cmd_buffer).GetEncoder()->GetCommandBuffer(); - vk::ImageMemoryBarrier image_barrier; - image_barrier.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite; - image_barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead; - image_barrier.image = image->GetVKImage(); - image_barrier.oldLayout = vk::ImageLayout::eColorAttachmentOptimal; - image_barrier.newLayout = vk::ImageLayout::ePresentSrcKHR; - image_barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; - image_barrier.subresourceRange.baseMipLevel = 0u; - image_barrier.subresourceRange.levelCount = 1u; - image_barrier.subresourceRange.baseArrayLayer = 0u; - image_barrier.subresourceRange.layerCount = 1u; - vk_cmd_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, // - vk::PipelineStageFlagBits::eAllGraphics, // - {}, // - nullptr, // - nullptr, // - image_barrier // - ); + + LayoutTransition transition; + transition.new_layout = vk::ImageLayout::ePresentSrcKHR; + transition.cmd_buffer = vk_cmd_buffer; + transition.src_access = vk::AccessFlagBits::eColorAttachmentWrite; + transition.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput; + transition.dst_access = {}; + transition.dst_stage = vk::PipelineStageFlagBits::eBottomOfPipe; + + if (!image->SetLayout(transition)) { + return false; + } + if (!cmd_buffer->SubmitCommands()) { return false; } diff --git a/impeller/renderer/backend/vulkan/texture_source_vk.cc b/impeller/renderer/backend/vulkan/texture_source_vk.cc index c411c62489cbf..25f231565e58e 100644 --- a/impeller/renderer/backend/vulkan/texture_source_vk.cc +++ b/impeller/renderer/backend/vulkan/texture_source_vk.cc @@ -6,6 +6,59 @@ namespace impeller { +TextureSourceVK::TextureSourceVK(TextureDescriptor desc) : desc_(desc) {} + +TextureSourceVK::~TextureSourceVK() = default; + +const TextureDescriptor& TextureSourceVK::GetTextureDescriptor() const { + return desc_; +} + +vk::ImageLayout TextureSourceVK::GetLayout() const { + ReaderLock lock(layout_mutex_); + return layout_; +} + +vk::ImageLayout TextureSourceVK::SetLayoutWithoutEncoding( + vk::ImageLayout layout) const { + WriterLock lock(layout_mutex_); + const auto old_layout = layout_; + layout_ = layout; + return old_layout; +} + +bool TextureSourceVK::SetLayout(const LayoutTransition& transition) const { + const auto old_layout = SetLayoutWithoutEncoding(transition.new_layout); + if (transition.new_layout == old_layout) { + return true; + } + + vk::ImageMemoryBarrier image_barrier; + image_barrier.srcAccessMask = transition.src_access; + image_barrier.dstAccessMask = transition.dst_access; + image_barrier.oldLayout = old_layout; + image_barrier.newLayout = transition.new_layout; + image_barrier.image = GetImage(); + image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_barrier.subresourceRange.aspectMask = + ToImageAspectFlags(transition.new_layout); + image_barrier.subresourceRange.baseMipLevel = 0u; + image_barrier.subresourceRange.levelCount = desc_.mip_count; + image_barrier.subresourceRange.baseArrayLayer = 0u; + image_barrier.subresourceRange.layerCount = ToArrayLayerCount(desc_.type); + + transition.cmd_buffer.pipelineBarrier(transition.src_stage, // src stage + transition.dst_stage, // dst stage + {}, // dependency flags + nullptr, // memory barriers + nullptr, // buffer barriers + image_barrier // image barriers + ); + + return true; +} + bool TextureSourceVK::SetContents(const TextureDescriptor& desc, const uint8_t* contents, size_t length, diff --git a/impeller/renderer/backend/vulkan/texture_source_vk.h b/impeller/renderer/backend/vulkan/texture_source_vk.h index 5fac2ce93980c..4b65739427c9b 100644 --- a/impeller/renderer/backend/vulkan/texture_source_vk.h +++ b/impeller/renderer/backend/vulkan/texture_source_vk.h @@ -5,6 +5,8 @@ #pragma once #include "flutter/fml/macros.h" +#include "impeller/base/thread.h" +#include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/texture_descriptor.h" @@ -12,16 +14,34 @@ namespace impeller { class TextureSourceVK { public: - virtual ~TextureSourceVK() = default; + virtual ~TextureSourceVK(); + + const TextureDescriptor& GetTextureDescriptor() const; virtual bool SetContents(const TextureDescriptor& desc, const uint8_t* contents, size_t length, size_t slice); - virtual vk::Image GetVKImage() const = 0; + virtual vk::Image GetImage() const = 0; + + virtual vk::ImageView GetImageView() const = 0; + + bool SetLayout(const LayoutTransition& transition) const; + + vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const; + + vk::ImageLayout GetLayout() const; + + protected: + const TextureDescriptor desc_; + + explicit TextureSourceVK(TextureDescriptor desc); - virtual vk::ImageView GetVKImageView() const = 0; + private: + mutable RWMutex layout_mutex_; + mutable vk::ImageLayout layout_ IPLR_GUARDED_BY(layout_mutex_) = + vk::ImageLayout::eUndefined; }; } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/texture_vk.cc b/impeller/renderer/backend/vulkan/texture_vk.cc index 70c048e1f459f..cc8c57280cc19 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.cc +++ b/impeller/renderer/backend/vulkan/texture_vk.cc @@ -4,12 +4,17 @@ #include "impeller/renderer/backend/vulkan/texture_vk.h" +#include "impeller/renderer/backend/vulkan/command_buffer_vk.h" +#include "impeller/renderer/backend/vulkan/command_encoder_vk.h" +#include "impeller/renderer/backend/vulkan/formats_vk.h" + namespace impeller { -TextureVK::TextureVK(TextureDescriptor desc, - std::weak_ptr context, +TextureVK::TextureVK(std::weak_ptr context, std::shared_ptr source) - : Texture(desc), context_(std::move(context)), source_(std::move(source)) {} + : Texture(source->GetTextureDescriptor()), + context_(std::move(context)), + source_(std::move(source)) {} TextureVK::~TextureVK() = default; @@ -20,6 +25,7 @@ void TextureVK::SetLabel(std::string_view label) { return; } ContextVK::Cast(*context).SetDebugName(GetImage(), label); + ContextVK::Cast(*context).SetDebugName(GetImageView(), label); } bool TextureVK::OnSetContents(const uint8_t* contents, @@ -33,11 +39,74 @@ bool TextureVK::OnSetContents(const uint8_t* contents, // Out of bounds access. if (length != desc.GetByteSizeOfBaseMipLevel()) { - VALIDATION_LOG << "illegal to set contents for invalid size"; + VALIDATION_LOG << "Illegal to set contents for invalid size."; + return false; + } + + auto context = context_.lock(); + if (!context) { + VALIDATION_LOG << "Context died before setting contents on texture."; + return false; + } + + auto staging_buffer = + context->GetResourceAllocator()->CreateBufferWithCopy(contents, length); + + if (!staging_buffer) { + VALIDATION_LOG << "Could not create staging buffer."; + return false; + } + + auto cmd_buffer = context->CreateCommandBuffer(); + + if (!cmd_buffer) { + return false; + } + + const auto encoder = CommandBufferVK::Cast(*cmd_buffer).GetEncoder(); + + if (!encoder->Track(staging_buffer) || !encoder->Track(source_)) { + return false; + } + + const auto& vk_cmd_buffer = encoder->GetCommandBuffer(); + + LayoutTransition transition; + transition.cmd_buffer = vk_cmd_buffer; + transition.new_layout = vk::ImageLayout::eTransferDstOptimal; + transition.src_access = {}; + transition.src_stage = vk::PipelineStageFlagBits::eTopOfPipe; + transition.dst_access = vk::AccessFlagBits::eTransferWrite; + transition.dst_stage = vk::PipelineStageFlagBits::eTransfer; + + if (!SetLayout(transition)) { return false; } - return source_->SetContents(desc, contents, length, slice); + vk::BufferImageCopy copy; + copy.bufferOffset = 0u; + copy.bufferRowLength = 0u; // 0u means tightly packed per spec. + copy.bufferImageHeight = 0u; // 0u means tightly packed per spec. + copy.imageOffset.x = 0u; + copy.imageOffset.y = 0u; + copy.imageOffset.z = 0u; + copy.imageExtent.width = desc.size.width; + copy.imageExtent.height = desc.size.height; + copy.imageExtent.depth = 1u; + copy.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor; + copy.imageSubresource.mipLevel = 0u; + copy.imageSubresource.baseArrayLayer = slice; + copy.imageSubresource.layerCount = 1u; + + vk_cmd_buffer.copyBufferToImage( + DeviceBufferVK::Cast(*staging_buffer).GetBuffer(), // src buffer + GetImage(), // dst image + transition.new_layout, // dst image layout + 1u, // region count + © // regions + ); + + return cmd_buffer->SubmitCommands(); } bool TextureVK::OnSetContents(std::shared_ptr mapping, @@ -56,75 +125,29 @@ ISize TextureVK::GetSize() const { } vk::Image TextureVK::GetImage() const { - return source_->GetVKImage(); + return source_->GetImage(); } vk::ImageView TextureVK::GetImageView() const { - return source_->GetVKImageView(); + return source_->GetImageView(); } -static constexpr vk::ImageAspectFlags ToImageAspectFlags( - vk::ImageLayout layout) { - switch (layout) { - case vk::ImageLayout::eColorAttachmentOptimal: - case vk::ImageLayout::eShaderReadOnlyOptimal: - return vk::ImageAspectFlagBits::eColor; - case vk::ImageLayout::eDepthAttachmentOptimal: - return vk::ImageAspectFlagBits::eDepth; - case vk::ImageLayout::eStencilAttachmentOptimal: - return vk::ImageAspectFlagBits::eStencil; - default: - FML_DLOG(INFO) << "Unknown layout to determine aspect."; - return vk::ImageAspectFlagBits::eNone; - } - FML_UNREACHABLE(); +std::shared_ptr TextureVK::GetTextureSource() const { + return source_; } -vk::ImageLayout TextureVK::GetLayout() const { - ReaderLock lock(layout_mutex_); - return layout_; +bool TextureVK::SetLayout(const LayoutTransition& transition) const { + return source_ ? source_->SetLayout(transition) : false; } vk::ImageLayout TextureVK::SetLayoutWithoutEncoding( vk::ImageLayout layout) const { - WriterLock lock(layout_mutex_); - const auto old_layout = layout_; - layout_ = layout; - return old_layout; + return source_ ? source_->SetLayoutWithoutEncoding(layout) + : vk::ImageLayout::eUndefined; } -bool TextureVK::SetLayout(vk::ImageLayout new_layout, - const vk::CommandBuffer& buffer) const { - const auto old_layout = SetLayoutWithoutEncoding(new_layout); - if (new_layout == old_layout) { - return true; - } - - vk::ImageMemoryBarrier image_barrier; - image_barrier.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | - vk::AccessFlagBits::eTransferWrite; - image_barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | - vk::AccessFlagBits::eShaderRead; - image_barrier.oldLayout = old_layout; - image_barrier.newLayout = new_layout; - image_barrier.image = GetImage(); - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.subresourceRange.aspectMask = ToImageAspectFlags(new_layout); - image_barrier.subresourceRange.baseMipLevel = 0u; - image_barrier.subresourceRange.levelCount = GetTextureDescriptor().mip_count; - image_barrier.subresourceRange.baseArrayLayer = 0u; - image_barrier.subresourceRange.layerCount = 1u; - - buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, // src stage - vk::PipelineStageFlagBits::eAllGraphics, // dst stage - {}, // dependency flags - nullptr, // memory barriers - nullptr, // buffer barriers - image_barrier // image barriers - ); - - return true; +vk::ImageLayout TextureVK::GetLayout() const { + return source_ ? source_->GetLayout() : vk::ImageLayout::eUndefined; } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/texture_vk.h b/impeller/renderer/backend/vulkan/texture_vk.h index 8ab9a00d27aa3..5128c2fd66ad5 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.h +++ b/impeller/renderer/backend/vulkan/texture_vk.h @@ -8,9 +8,9 @@ #include "flutter/fml/macros.h" #include "impeller/base/backend_cast.h" -#include "impeller/base/thread.h" #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" +#include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/texture_source_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/texture.h" @@ -19,8 +19,7 @@ namespace impeller { class TextureVK final : public Texture, public BackendCast { public: - TextureVK(TextureDescriptor desc, - std::weak_ptr context, + TextureVK(std::weak_ptr context, std::shared_ptr source); // |Texture| @@ -30,12 +29,14 @@ class TextureVK final : public Texture, public BackendCast { vk::ImageView GetImageView() const; - bool SetLayout(vk::ImageLayout layout, const vk::CommandBuffer& buffer) const; + bool SetLayout(const LayoutTransition& transition) const; vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const; vk::ImageLayout GetLayout() const; + std::shared_ptr GetTextureSource() const; + private: std::weak_ptr context_; std::shared_ptr source_; diff --git a/impeller/renderer/capabilities.cc b/impeller/renderer/capabilities.cc new file mode 100644 index 0000000000000..b7e6b944211c2 --- /dev/null +++ b/impeller/renderer/capabilities.cc @@ -0,0 +1,159 @@ +// 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 "impeller/renderer/capabilities.h" + +namespace impeller { + +Capabilities::Capabilities() = default; + +Capabilities::~Capabilities() = default; + +class StandardCapabilities final : public Capabilities { + public: + // |Capabilities| + ~StandardCapabilities() override = default; + + // |Capabilities| + bool HasThreadingRestrictions() const override { + return has_threading_restrictions_; + } + + // |Capabilities| + bool SupportsOffscreenMSAA() const override { + return supports_offscreen_msaa_; + } + + // |Capabilities| + bool SupportsSSBO() const override { return supports_ssbo_; } + + // |Capabilities| + bool SupportsTextureToTextureBlits() const override { + return supports_texture_to_texture_blits_; + } + + // |Capabilities| + bool SupportsFramebufferFetch() const override { + return supports_framebuffer_fetch_; + } + + // |Capabilities| + bool SupportsCompute() const override { return supports_compute_; } + + // |Capabilities| + bool SupportsComputeSubgroups() const override { + return supports_compute_subgroups_; + } + + // |Capabilities| + PixelFormat GetDefaultColorFormat() const override { + return default_color_format_; + } + + // |Capabilities| + PixelFormat GetDefaultStencilFormat() const override { + return default_stencil_format_; + } + + private: + StandardCapabilities(bool has_threading_restrictions, + bool supports_offscreen_msaa, + bool supports_ssbo, + bool supports_texture_to_texture_blits, + bool supports_framebuffer_fetch, + bool supports_compute, + bool supports_compute_subgroups, + PixelFormat default_color_format, + PixelFormat default_stencil_format) + : has_threading_restrictions_(has_threading_restrictions), + supports_offscreen_msaa_(supports_offscreen_msaa), + supports_ssbo_(supports_ssbo), + supports_texture_to_texture_blits_(supports_texture_to_texture_blits), + supports_framebuffer_fetch_(supports_framebuffer_fetch), + supports_compute_(supports_compute), + supports_compute_subgroups_(supports_compute_subgroups), + default_color_format_(default_color_format), + default_stencil_format_(default_stencil_format) {} + + friend class CapabilitiesBuilder; + + bool has_threading_restrictions_ = false; + bool supports_offscreen_msaa_ = false; + bool supports_ssbo_ = false; + bool supports_texture_to_texture_blits_ = false; + bool supports_framebuffer_fetch_ = false; + bool supports_compute_ = false; + bool supports_compute_subgroups_ = false; + PixelFormat default_color_format_ = PixelFormat::kUnknown; + PixelFormat default_stencil_format_ = PixelFormat::kUnknown; + + FML_DISALLOW_COPY_AND_ASSIGN(StandardCapabilities); +}; + +CapabilitiesBuilder::CapabilitiesBuilder() = default; + +CapabilitiesBuilder::~CapabilitiesBuilder() = default; + +CapabilitiesBuilder& CapabilitiesBuilder::SetHasThreadingRestrictions( + bool value) { + has_threading_restrictions_ = value; + return *this; +} + +CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsOffscreenMSAA(bool value) { + supports_offscreen_msaa_ = value; + return *this; +} + +CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsSSBO(bool value) { + supports_ssbo_ = value; + return *this; +} + +CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsTextureToTextureBlits( + bool value) { + supports_texture_to_texture_blits_ = value; + return *this; +} + +CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsFramebufferFetch( + bool value) { + supports_framebuffer_fetch_ = value; + return *this; +} + +CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsCompute(bool compute, + bool subgroups) { + supports_compute_ = compute; + supports_compute_subgroups_ = subgroups; + return *this; +} + +CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultColorFormat( + PixelFormat value) { + default_color_format_ = value; + return *this; +} + +CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultStencilFormat( + PixelFormat value) { + default_stencil_format_ = value; + return *this; +} + +std::unique_ptr CapabilitiesBuilder::Build() { + return std::unique_ptr(new StandardCapabilities( // + has_threading_restrictions_, // + supports_offscreen_msaa_, // + supports_ssbo_, // + supports_texture_to_texture_blits_, // + supports_framebuffer_fetch_, // + supports_compute_, // + supports_compute_subgroups_, // + *default_color_format_, // + *default_stencil_format_ // + )); +} + +} // namespace impeller diff --git a/impeller/renderer/capabilities.h b/impeller/renderer/capabilities.h new file mode 100644 index 0000000000000..945e9fde3fbc2 --- /dev/null +++ b/impeller/renderer/capabilities.h @@ -0,0 +1,80 @@ +// 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. + +#pragma once + +#include + +#include "flutter/fml/macros.h" +#include "impeller/renderer/formats.h" + +namespace impeller { + +class Capabilities { + public: + virtual ~Capabilities(); + + virtual bool HasThreadingRestrictions() const = 0; + + virtual bool SupportsOffscreenMSAA() const = 0; + + virtual bool SupportsSSBO() const = 0; + + virtual bool SupportsTextureToTextureBlits() const = 0; + + virtual bool SupportsFramebufferFetch() const = 0; + + virtual bool SupportsCompute() const = 0; + + virtual bool SupportsComputeSubgroups() const = 0; + + virtual PixelFormat GetDefaultColorFormat() const = 0; + + virtual PixelFormat GetDefaultStencilFormat() const = 0; + + protected: + Capabilities(); + + FML_DISALLOW_COPY_AND_ASSIGN(Capabilities); +}; + +class CapabilitiesBuilder { + public: + CapabilitiesBuilder(); + + ~CapabilitiesBuilder(); + + CapabilitiesBuilder& SetHasThreadingRestrictions(bool value); + + CapabilitiesBuilder& SetSupportsOffscreenMSAA(bool value); + + CapabilitiesBuilder& SetSupportsSSBO(bool value); + + CapabilitiesBuilder& SetSupportsTextureToTextureBlits(bool value); + + CapabilitiesBuilder& SetSupportsFramebufferFetch(bool value); + + CapabilitiesBuilder& SetSupportsCompute(bool compute, bool subgroups); + + CapabilitiesBuilder& SetDefaultColorFormat(PixelFormat value); + + CapabilitiesBuilder& SetDefaultStencilFormat(PixelFormat value); + + std::unique_ptr Build(); + + private: + bool has_threading_restrictions_ = false; + bool supports_offscreen_msaa_ = false; + bool supports_ssbo_ = false; + bool supports_texture_to_texture_blits_ = false; + bool supports_framebuffer_fetch_ = false; + bool supports_compute_ = false; + bool supports_compute_subgroups_ = false; + std::optional default_color_format_ = std::nullopt; + std::optional default_stencil_format_ = std::nullopt; + + FML_DISALLOW_COPY_AND_ASSIGN(CapabilitiesBuilder); +}; + +} // namespace impeller diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc index 1b93ae66ec243..f5305f278da57 100644 --- a/impeller/renderer/compute_subgroup_unittests.cc +++ b/impeller/renderer/compute_subgroup_unittests.cc @@ -39,7 +39,7 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups()); + ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups()); auto cmd_buffer = context->CreateCommandBuffer(); auto pass = cmd_buffer->CreateComputePass(); @@ -258,7 +258,7 @@ TEST_P(ComputeTest, QuadsToPolyline) { using QS = QuadPolylineComputeShader; auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups()); + ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups()); auto cmd_buffer = context->CreateCommandBuffer(); auto pass = cmd_buffer->CreateComputePass(); diff --git a/impeller/renderer/compute_unittests.cc b/impeller/renderer/compute_unittests.cc index ffed4bd7e8502..62ddeadb44b49 100644 --- a/impeller/renderer/compute_unittests.cc +++ b/impeller/renderer/compute_unittests.cc @@ -28,7 +28,7 @@ TEST_P(ComputeTest, CanCreateComputePass) { using CS = SampleComputeShader; auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetDeviceCapabilities().SupportsCompute()); + ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); using SamplePipelineBuilder = ComputePipelineBuilder; auto pipeline_desc = @@ -111,7 +111,7 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) { auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetDeviceCapabilities().SupportsCompute()); + ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); auto pipeline_desc_1 = Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context); diff --git a/impeller/renderer/context.cc b/impeller/renderer/context.cc index 9d8aad55e681a..1525dfc1bf0f9 100644 --- a/impeller/renderer/context.cc +++ b/impeller/renderer/context.cc @@ -14,8 +14,8 @@ std::shared_ptr Context::GetGPUTracer() const { return nullptr; } -PixelFormat Context::GetColorAttachmentPixelFormat() const { - return GetDeviceCapabilities().GetDefaultColorFormat(); +bool Context::UpdateOffscreenLayerPixelFormat(PixelFormat format) { + return false; } } // namespace impeller diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index a6a485c3e6de3..f78d2e3d00f12 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -8,7 +8,7 @@ #include #include "flutter/fml/macros.h" -#include "impeller/renderer/device_capabilities.h" +#include "impeller/renderer/capabilities.h" #include "impeller/renderer/formats.h" namespace impeller { @@ -27,9 +27,11 @@ class Context : public std::enable_shared_from_this { virtual bool IsValid() const = 0; - //---------------------------------------------------------------------------- - /// @return A resource allocator. - /// + virtual const std::shared_ptr& GetCapabilities() + const = 0; + + virtual bool UpdateOffscreenLayerPixelFormat(PixelFormat format); + virtual std::shared_ptr GetResourceAllocator() const = 0; virtual std::shared_ptr GetShaderLibrary() const = 0; @@ -42,15 +44,8 @@ class Context : public std::enable_shared_from_this { virtual std::shared_ptr GetWorkQueue() const = 0; - //---------------------------------------------------------------------------- - /// @return A GPU Tracer to trace gpu rendering. - /// virtual std::shared_ptr GetGPUTracer() const; - virtual PixelFormat GetColorAttachmentPixelFormat() const; - - virtual const IDeviceCapabilities& GetDeviceCapabilities() const = 0; - protected: Context(); diff --git a/impeller/renderer/descriptor_set_layout.h b/impeller/renderer/descriptor_set_layout.h deleted file mode 100644 index d853f0a663086..0000000000000 --- a/impeller/renderer/descriptor_set_layout.h +++ /dev/null @@ -1,27 +0,0 @@ -// 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. - -#pragma once - -#include -#include - -#include "flutter/fml/macros.h" -#include "impeller/renderer/shader_types.h" - -namespace impeller { - -enum class DescriptorType { - kSampledImage, - kUniformBuffer, -}; - -struct DescriptorSetLayout { - uint32_t binding; - DescriptorType descriptor_type; - uint32_t descriptor_count; - ShaderStage shader_stage; -}; - -} // namespace impeller diff --git a/impeller/renderer/device_capabilities.cc b/impeller/renderer/device_capabilities.cc deleted file mode 100644 index bf88bbc4c5f6b..0000000000000 --- a/impeller/renderer/device_capabilities.cc +++ /dev/null @@ -1,141 +0,0 @@ -// 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 "impeller/renderer/device_capabilities.h" -#include "device_capabilities.h" - -namespace impeller { - -IDeviceCapabilities::IDeviceCapabilities(bool has_threading_restrictions, - bool supports_offscreen_msaa, - bool supports_ssbo, - bool supports_texture_to_texture_blits, - bool supports_framebuffer_fetch, - PixelFormat default_color_format, - PixelFormat default_stencil_format, - bool supports_compute, - bool supports_compute_subgroups) - : has_threading_restrictions_(has_threading_restrictions), - supports_offscreen_msaa_(supports_offscreen_msaa), - supports_ssbo_(supports_ssbo), - supports_texture_to_texture_blits_(supports_texture_to_texture_blits), - supports_framebuffer_fetch_(supports_framebuffer_fetch), - default_color_format_(default_color_format), - default_stencil_format_(default_stencil_format), - supports_compute_(supports_compute), - supports_compute_subgroups_(supports_compute_subgroups) {} - -IDeviceCapabilities::~IDeviceCapabilities() = default; - -bool IDeviceCapabilities::HasThreadingRestrictions() const { - return has_threading_restrictions_; -} - -bool IDeviceCapabilities::SupportsOffscreenMSAA() const { - return supports_offscreen_msaa_; -} - -bool IDeviceCapabilities::SupportsSSBO() const { - return supports_ssbo_; -} - -bool IDeviceCapabilities::SupportsTextureToTextureBlits() const { - return supports_texture_to_texture_blits_; -} - -bool IDeviceCapabilities::SupportsFramebufferFetch() const { - return supports_framebuffer_fetch_; -} - -PixelFormat IDeviceCapabilities::GetDefaultColorFormat() const { - return default_color_format_; -} - -PixelFormat IDeviceCapabilities::GetDefaultStencilFormat() const { - return default_stencil_format_; -} - -bool IDeviceCapabilities::SupportsCompute() const { - return supports_compute_; -} - -bool IDeviceCapabilities::SupportsComputeSubgroups() const { - return supports_compute_subgroups_; -} - -DeviceCapabilitiesBuilder::DeviceCapabilitiesBuilder() = default; - -DeviceCapabilitiesBuilder::~DeviceCapabilitiesBuilder() = default; - -DeviceCapabilitiesBuilder& -DeviceCapabilitiesBuilder::SetHasThreadingRestrictions(bool value) { - has_threading_restrictions_ = value; - return *this; -} - -DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetSupportsOffscreenMSAA( - bool value) { - supports_offscreen_msaa_ = value; - return *this; -} - -DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetSupportsSSBO( - bool value) { - supports_ssbo_ = value; - return *this; -} - -DeviceCapabilitiesBuilder& -DeviceCapabilitiesBuilder::SetSupportsTextureToTextureBlits(bool value) { - supports_texture_to_texture_blits_ = value; - return *this; -} - -DeviceCapabilitiesBuilder& -DeviceCapabilitiesBuilder::SetSupportsFramebufferFetch(bool value) { - supports_framebuffer_fetch_ = value; - return *this; -} - -DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetDefaultColorFormat( - PixelFormat value) { - default_color_format_ = value; - return *this; -} - -DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetDefaultStencilFormat( - PixelFormat value) { - default_stencil_format_ = value; - return *this; -} - -DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetSupportsCompute( - bool value, - bool subgroups) { - supports_compute_ = value; - supports_compute_subgroups_ = subgroups; - return *this; -} - -std::unique_ptr DeviceCapabilitiesBuilder::Build() { - FML_CHECK(default_color_format_.has_value()) - << "Default color format not set"; - FML_CHECK(default_stencil_format_.has_value()) - << "Default stencil format not set"; - - IDeviceCapabilities* capabilities = new IDeviceCapabilities( // - has_threading_restrictions_, // - supports_offscreen_msaa_, // - supports_ssbo_, // - supports_texture_to_texture_blits_, // - supports_framebuffer_fetch_, // - *default_color_format_, // - *default_stencil_format_, // - supports_compute_, // - supports_compute_subgroups_ // - ); - return std::unique_ptr(capabilities); -} - -} // namespace impeller diff --git a/impeller/renderer/device_capabilities.h b/impeller/renderer/device_capabilities.h deleted file mode 100644 index f74d95c27f494..0000000000000 --- a/impeller/renderer/device_capabilities.h +++ /dev/null @@ -1,99 +0,0 @@ -// 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. - -#pragma once - -#include - -#include "flutter/fml/macros.h" -#include "impeller/renderer/formats.h" - -namespace impeller { - -class IDeviceCapabilities { - public: - ~IDeviceCapabilities(); - - bool HasThreadingRestrictions() const; - - bool SupportsOffscreenMSAA() const; - - bool SupportsSSBO() const; - - bool SupportsTextureToTextureBlits() const; - - bool SupportsFramebufferFetch() const; - - PixelFormat GetDefaultColorFormat() const; - - PixelFormat GetDefaultStencilFormat() const; - - bool SupportsCompute() const; - bool SupportsComputeSubgroups() const; - - private: - IDeviceCapabilities(bool has_threading_restrictions, - bool supports_offscreen_msaa, - bool supports_ssbo, - bool supports_texture_to_texture_blits, - bool supports_framebuffer_fetch, - PixelFormat default_color_format, - PixelFormat default_stencil_format, - bool supports_compute, - bool supports_compute_subgroups); - - friend class DeviceCapabilitiesBuilder; - - bool has_threading_restrictions_ = false; - bool supports_offscreen_msaa_ = false; - bool supports_ssbo_ = false; - bool supports_texture_to_texture_blits_ = false; - bool supports_framebuffer_fetch_ = false; - PixelFormat default_color_format_; - PixelFormat default_stencil_format_; - bool supports_compute_ = false; - bool supports_compute_subgroups_ = false; - - FML_DISALLOW_COPY_AND_ASSIGN(IDeviceCapabilities); -}; - -class DeviceCapabilitiesBuilder { - public: - DeviceCapabilitiesBuilder(); - - ~DeviceCapabilitiesBuilder(); - - DeviceCapabilitiesBuilder& SetHasThreadingRestrictions(bool value); - - DeviceCapabilitiesBuilder& SetSupportsOffscreenMSAA(bool value); - - DeviceCapabilitiesBuilder& SetSupportsSSBO(bool value); - - DeviceCapabilitiesBuilder& SetSupportsTextureToTextureBlits(bool value); - - DeviceCapabilitiesBuilder& SetSupportsFramebufferFetch(bool value); - - DeviceCapabilitiesBuilder& SetDefaultColorFormat(PixelFormat value); - - DeviceCapabilitiesBuilder& SetDefaultStencilFormat(PixelFormat value); - - DeviceCapabilitiesBuilder& SetSupportsCompute(bool value, bool subgroups); - - std::unique_ptr Build(); - - private: - bool has_threading_restrictions_ = false; - bool supports_offscreen_msaa_ = false; - bool supports_ssbo_ = false; - bool supports_texture_to_texture_blits_ = false; - bool supports_framebuffer_fetch_ = false; - bool supports_compute_ = false; - bool supports_compute_subgroups_ = false; - std::optional default_color_format_ = std::nullopt; - std::optional default_stencil_format_ = std::nullopt; - - FML_DISALLOW_COPY_AND_ASSIGN(DeviceCapabilitiesBuilder); -}; - -} // namespace impeller diff --git a/impeller/renderer/formats.h b/impeller/renderer/formats.h index 170a068da607f..79daace56ff96 100644 --- a/impeller/renderer/formats.h +++ b/impeller/renderer/formats.h @@ -188,6 +188,10 @@ enum class TextureUsage : TextureUsageMask { kRenderTarget = 1 << 2, }; +constexpr bool TextureUsageIsRenderTarget(TextureUsageMask mask) { + return static_cast(TextureUsage::kRenderTarget) & mask; +} + enum class TextureIntent { kUploadFromHost, kRenderToTexture, diff --git a/impeller/renderer/pipeline_builder.h b/impeller/renderer/pipeline_builder.h index efaab15e65865..c1c3fbb94781c 100644 --- a/impeller/renderer/pipeline_builder.h +++ b/impeller/renderer/pipeline_builder.h @@ -117,7 +117,7 @@ struct PipelineBuilder { // Configure the sole color attachments pixel format. This is by // convention. ColorAttachmentDescriptor color0; - color0.format = context.GetColorAttachmentPixelFormat(); + color0.format = context.GetCapabilities()->GetDefaultColorFormat(); color0.blending_enabled = true; desc.SetColorAttachmentDescriptor(0u, color0); } @@ -128,7 +128,7 @@ struct PipelineBuilder { stencil0.stencil_compare = CompareFunction::kEqual; desc.SetStencilAttachmentDescriptors(stencil0); desc.SetStencilPixelFormat( - context.GetDeviceCapabilities().GetDefaultStencilFormat()); + context.GetCapabilities()->GetDefaultStencilFormat()); } return true; diff --git a/impeller/renderer/render_target.cc b/impeller/renderer/render_target.cc index aba17fd6532ef..167a4d3d37b34 100644 --- a/impeller/renderer/render_target.cc +++ b/impeller/renderer/render_target.cc @@ -210,7 +210,7 @@ RenderTarget RenderTarget::CreateOffscreen( } RenderTarget target; - PixelFormat pixel_format = context.GetColorAttachmentPixelFormat(); + PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat(); TextureDescriptor color_tex0; color_tex0.storage_mode = color_attachment_config.storage_mode; color_tex0.format = pixel_format; @@ -233,8 +233,7 @@ RenderTarget RenderTarget::CreateOffscreen( if (stencil_attachment_config.has_value()) { TextureDescriptor stencil_tex0; stencil_tex0.storage_mode = stencil_attachment_config->storage_mode; - stencil_tex0.format = - context.GetDeviceCapabilities().GetDefaultStencilFormat(); + stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); stencil_tex0.size = size; stencil_tex0.usage = static_cast(TextureUsage::kRenderTarget); @@ -269,7 +268,7 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( } RenderTarget target; - PixelFormat pixel_format = context.GetColorAttachmentPixelFormat(); + PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat(); // Create MSAA color texture. @@ -327,8 +326,7 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( stencil_tex0.storage_mode = stencil_attachment_config->storage_mode; stencil_tex0.type = TextureType::kTexture2DMultisample; stencil_tex0.sample_count = SampleCount::kCount4; - stencil_tex0.format = - context.GetDeviceCapabilities().GetDefaultStencilFormat(); + stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); stencil_tex0.size = size; stencil_tex0.usage = static_cast(TextureUsage::kRenderTarget); diff --git a/impeller/renderer/sampler.h b/impeller/renderer/sampler.h index 2b14d2843c5a3..41a16f5b74865 100644 --- a/impeller/renderer/sampler.h +++ b/impeller/renderer/sampler.h @@ -20,7 +20,7 @@ class Sampler { protected: SamplerDescriptor desc_; - Sampler(SamplerDescriptor desc); + explicit Sampler(SamplerDescriptor desc); private: FML_DISALLOW_COPY_AND_ASSIGN(Sampler); diff --git a/impeller/renderer/shader_types.h b/impeller/renderer/shader_types.h index 400607c1f55f6..b29bffd6f1260 100644 --- a/impeller/renderer/shader_types.h +++ b/impeller/renderer/shader_types.h @@ -123,6 +123,17 @@ struct SampledImageSlot { constexpr bool HasSampler() const { return sampler_index < 32u; } }; +enum class DescriptorType { + kSampledImage, + kUniformBuffer, +}; + +struct DescriptorSetLayout { + uint32_t binding; + DescriptorType descriptor_type; + ShaderStage shader_stage; +}; + template struct Padding { private: diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index 1f387ee58e05a..7357cec41514c 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -97,9 +97,8 @@ class MockImpellerContext : public Context { MOCK_CONST_METHOD0(GetGPUTracer, std::shared_ptr()); - MOCK_CONST_METHOD0(GetColorAttachmentPixelFormat, PixelFormat()); - - MOCK_CONST_METHOD0(GetDeviceCapabilities, const IDeviceCapabilities&()); + MOCK_CONST_METHOD0(GetCapabilities, + const std::shared_ptr&()); }; class MockTexture : public Texture { diff --git a/impeller/renderer/vertex_descriptor.h b/impeller/renderer/vertex_descriptor.h index dffe6694f7caf..8d145bb0f503e 100644 --- a/impeller/renderer/vertex_descriptor.h +++ b/impeller/renderer/vertex_descriptor.h @@ -8,7 +8,6 @@ #include "flutter/fml/macros.h" #include "impeller/base/comparable.h" -#include "impeller/renderer/descriptor_set_layout.h" #include "impeller/renderer/shader_types.h" namespace impeller { diff --git a/impeller/runtime_stage/runtime_stage_unittests.cc b/impeller/runtime_stage/runtime_stage_unittests.cc index 896ecab89e824..d5596afa6748f 100644 --- a/impeller/runtime_stage/runtime_stage_unittests.cc +++ b/impeller/runtime_stage/runtime_stage_unittests.cc @@ -242,13 +242,13 @@ TEST_P(RuntimeStageTest, CanCreatePipelineFromRuntimeStage) { ASSERT_TRUE(vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs)); desc.SetVertexDescriptor(std::move(vertex_descriptor)); ColorAttachmentDescriptor color0; - color0.format = GetContext()->GetColorAttachmentPixelFormat(); + color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat(); StencilAttachmentDescriptor stencil0; stencil0.stencil_compare = CompareFunction::kEqual; desc.SetColorAttachmentDescriptor(0u, color0); desc.SetStencilAttachmentDescriptors(stencil0); const auto stencil_fmt = - GetContext()->GetDeviceCapabilities().GetDefaultStencilFormat(); + GetContext()->GetCapabilities()->GetDefaultStencilFormat(); desc.SetStencilPixelFormat(stencil_fmt); auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get(); ASSERT_NE(pipeline, nullptr); diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc index 04c4cd84b26c6..45c02e5b28b1b 100644 --- a/lib/ui/painting/image_decoder_impeller.cc +++ b/lib/ui/painting/image_decoder_impeller.cc @@ -325,7 +325,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr descriptor, // Depending on whether the context has threading restrictions, stay on // the concurrent runner to perform texture upload or move to an IO // runner. - if (context->GetDeviceCapabilities().HasThreadingRestrictions()) { + if (context->GetCapabilities()->HasThreadingRestrictions()) { io_runner->PostTask(upload_texture_and_invoke_result); } else { upload_texture_and_invoke_result(); diff --git a/shell/platform/darwin/ios/ios_surface_metal_impeller.mm b/shell/platform/darwin/ios/ios_surface_metal_impeller.mm index c1696ff309d70..a74343ba1fe26 100644 --- a/shell/platform/darwin/ios/ios_surface_metal_impeller.mm +++ b/shell/platform/darwin/ios/ios_surface_metal_impeller.mm @@ -8,8 +8,9 @@ #include "flutter/impeller/renderer/context.h" #include "flutter/shell/gpu/gpu_surface_metal_impeller.h" -namespace { -impeller::PixelFormat InferOffscreenLayerPixelFormat(impeller::PixelFormat pixel_format) { +namespace flutter { + +static impeller::PixelFormat InferOffscreenLayerPixelFormat(impeller::PixelFormat pixel_format) { switch (pixel_format) { case impeller::PixelFormat::kB10G10R10XR: return impeller::PixelFormat::kB10G10R10A10XR; @@ -17,66 +18,6 @@ return pixel_format; } } -} // namespace - -namespace impeller { -namespace { -// This appears to be the only safe way to override the -// GetColorAttachmentPixelFormat method. It is assumed in the Context that -// there will be one pixel format for the whole app which is not true. So, it -// is unsafe to mutate the Context and you cannot clone the Context at this -// level since the Context does not safely manage the MTLDevice. -class CustomColorAttachmentPixelFormatContext final : public Context { - public: - CustomColorAttachmentPixelFormatContext(const std::shared_ptr& context, - PixelFormat color_attachment_pixel_format) - : context_(context), color_attachment_pixel_format_(color_attachment_pixel_format) {} - - bool IsValid() const override { return context_->IsValid(); } - - std::shared_ptr GetResourceAllocator() const override { - return context_->GetResourceAllocator(); - } - - std::shared_ptr GetShaderLibrary() const override { - return context_->GetShaderLibrary(); - } - - std::shared_ptr GetSamplerLibrary() const override { - return context_->GetSamplerLibrary(); - } - - std::shared_ptr GetPipelineLibrary() const override { - return context_->GetPipelineLibrary(); - } - - std::shared_ptr CreateCommandBuffer() const override { - return context_->CreateCommandBuffer(); - } - - std::shared_ptr GetWorkQueue() const override { return context_->GetWorkQueue(); } - - std::shared_ptr GetGPUTracer() const override { return context_->GetGPUTracer(); } - - PixelFormat GetColorAttachmentPixelFormat() const override { - return color_attachment_pixel_format_; - } - - const IDeviceCapabilities& GetDeviceCapabilities() const override { - return context_->GetDeviceCapabilities(); - } - - private: - std::shared_ptr context_; - PixelFormat color_attachment_pixel_format_; -}; -} // namespace -} // namespace impeller - -namespace flutter { - -using impeller::CustomColorAttachmentPixelFormatContext; -using impeller::FromMTLPixelFormat; IOSSurfaceMetalImpeller::IOSSurfaceMetalImpeller(const fml::scoped_nsobject& layer, const std::shared_ptr& context) @@ -87,7 +28,8 @@ PixelFormat GetColorAttachmentPixelFormat() const override { if (!impeller_context_) { return; } - is_valid_ = true; + is_valid_ = impeller_context_->UpdateOffscreenLayerPixelFormat( + InferOffscreenLayerPixelFormat(impeller::FromMTLPixelFormat(layer_.get().pixelFormat))); } // |IOSSurface| @@ -105,11 +47,8 @@ PixelFormat GetColorAttachmentPixelFormat() const override { // |IOSSurface| std::unique_ptr IOSSurfaceMetalImpeller::CreateGPUSurface(GrDirectContext*) { - auto context = std::make_shared( - impeller_context_, - InferOffscreenLayerPixelFormat(FromMTLPixelFormat(layer_.get().pixelFormat))); - return std::make_unique(this, // - context // + return std::make_unique(this, // + impeller_context_ // ); } From 24afaf9eb60f177e29300ea09c70b8a525917a46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 09:44:31 +0000 Subject: [PATCH 11/16] Bump github/codeql-action from 2.2.5 to 2.2.6 (#40246) Bump github/codeql-action from 2.2.5 to 2.2.6 --- .github/workflows/scorecards-analysis.yml | 2 +- .github/workflows/third_party_scan.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 818126d58b0a2..10a01d9900b27 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -65,6 +65,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@32dc499307d133bb5085bae78498c0ac2cf762d5 + uses: github/codeql-action/upload-sarif@16964e90ba004cdf0cd845b866b5df21038b7723 with: sarif_file: results.sarif diff --git a/.github/workflows/third_party_scan.yml b/.github/workflows/third_party_scan.yml index b93e79714b576..d8dd3c15a550c 100644 --- a/.github/workflows/third_party_scan.yml +++ b/.github/workflows/third_party_scan.yml @@ -51,6 +51,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@32dc499307d133bb5085bae78498c0ac2cf762d5 + uses: github/codeql-action/upload-sarif@16964e90ba004cdf0cd845b866b5df21038b7723 with: sarif_file: osvReport.sarif From bb1ca8f1e659b329bff1ebe19dadfd91a2fa6e05 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 13 Mar 2023 13:43:04 +0100 Subject: [PATCH 12/16] Change `extends Iterator` to using `implements` (#40175) The Dart 3.0 libraries will mark Iterator with the interface class modifier, which prevents extends. It will do so because the class has no implementation to inherit, and is only intended as an interface, which it is now possible to express. This should unblock relanding https://dart-review.googlesource.com/c/sdk/+/287760 (Also working on disabling the class-modifiers experiment for Flutter dart: libraries, which was enabled along with the Dart SDK libraries, until the experiment can be intentionally turned back on.) --- lib/web_ui/lib/src/engine/dom.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/web_ui/lib/src/engine/dom.dart b/lib/web_ui/lib/src/engine/dom.dart index 034899755f56c..01b9da8199174 100644 --- a/lib/web_ui/lib/src/engine/dom.dart +++ b/lib/web_ui/lib/src/engine/dom.dart @@ -2053,7 +2053,7 @@ extension DomListExtension on _DomList { js_util.callMethod(this, 'item', [index.toDouble()]); } -class _DomListIterator extends Iterator { +class _DomListIterator implements Iterator { _DomListIterator(this.list); final _DomList list; @@ -2101,7 +2101,7 @@ extension DomTouchListExtension on _DomTouchList { js_util.callMethod(this, 'item', [index.toDouble()]); } -class _DomTouchListIterator extends Iterator { +class _DomTouchListIterator implements Iterator { _DomTouchListIterator(this.list); final _DomTouchList list; From 3ac895ee38b8f188e1a8da06abd357eba9f9ba7c Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 13 Mar 2023 08:42:13 -0700 Subject: [PATCH 13/16] [Impeller] support for foreground shaders on text (#40193) [Impeller] support for foreground shaders on text --- ci/licenses_golden/licenses_flutter | 4 + impeller/aiks/canvas.cc | 31 ++++++- .../display_list/display_list_unittests.cc | 19 +++++ impeller/entity/BUILD.gn | 2 + .../entity/contents/color_source_contents.h | 4 +- .../contents/color_source_text_contents.cc | 84 +++++++++++++++++++ .../contents/color_source_text_contents.h | 48 +++++++++++ impeller/entity/contents/text_contents.cc | 17 ++-- impeller/entity/contents/text_contents.h | 3 + impeller/geometry/geometry_unittests.cc | 7 ++ impeller/geometry/rect.h | 6 ++ 11 files changed, 215 insertions(+), 10 deletions(-) create mode 100644 impeller/entity/contents/color_source_text_contents.cc create mode 100644 impeller/entity/contents/color_source_text_contents.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index f3cf26206c773..7c510864e4266 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1121,6 +1121,8 @@ ORIGIN: ../../../flutter/impeller/entity/contents/clip_contents.cc + ../../../fl ORIGIN: ../../../flutter/impeller/entity/contents/clip_contents.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/color_source_contents.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/color_source_contents.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/contents/color_source_text_contents.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/contents/color_source_text_contents.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/content_context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/content_context.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/contents.cc + ../../../flutter/LICENSE @@ -3655,6 +3657,8 @@ FILE: ../../../flutter/impeller/entity/contents/clip_contents.cc FILE: ../../../flutter/impeller/entity/contents/clip_contents.h FILE: ../../../flutter/impeller/entity/contents/color_source_contents.cc FILE: ../../../flutter/impeller/entity/contents/color_source_contents.h +FILE: ../../../flutter/impeller/entity/contents/color_source_text_contents.cc +FILE: ../../../flutter/impeller/entity/contents/color_source_text_contents.h FILE: ../../../flutter/impeller/entity/contents/content_context.cc FILE: ../../../flutter/impeller/entity/contents/content_context.h FILE: ../../../flutter/impeller/entity/contents/contents.cc diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 0b86986c34a3e..b88543c1596da 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -12,6 +12,7 @@ #include "impeller/aiks/paint_pass_delegate.h" #include "impeller/entity/contents/atlas_contents.h" #include "impeller/entity/contents/clip_contents.h" +#include "impeller/entity/contents/color_source_text_contents.h" #include "impeller/entity/contents/rrect_shadow_contents.h" #include "impeller/entity/contents/text_contents.h" #include "impeller/entity/contents/texture_contents.h" @@ -380,16 +381,40 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame, const Paint& paint) { lazy_glyph_atlas_->AddTextFrame(text_frame); + Entity entity; + entity.SetStencilDepth(GetStencilDepth()); + entity.SetBlendMode(paint.blend_mode); + auto text_contents = std::make_shared(); text_contents->SetTextFrame(text_frame); text_contents->SetGlyphAtlas(lazy_glyph_atlas_); + + if (paint.color_source.has_value()) { + auto& source = paint.color_source.value(); + auto color_text_contents = std::make_shared(); + entity.SetTransformation(GetCurrentTransformation()); + + Entity test; + auto cvg = text_contents->GetCoverage(test).value(); + color_text_contents->SetTextPosition(cvg.origin + position); + + text_contents->SetInverseMatrix( + Matrix::MakeTranslation(Vector3(-cvg.origin.x, -cvg.origin.y, 0))); + color_text_contents->SetTextContents(std::move(text_contents)); + color_text_contents->SetColorSourceContents(source()); + + entity.SetContents( + paint.WithFilters(std::move(color_text_contents), false)); + + GetCurrentPass().AddEntity(entity); + return; + } + text_contents->SetColor(paint.color); - Entity entity; entity.SetTransformation(GetCurrentTransformation() * Matrix::MakeTranslation(position)); - entity.SetStencilDepth(GetStencilDepth()); - entity.SetBlendMode(paint.blend_mode); + entity.SetContents(paint.WithFilters(std::move(text_contents), true)); GetCurrentPass().AddEntity(entity); diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index 0c5c9565b69f3..d214406eca2d2 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -57,6 +57,25 @@ TEST_P(DisplayListTest, CanDrawTextBlob) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(DisplayListTest, CanDrawTextBlobWithGradient) { + flutter::DisplayListBuilder builder; + + std::vector colors = {flutter::DlColor::kBlue(), + flutter::DlColor::kRed()}; + const float stops[2] = {0.0, 1.0}; + + auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0}, + 2, colors.data(), stops, + flutter::DlTileMode::kClamp); + flutter::DlPaint paint; + paint.setColorSource(linear); + + builder.DrawTextBlob( + SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100, + paint); + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + TEST_P(DisplayListTest, CanDrawTextWithSaveLayer) { flutter::DisplayListBuilder builder; builder.setColor(SK_ColorRED); diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 1c1fc90d25776..0a68451519643 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -120,6 +120,8 @@ impeller_component("entity") { "contents/clip_contents.h", "contents/color_source_contents.cc", "contents/color_source_contents.h", + "contents/color_source_text_contents.cc", + "contents/color_source_text_contents.h", "contents/content_context.cc", "contents/content_context.h", "contents/contents.cc", diff --git a/impeller/entity/contents/color_source_contents.h b/impeller/entity/contents/color_source_contents.h index 89a86cf47ea78..5eacfc6041a39 100644 --- a/impeller/entity/contents/color_source_contents.h +++ b/impeller/entity/contents/color_source_contents.h @@ -22,6 +22,8 @@ class ColorSourceContents : public Contents { void SetEffectTransform(Matrix matrix); + const Matrix& GetInverseMatrix() const; + void SetAlpha(Scalar alpha); // |Contents| @@ -34,8 +36,6 @@ class ColorSourceContents : public Contents { protected: const std::shared_ptr& GetGeometry() const; - const Matrix& GetInverseMatrix() const; - Scalar GetAlpha() const; private: diff --git a/impeller/entity/contents/color_source_text_contents.cc b/impeller/entity/contents/color_source_text_contents.cc new file mode 100644 index 0000000000000..3301fb26c9e7e --- /dev/null +++ b/impeller/entity/contents/color_source_text_contents.cc @@ -0,0 +1,84 @@ +// 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 "impeller/entity/contents/color_source_text_contents.h" + +#include "impeller/entity/contents/content_context.h" +#include "impeller/entity/contents/texture_contents.h" +#include "impeller/renderer/render_pass.h" + +namespace impeller { + +ColorSourceTextContents::ColorSourceTextContents() = default; + +ColorSourceTextContents::~ColorSourceTextContents() = default; + +void ColorSourceTextContents::SetTextContents( + std::shared_ptr text_contents) { + text_contents_ = std::move(text_contents); +} + +void ColorSourceTextContents::SetColorSourceContents( + std::shared_ptr color_source_contents) { + color_source_contents_ = std::move(color_source_contents); +} + +std::optional ColorSourceTextContents::GetCoverage( + const Entity& entity) const { + return text_contents_->GetCoverage(entity); +} + +void ColorSourceTextContents::SetTextPosition(Point position) { + position_ = position; +} + +bool ColorSourceTextContents::Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + auto coverage = text_contents_->GetCoverage(entity); + if (!coverage.has_value()) { + return true; + } + auto transform = entity.GetTransformation(); + + text_contents_->SetColor(Color::Black()); + color_source_contents_->SetGeometry( + Geometry::MakeRect(Rect::MakeSize(coverage->size))); + + // offset the color source so it behaves as if it were drawn in the original + // position. + auto effect_transform = + color_source_contents_->GetInverseMatrix().Invert().Translate(-position_); + color_source_contents_->SetEffectTransform(effect_transform); + + auto new_texture = renderer.MakeSubpass( + "Text Color Blending", ISize::Ceil(coverage.value().size), + [&](const ContentContext& context, RenderPass& pass) { + Entity sub_entity; + sub_entity.SetTransformation(transform); + sub_entity.SetContents(text_contents_); + sub_entity.SetBlendMode(BlendMode::kSource); + if (!sub_entity.Render(context, pass)) { + return false; + } + + sub_entity.SetContents(color_source_contents_); + sub_entity.SetBlendMode(BlendMode::kSourceIn); + return sub_entity.Render(context, pass); + }); + if (!new_texture) { + return false; + } + + auto dest_rect = Rect::MakeSize(new_texture->GetSize()) + .TransformBounds(transform.Invert()) + .Shift(position_); + + auto texture_contents = TextureContents::MakeRect(dest_rect); + texture_contents->SetTexture(new_texture); + texture_contents->SetSourceRect(Rect::MakeSize(new_texture->GetSize())); + return texture_contents->Render(renderer, entity, pass); +} + +} // namespace impeller diff --git a/impeller/entity/contents/color_source_text_contents.h b/impeller/entity/contents/color_source_text_contents.h new file mode 100644 index 0000000000000..e93738c8f3760 --- /dev/null +++ b/impeller/entity/contents/color_source_text_contents.h @@ -0,0 +1,48 @@ +// 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. + +#pragma once + +#include +#include +#include +#include + +#include "flutter/fml/macros.h" +#include "impeller/entity/contents/color_source_contents.h" +#include "impeller/entity/contents/contents.h" +#include "impeller/entity/contents/text_contents.h" + +namespace impeller { + +class ColorSourceTextContents final : public Contents { + public: + ColorSourceTextContents(); + + ~ColorSourceTextContents(); + + void SetTextContents(std::shared_ptr text_contents); + + void SetColorSourceContents( + std::shared_ptr color_source_contents); + + void SetTextPosition(Point position); + + // |Contents| + std::optional GetCoverage(const Entity& entity) const override; + + // |Contents| + bool Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + private: + Point position_; + std::shared_ptr text_contents_; + std::shared_ptr color_source_contents_; + + FML_DISALLOW_COPY_AND_ASSIGN(ColorSourceTextContents); +}; + +} // namespace impeller diff --git a/impeller/entity/contents/text_contents.cc b/impeller/entity/contents/text_contents.cc index 141ffaccea293..713dbbaf2033b 100644 --- a/impeller/entity/contents/text_contents.cc +++ b/impeller/entity/contents/text_contents.cc @@ -50,6 +50,10 @@ void TextContents::SetColor(Color color) { color_ = color; } +void TextContents::SetInverseMatrix(Matrix matrix) { + inverse_matrix_ = matrix; +} + std::optional TextContents::GetCoverage(const Entity& entity) const { auto bounds = frame_.GetBounds(); if (!bounds.has_value()) { @@ -71,6 +75,7 @@ static bool CommonRender( RenderPass& pass, const Color& color, const TextFrame& frame, + const Matrix& inverse_matrix, std::shared_ptr atlas, // NOLINT(performance-unnecessary-value-param) Command& cmd) { @@ -159,8 +164,10 @@ static bool CommonRender( auto uv_scaler_a = atlas_glyph_pos->size / atlas_size; auto uv_scaler_b = (Point::Round(atlas_glyph_pos->origin) / atlas_size); - auto translation = Matrix::MakeTranslation( - Vector3(offset_glyph_position.x, offset_glyph_position.y, 0)); + auto translation = + Matrix::MakeTranslation( + Vector3(offset_glyph_position.x, offset_glyph_position.y, 0)) * + inverse_matrix; for (const auto& point : unit_points) { typename VS::PerVertexData vtx; @@ -209,8 +216,8 @@ bool TextContents::RenderSdf(const ContentContext& renderer, cmd.pipeline = renderer.GetGlyphAtlasSdfPipeline(opts); cmd.stencil_reference = entity.GetStencilDepth(); - return CommonRender(renderer, entity, pass, color_, - frame_, atlas, cmd); + return CommonRender( + renderer, entity, pass, color_, frame_, inverse_matrix_, atlas, cmd); } bool TextContents::Render(const ContentContext& renderer, @@ -245,7 +252,7 @@ bool TextContents::Render(const ContentContext& renderer, cmd.stencil_reference = entity.GetStencilDepth(); return CommonRender(renderer, entity, pass, color_, - frame_, atlas, cmd); + frame_, inverse_matrix_, atlas, cmd); } } // namespace impeller diff --git a/impeller/entity/contents/text_contents.h b/impeller/entity/contents/text_contents.h index a0cec70a95103..0a6b5bf716e4b 100644 --- a/impeller/entity/contents/text_contents.h +++ b/impeller/entity/contents/text_contents.h @@ -32,6 +32,8 @@ class TextContents final : public Contents { void SetColor(Color color); + void SetInverseMatrix(Matrix matrix); + // |Contents| std::optional GetCoverage(const Entity& entity) const override; @@ -49,6 +51,7 @@ class TextContents final : public Contents { TextFrame frame_; Color color_; mutable std::shared_ptr lazy_atlas_; + Matrix inverse_matrix_; std::shared_ptr ResolveAtlas( GlyphAtlas::Type type, diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 927f8536a3f49..b5720d0c0cebd 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -1646,6 +1646,13 @@ TEST(GeometryTest, RectGetPoints) { ASSERT_POINT_NEAR(points[3], Point(400, 600)); } +TEST(GeometryTest, RectShift) { + auto r = Rect::MakeLTRB(0, 0, 100, 100); + + ASSERT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105)); + ASSERT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95)); +} + TEST(GeometryTest, RectGetTransformedPoints) { Rect r(100, 200, 300, 400); auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20})); diff --git a/impeller/geometry/rect.h b/impeller/geometry/rect.h index 4dd4107107144..afeb68620d9a2 100644 --- a/impeller/geometry/rect.h +++ b/impeller/geometry/rect.h @@ -238,6 +238,12 @@ struct TRect { return *this; } + + /// @brief Returns a new rectangle translated by the given offset. + constexpr TRect Shift(TPoint offset) const { + return TRect(origin.x + offset.x, origin.y + offset.y, size.width, + size.height); + } }; using Rect = TRect; From 650c6e3ad8c9f6597007684e87fd999a4ea39dda Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Mon, 13 Mar 2023 08:45:38 -0700 Subject: [PATCH 14/16] Revert "[Impeller] More sundry fixes to the Vulkan backend. (#40244)" (#40247) Revert "[Impeller] More sundry fixes to the Vulkan backend." --- ci/licenses_golden/licenses_flutter | 26 +- impeller/aiks/aiks_unittests.cc | 2 +- impeller/aiks/picture.cc | 2 +- impeller/compiler/code_gen_template.h | 12 +- impeller/entity/contents/content_context.cc | 14 +- impeller/entity/contents/content_context.h | 4 +- .../contents/runtime_effect_contents.cc | 7 +- impeller/entity/entity_pass.cc | 6 +- .../backend/metal/playground_impl_mtl.mm | 5 +- impeller/playground/playground.cc | 9 +- impeller/renderer/BUILD.gn | 5 +- .../renderer/backend/gles/context_gles.cc | 14 +- impeller/renderer/backend/gles/context_gles.h | 9 +- impeller/renderer/backend/metal/context_mtl.h | 37 +- .../renderer/backend/metal/context_mtl.mm | 98 ++-- .../renderer/backend/metal/surface_mtl.mm | 3 +- impeller/renderer/backend/vulkan/BUILD.gn | 8 - .../renderer/backend/vulkan/allocator_vk.cc | 67 ++- .../renderer/backend/vulkan/allocator_vk.h | 2 +- .../backend/vulkan/blit_command_vk.cc | 104 ++-- .../backend/vulkan/capabilities_vk.cc | 324 +----------- .../renderer/backend/vulkan/capabilities_vk.h | 68 +-- .../backend/vulkan/command_encoder_vk.cc | 179 ++----- .../backend/vulkan/command_encoder_vk.h | 31 +- .../backend/vulkan/command_pool_vk.cc | 135 ----- .../renderer/backend/vulkan/command_pool_vk.h | 55 -- .../renderer/backend/vulkan/context_vk.cc | 492 ++++++++++++------ impeller/renderer/backend/vulkan/context_vk.h | 55 +- .../backend/vulkan/debug_report_vk.cc | 189 ------- .../renderer/backend/vulkan/debug_report_vk.h | 44 -- .../backend/vulkan/descriptor_pool_vk.cc | 74 --- .../backend/vulkan/descriptor_pool_vk.h | 48 -- .../backend/vulkan/device_buffer_vk.cc | 2 +- .../backend/vulkan/device_buffer_vk.h | 2 +- .../backend/vulkan/fence_waiter_vk.cc | 108 ---- .../renderer/backend/vulkan/fence_waiter_vk.h | 53 -- impeller/renderer/backend/vulkan/formats_vk.h | 56 +- .../backend/vulkan/pipeline_library_vk.cc | 169 +++--- .../backend/vulkan/pipeline_library_vk.h | 5 +- .../renderer/backend/vulkan/pipeline_vk.cc | 49 +- .../renderer/backend/vulkan/pipeline_vk.h | 46 +- .../renderer/backend/vulkan/render_pass_vk.cc | 331 ++++++------ .../renderer/backend/vulkan/render_pass_vk.h | 3 +- .../backend/vulkan/sampler_library_vk.cc | 6 - .../renderer/backend/vulkan/sampler_vk.cc | 2 +- impeller/renderer/backend/vulkan/sampler_vk.h | 2 +- .../backend/vulkan/shared_object_vk.h | 9 +- .../renderer/backend/vulkan/surface_vk.cc | 8 +- .../backend/vulkan/swapchain_image_vk.cc | 25 +- .../backend/vulkan/swapchain_image_vk.h | 11 +- .../backend/vulkan/swapchain_impl_vk.cc | 61 +-- .../backend/vulkan/texture_source_vk.cc | 53 -- .../backend/vulkan/texture_source_vk.h | 26 +- .../renderer/backend/vulkan/texture_vk.cc | 145 +++--- impeller/renderer/backend/vulkan/texture_vk.h | 9 +- impeller/renderer/capabilities.cc | 159 ------ impeller/renderer/capabilities.h | 80 --- .../renderer/compute_subgroup_unittests.cc | 4 +- impeller/renderer/compute_unittests.cc | 4 +- impeller/renderer/context.cc | 4 +- impeller/renderer/context.h | 17 +- impeller/renderer/descriptor_set_layout.h | 27 + impeller/renderer/device_capabilities.cc | 141 +++++ impeller/renderer/device_capabilities.h | 99 ++++ impeller/renderer/formats.h | 4 - impeller/renderer/pipeline_builder.h | 4 +- impeller/renderer/render_target.cc | 10 +- impeller/renderer/sampler.h | 2 +- impeller/renderer/shader_types.h | 11 - impeller/renderer/testing/mocks.h | 5 +- impeller/renderer/vertex_descriptor.h | 1 + .../runtime_stage/runtime_stage_unittests.cc | 4 +- lib/ui/painting/image_decoder_impeller.cc | 2 +- .../darwin/ios/ios_surface_metal_impeller.mm | 75 ++- 74 files changed, 1423 insertions(+), 2539 deletions(-) delete mode 100644 impeller/renderer/backend/vulkan/command_pool_vk.cc delete mode 100644 impeller/renderer/backend/vulkan/command_pool_vk.h delete mode 100644 impeller/renderer/backend/vulkan/debug_report_vk.cc delete mode 100644 impeller/renderer/backend/vulkan/debug_report_vk.h delete mode 100644 impeller/renderer/backend/vulkan/descriptor_pool_vk.cc delete mode 100644 impeller/renderer/backend/vulkan/descriptor_pool_vk.h delete mode 100644 impeller/renderer/backend/vulkan/fence_waiter_vk.cc delete mode 100644 impeller/renderer/backend/vulkan/fence_waiter_vk.h delete mode 100644 impeller/renderer/capabilities.cc delete mode 100644 impeller/renderer/capabilities.h create mode 100644 impeller/renderer/descriptor_set_layout.h create mode 100644 impeller/renderer/device_capabilities.cc create mode 100644 impeller/renderer/device_capabilities.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 7c510864e4266..fdb72da12350e 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1411,18 +1411,10 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc + ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.cc + ../../../flutter/LICENSE @@ -1464,8 +1456,6 @@ ORIGIN: ../../../flutter/impeller/renderer/buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/buffer_view.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/buffer_view.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/capabilities.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/capabilities.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/command.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/command.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/command_buffer.cc + ../../../flutter/LICENSE @@ -1480,10 +1470,13 @@ ORIGIN: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.cc + ../. ORIGIN: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/context.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/descriptor_set_layout.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer_descriptor.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/device_buffer_descriptor.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/device_capabilities.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/device_capabilities.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/formats.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/formats.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/gpu_tracer.cc + ../../../flutter/LICENSE @@ -3947,18 +3940,10 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/debug_report_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/descriptor_pool_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/device_buffer_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/formats_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/pipeline_library_vk.cc @@ -4000,8 +3985,6 @@ FILE: ../../../flutter/impeller/renderer/buffer.cc FILE: ../../../flutter/impeller/renderer/buffer.h FILE: ../../../flutter/impeller/renderer/buffer_view.cc FILE: ../../../flutter/impeller/renderer/buffer_view.h -FILE: ../../../flutter/impeller/renderer/capabilities.cc -FILE: ../../../flutter/impeller/renderer/capabilities.h FILE: ../../../flutter/impeller/renderer/command.cc FILE: ../../../flutter/impeller/renderer/command.h FILE: ../../../flutter/impeller/renderer/command_buffer.cc @@ -4016,10 +3999,13 @@ FILE: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.cc FILE: ../../../flutter/impeller/renderer/compute_pipeline_descriptor.h FILE: ../../../flutter/impeller/renderer/context.cc FILE: ../../../flutter/impeller/renderer/context.h +FILE: ../../../flutter/impeller/renderer/descriptor_set_layout.h FILE: ../../../flutter/impeller/renderer/device_buffer.cc FILE: ../../../flutter/impeller/renderer/device_buffer.h FILE: ../../../flutter/impeller/renderer/device_buffer_descriptor.cc FILE: ../../../flutter/impeller/renderer/device_buffer_descriptor.h +FILE: ../../../flutter/impeller/renderer/device_capabilities.cc +FILE: ../../../flutter/impeller/renderer/device_capabilities.h FILE: ../../../flutter/impeller/renderer/formats.cc FILE: ../../../flutter/impeller/renderer/formats.h FILE: ../../../flutter/impeller/renderer/gpu_tracer.cc diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 04fdeb5b01e4e..634bf58f27642 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -108,7 +108,7 @@ bool GenerateMipmap(const std::shared_ptr& context, } pass->GenerateMipmap(std::move(texture), std::move(label)); pass->EncodeCommands(context->GetResourceAllocator()); - return buffer->SubmitCommands(); + return true; } TEST_P(AiksTest, CanRenderTiledTexture) { diff --git a/impeller/aiks/picture.cc b/impeller/aiks/picture.cc index 10500e6c09d89..97b48e357a321 100644 --- a/impeller/aiks/picture.cc +++ b/impeller/aiks/picture.cc @@ -54,7 +54,7 @@ std::shared_ptr Picture::RenderToTexture( // features to Image someday. auto impeller_context = context.GetContext(); RenderTarget target; - if (impeller_context->GetCapabilities()->SupportsOffscreenMSAA()) { + if (impeller_context->GetDeviceCapabilities().SupportsOffscreenMSAA()) { target = RenderTarget::CreateOffscreenMSAA(*impeller_context, size); } else { target = RenderTarget::CreateOffscreen(*impeller_context, size); diff --git a/impeller/compiler/code_gen_template.h b/impeller/compiler/code_gen_template.h index 2666a53f9ca96..d2708052d1838 100644 --- a/impeller/compiler/code_gen_template.h +++ b/impeller/compiler/code_gen_template.h @@ -22,6 +22,8 @@ constexpr std::string_view kReflectionHeaderTemplate = #include "impeller/renderer/compute_command.h" {# // nogncheck #} +#include "impeller/renderer/descriptor_set_layout.h" {# // nogncheck #} + #include "impeller/renderer/sampler.h" {# // nogncheck #} #include "impeller/renderer/shader_types.h" {# // nogncheck #} @@ -164,15 +166,17 @@ std::move({{ arg.argument_name }}){% if not loop.is_last %}, {% endif %} {% for buffer in buffers %} DescriptorSetLayout{ {{buffer.binding}}, // binding = {{buffer.binding}} - DescriptorType::kUniformBuffer, // descriptor_type = Uniform Buffer - {{to_shader_stage(shader_stage)}}, // shader_stage = {{to_shader_stage(shader_stage)}} + DescriptorType::kUniformBuffer, // descriptorType = Uniform Buffer + 1, // descriptorCount = 1 + {{to_shader_stage(shader_stage)}}, // stageFlags = {{to_shader_stage(shader_stage)}} }, {% endfor %} {% for sampled_image in sampled_images %} DescriptorSetLayout{ {{sampled_image.binding}}, // binding = {{sampled_image.binding}} - DescriptorType::kSampledImage, // descriptor_type = Sampled Image - {{to_shader_stage(shader_stage)}}, // shader_stage = {{to_shader_stage(shader_stage)}} + DescriptorType::kSampledImage, // descriptorType = Sampled Image + 1, // descriptorCount = 1 + {{to_shader_stage(shader_stage)}}, // stageFlags = {{to_shader_stage(shader_stage)}} }, {% endfor %} }; diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 54a9fb46250fc..36287aaf935f7 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -154,8 +154,7 @@ static std::unique_ptr CreateDefaultPipeline( return nullptr; } // Apply default ContentContextOptions to the descriptor. - const auto default_color_fmt = - context.GetCapabilities()->GetDefaultColorFormat(); + const auto default_color_fmt = context.GetColorAttachmentPixelFormat(); ContentContextOptions{.color_attachment_pixel_format = default_color_fmt} .ApplyToPipelineDescriptor(*desc); return std::make_unique(context, desc); @@ -176,7 +175,7 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); radial_gradient_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); - if (context_->GetCapabilities()->SupportsSSBO()) { + if (context_->GetDeviceCapabilities().SupportsSSBO()) { linear_gradient_ssbo_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); radial_gradient_ssbo_fill_pipelines_[{}] = @@ -184,7 +183,7 @@ ContentContext::ContentContext(std::shared_ptr context) sweep_gradient_ssbo_fill_pipelines_[{}] = CreateDefaultPipeline(*context_); } - if (context_->GetCapabilities()->SupportsFramebufferFetch()) { + if (context_->GetDeviceCapabilities().SupportsFramebufferFetch()) { framebuffer_blend_color_pipelines_[{}] = CreateDefaultPipeline(*context_); framebuffer_blend_colorburn_pipelines_[{}] = @@ -316,7 +315,8 @@ std::shared_ptr ContentContext::MakeSubpass( auto context = GetContext(); RenderTarget subpass_target; - if (context->GetCapabilities()->SupportsOffscreenMSAA() && msaa_enabled) { + if (context->GetDeviceCapabilities().SupportsOffscreenMSAA() && + msaa_enabled) { subpass_target = RenderTarget::CreateOffscreenMSAA( *context, texture_size, SPrintF("%s Offscreen", label.c_str()), RenderTarget::kDefaultColorAttachmentConfigMSAA, std::nullopt); @@ -374,8 +374,8 @@ std::shared_ptr ContentContext::GetContext() const { return context_; } -const Capabilities& ContentContext::GetDeviceCapabilities() const { - return *context_->GetCapabilities(); +const IDeviceCapabilities& ContentContext::GetDeviceCapabilities() const { + return context_->GetDeviceCapabilities(); } void ContentContext::SetWireframe(bool wireframe) { diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 3449236aae490..236167f3a9e58 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -47,7 +47,7 @@ #include "impeller/entity/vertices.frag.h" #include "impeller/entity/yuv_to_rgb_filter.frag.h" #include "impeller/entity/yuv_to_rgb_filter.vert.h" -#include "impeller/renderer/capabilities.h" +#include "impeller/renderer/device_capabilities.h" #include "impeller/renderer/formats.h" #include "impeller/renderer/pipeline.h" #include "impeller/scene/scene_context.h" @@ -601,7 +601,7 @@ class ContentContext { std::shared_ptr GetGlyphAtlasContext() const; - const Capabilities& GetDeviceCapabilities() const; + const IDeviceCapabilities& GetDeviceCapabilities() const; void SetWireframe(bool wireframe); diff --git a/impeller/entity/contents/runtime_effect_contents.cc b/impeller/entity/contents/runtime_effect_contents.cc index 9f7aaadbde09c..841027d84fc54 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -102,9 +102,10 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, /// Get or create runtime stage pipeline. /// - const auto& caps = context->GetCapabilities(); - const auto color_attachment_format = caps->GetDefaultColorFormat(); - const auto stencil_attachment_format = caps->GetDefaultStencilFormat(); + const auto& device_capabilities = context->GetDeviceCapabilities(); + const auto color_attachment_format = context->GetColorAttachmentPixelFormat(); + const auto stencil_attachment_format = + device_capabilities.GetDefaultStencilFormat(); using VS = RuntimeEffectVertexShader; PipelineDescriptor desc; diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 5e00c6b1c1ee0..487c56d063976 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -152,7 +152,7 @@ static RenderTarget CreateRenderTarget(ContentContext& renderer, /// What's important is the `StorageMode` of the textures, which cannot be /// changed for the lifetime of the textures. - if (context->GetCapabilities()->SupportsOffscreenMSAA()) { + if (context->GetDeviceCapabilities().SupportsOffscreenMSAA()) { return RenderTarget::CreateOffscreenMSAA( *context, // context size, // size @@ -210,8 +210,8 @@ bool EntityPass::Render(ContentContext& renderer, command_buffer->SetLabel("EntityPass Root Command Buffer"); if (renderer.GetContext() - ->GetCapabilities() - ->SupportsTextureToTextureBlits()) { + ->GetDeviceCapabilities() + .SupportsTextureToTextureBlits()) { auto blit_pass = command_buffer->CreateBlitPass(); blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(), diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index cf26700b41706..2418d1dae7c9a 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -82,8 +82,9 @@ } data_->metal_layer = [CAMetalLayer layer]; data_->metal_layer.device = ContextMTL::Cast(*context).GetMTLDevice(); - data_->metal_layer.pixelFormat = - ToMTLPixelFormat(context->GetCapabilities()->GetDefaultColorFormat()); + // This pixel format is one of the documented supported formats. + const auto color_fmt = context->GetColorAttachmentPixelFormat(); + data_->metal_layer.pixelFormat = ToMTLPixelFormat(color_fmt); data_->metal_layer.framebufferOnly = NO; cocoa_window.contentView.layer = data_->metal_layer; cocoa_window.contentView.wantsLayer = YES; diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index ecce6934d7ae4..85042638b8044 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -402,13 +402,8 @@ std::shared_ptr Playground::CreateTextureForFixture( std::shared_ptr Playground::CreateTextureForFixture( const char* fixture_name, bool enable_mipmapping) const { - auto texture = CreateTextureForFixture(OpenAssetAsMapping(fixture_name), - enable_mipmapping); - if (texture == nullptr) { - return nullptr; - } - texture->SetLabel(fixture_name); - return texture; + return CreateTextureForFixture(OpenAssetAsMapping(fixture_name), + enable_mipmapping); } std::shared_ptr Playground::CreateTextureCubeForFixture( diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn index f968e626ee074..792fc8ed85ff9 100644 --- a/impeller/renderer/BUILD.gn +++ b/impeller/renderer/BUILD.gn @@ -16,8 +16,6 @@ impeller_component("renderer") { "buffer.h", "buffer_view.cc", "buffer_view.h", - "capabilities.cc", - "capabilities.h", "command.cc", "command.h", "command_buffer.cc", @@ -32,10 +30,13 @@ impeller_component("renderer") { "compute_pipeline_descriptor.h", "context.cc", "context.h", + "descriptor_set_layout.h", "device_buffer.cc", "device_buffer.h", "device_buffer_descriptor.cc", "device_buffer_descriptor.h", + "device_capabilities.cc", + "device_capabilities.h", "formats.cc", "formats.h", "gpu_tracer.cc", diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index b523a0d598250..85e1bd3ee8f78 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -7,7 +7,7 @@ #include "impeller/base/config.h" #include "impeller/base/validation.h" #include "impeller/base/work_queue_common.h" -#include "impeller/renderer/capabilities.h" +#include "impeller/renderer/device_capabilities.h" namespace impeller { @@ -72,7 +72,7 @@ ContextGLES::ContextGLES(std::unique_ptr gl, // Create the device capabilities. { device_capabilities_ = - CapabilitiesBuilder() + DeviceCapabilitiesBuilder() .SetHasThreadingRestrictions(true) .SetSupportsOffscreenMSAA(false) .SetSupportsSSBO(false) @@ -145,9 +145,13 @@ std::shared_ptr ContextGLES::GetWorkQueue() const { } // |Context| -const std::shared_ptr& ContextGLES::GetCapabilities() - const { - return device_capabilities_; +const IDeviceCapabilities& ContextGLES::GetDeviceCapabilities() const { + return *device_capabilities_; +} + +// |Context| +PixelFormat ContextGLES::GetColorAttachmentPixelFormat() const { + return PixelFormat::kR8G8B8A8UNormInt; } } // namespace impeller diff --git a/impeller/renderer/backend/gles/context_gles.h b/impeller/renderer/backend/gles/context_gles.h index 030877262741d..39e1384d97512 100644 --- a/impeller/renderer/backend/gles/context_gles.h +++ b/impeller/renderer/backend/gles/context_gles.h @@ -12,8 +12,8 @@ #include "impeller/renderer/backend/gles/reactor_gles.h" #include "impeller/renderer/backend/gles/sampler_library_gles.h" #include "impeller/renderer/backend/gles/shader_library_gles.h" -#include "impeller/renderer/capabilities.h" #include "impeller/renderer/context.h" +#include "impeller/renderer/device_capabilities.h" namespace impeller { @@ -41,7 +41,7 @@ class ContextGLES final : public Context, std::shared_ptr sampler_library_; std::shared_ptr work_queue_; std::shared_ptr resource_allocator_; - std::shared_ptr device_capabilities_; + std::unique_ptr device_capabilities_; bool is_valid_ = false; ContextGLES( @@ -70,7 +70,10 @@ class ContextGLES final : public Context, std::shared_ptr GetWorkQueue() const override; // |Context| - const std::shared_ptr& GetCapabilities() const override; + const IDeviceCapabilities& GetDeviceCapabilities() const override; + + // |Context| + PixelFormat GetColorAttachmentPixelFormat() const override; FML_DISALLOW_COPY_AND_ASSIGN(ContextGLES); }; diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index 80b9bdc8f04ab..bd75e585d86c0 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -16,8 +16,8 @@ #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h" #include "impeller/renderer/backend/metal/pipeline_library_mtl.h" #include "impeller/renderer/backend/metal/shader_library_mtl.h" -#include "impeller/renderer/capabilities.h" #include "impeller/renderer/context.h" +#include "impeller/renderer/device_capabilities.h" #include "impeller/renderer/sampler.h" namespace impeller { @@ -37,6 +37,22 @@ class ContextMTL final : public Context, id GetMTLDevice() const; + private: + id device_ = nullptr; + id command_queue_ = nullptr; + std::shared_ptr shader_library_; + std::shared_ptr pipeline_library_; + std::shared_ptr sampler_library_; + std::shared_ptr resource_allocator_; + std::shared_ptr work_queue_; + std::shared_ptr gpu_tracer_; + std::unique_ptr device_capabilities_; + bool is_valid_ = false; + + ContextMTL(id device, NSArray>* shader_libraries); + + bool SupportsFramebufferFetch() const; + // |Context| bool IsValid() const override; @@ -62,24 +78,7 @@ class ContextMTL final : public Context, std::shared_ptr GetGPUTracer() const override; // |Context| - const std::shared_ptr& GetCapabilities() const override; - - // |Context| - bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override; - - private: - id device_ = nullptr; - id command_queue_ = nullptr; - std::shared_ptr shader_library_; - std::shared_ptr pipeline_library_; - std::shared_ptr sampler_library_; - std::shared_ptr resource_allocator_; - std::shared_ptr work_queue_; - std::shared_ptr gpu_tracer_; - std::shared_ptr device_capabilities_; - bool is_valid_ = false; - - ContextMTL(id device, NSArray>* shader_libraries); + const IDeviceCapabilities& GetDeviceCapabilities() const override; std::shared_ptr CreateCommandBufferInQueue( id queue) const; diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index ce114a9862b5f..70c76592aa5fa 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -11,56 +11,11 @@ #include "flutter/fml/paths.h" #include "impeller/base/platform/darwin/work_queue_darwin.h" #include "impeller/renderer/backend/metal/sampler_library_mtl.h" -#include "impeller/renderer/capabilities.h" +#include "impeller/renderer/device_capabilities.h" #include "impeller/renderer/sampler_descriptor.h" namespace impeller { -static bool DeviceSupportsFramebufferFetch(id device) { - // The iOS simulator lies about supporting framebuffer fetch. -#if FML_OS_IOS_SIMULATOR - return false; -#endif // FML_OS_IOS_SIMULATOR - - if (@available(macOS 10.15, iOS 13, tvOS 13, *)) { - return [device supportsFamily:MTLGPUFamilyApple2]; - } - // According to - // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf , Apple2 - // corresponds to iOS GPU family 2, which supports A8 devices. -#if FML_OS_IOS - return [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]; -#else - return false; -#endif // FML_OS_IOS -} - -static bool DeviceSupportsComputeSubgroups(id device) { - bool supports_subgroups = false; - // Refer to the "SIMD-scoped reduction operations" feature in the table - // below: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf - if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) { - supports_subgroups = [device supportsFamily:MTLGPUFamilyApple7] || - [device supportsFamily:MTLGPUFamilyMac2]; - } - return supports_subgroups; -} - -static std::unique_ptr InferMetalCapabilities( - id device, - PixelFormat color_format = PixelFormat::kB8G8R8A8UNormInt) { - return CapabilitiesBuilder() - .SetHasThreadingRestrictions(false) - .SetSupportsOffscreenMSAA(true) - .SetSupportsSSBO(true) - .SetSupportsTextureToTextureBlits(true) - .SetSupportsFramebufferFetch(DeviceSupportsFramebufferFetch(device)) - .SetDefaultColorFormat(color_format) - .SetDefaultStencilFormat(PixelFormat::kS8UInt) - .SetSupportsCompute(true, DeviceSupportsComputeSubgroups(device)) - .Build(); -} - ContextMTL::ContextMTL(id device, NSArray>* shader_libraries) : device_(device) { @@ -134,11 +89,50 @@ static bool DeviceSupportsComputeSubgroups(id device) { { gpu_tracer_ = std::shared_ptr(new GPUTracerMTL(device_)); } #endif - device_capabilities_ = InferMetalCapabilities(device_); + { + bool supports_subgroups = false; + // Refer to the "SIMD-scoped reduction operations" feature in the table + // below: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf + if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) { + supports_subgroups = [device supportsFamily:MTLGPUFamilyApple7] || + [device supportsFamily:MTLGPUFamilyMac2]; + } + + device_capabilities_ = + DeviceCapabilitiesBuilder() + .SetHasThreadingRestrictions(false) + .SetSupportsOffscreenMSAA(true) + .SetSupportsSSBO(true) + .SetSupportsTextureToTextureBlits(true) + .SetSupportsFramebufferFetch(SupportsFramebufferFetch()) + .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) + .SetDefaultStencilFormat(PixelFormat::kS8UInt) + .SetSupportsCompute(true, supports_subgroups) + .Build(); + } is_valid_ = true; } +bool ContextMTL::SupportsFramebufferFetch() const { + // The iOS simulator lies about supporting framebuffer fetch. +#if FML_OS_IOS_SIMULATOR + return false; +#endif // FML_OS_IOS_SIMULATOR + + if (@available(macOS 10.15, iOS 13, tvOS 13, *)) { + return [device_ supportsFamily:MTLGPUFamilyApple2]; + } + // According to + // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf , Apple2 + // corresponds to iOS GPU family 2, which supports A8 devices. +#if FML_OS_IOS + return [device_ supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]; +#else + return false; +#endif // FML_OS_IOS +} + static NSArray>* MTLShaderLibraryFromFilePaths( id device, const std::vector& libraries_paths) { @@ -293,14 +287,8 @@ static bool DeviceSupportsComputeSubgroups(id device) { return device_; } -const std::shared_ptr& ContextMTL::GetCapabilities() const { - return device_capabilities_; -} - -// |Context| -bool ContextMTL::UpdateOffscreenLayerPixelFormat(PixelFormat format) { - device_capabilities_ = InferMetalCapabilities(device_); - return true; +const IDeviceCapabilities& ContextMTL::GetDeviceCapabilities() const { + return *device_capabilities_; } } // namespace impeller diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index dccdac147f4e9..70eedfd7aee60 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -64,7 +64,6 @@ resolve_tex_desc.format = color_format; resolve_tex_desc.size = msaa_tex_desc.size; resolve_tex_desc.usage = static_cast(TextureUsage::kRenderTarget); - resolve_tex_desc.sample_count = SampleCount::kCount1; resolve_tex_desc.storage_mode = StorageMode::kDevicePrivate; std::shared_ptr resolve_tex = @@ -87,7 +86,7 @@ stencil_tex_desc.type = TextureType::kTexture2DMultisample; stencil_tex_desc.sample_count = SampleCount::kCount4; stencil_tex_desc.format = - context->GetCapabilities()->GetDefaultStencilFormat(); + context->GetDeviceCapabilities().GetDefaultStencilFormat(); stencil_tex_desc.size = msaa_tex_desc.size; stencil_tex_desc.usage = static_cast(TextureUsage::kRenderTarget); diff --git a/impeller/renderer/backend/vulkan/BUILD.gn b/impeller/renderer/backend/vulkan/BUILD.gn index a5de877f8afc9..2c30458c842b8 100644 --- a/impeller/renderer/backend/vulkan/BUILD.gn +++ b/impeller/renderer/backend/vulkan/BUILD.gn @@ -18,18 +18,10 @@ impeller_component("vulkan") { "command_buffer_vk.h", "command_encoder_vk.cc", "command_encoder_vk.h", - "command_pool_vk.cc", - "command_pool_vk.h", "context_vk.cc", "context_vk.h", - "debug_report_vk.cc", - "debug_report_vk.h", - "descriptor_pool_vk.cc", - "descriptor_pool_vk.h", "device_buffer_vk.cc", "device_buffer_vk.h", - "fence_waiter_vk.cc", - "fence_waiter_vk.h", "formats_vk.cc", "formats_vk.h", "pipeline_library_vk.cc", diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc index 25631dacb5ec9..f1c1e210e6ec9 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -152,12 +152,10 @@ static constexpr vk::ImageUsageFlags ToVKImageUsageFlags(PixelFormat format, } } - if (mode != StorageMode::kDeviceTransient) { - // TODO (https://github.com/flutter/flutter/issues/121634): - // Add transfer usage flags to support blit passes - vk_usage |= vk::ImageUsageFlagBits::eTransferSrc | - vk::ImageUsageFlagBits::eTransferDst; - } + // TODO (https://github.com/flutter/flutter/issues/121634): + // Add transfer usage flags to support blit passes + vk_usage |= vk::ImageUsageFlagBits::eTransferSrc | + vk::ImageUsageFlagBits::eTransferDst; return vk_usage; } @@ -213,10 +211,8 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { public: AllocatedTextureSourceVK(const TextureDescriptor& desc, VmaAllocator allocator, - vk::Device device) - : TextureSourceVK(desc) { + vk::Device device) { vk::ImageCreateInfo image_info; - image_info.flags = ToVKImageCreateFlags(desc.type); image_info.imageType = vk::ImageType::e2D; image_info.format = ToVKImageFormat(desc.format); image_info.extent = VkExtent3D{ @@ -233,11 +229,13 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { ToVKImageUsageFlags(desc.format, desc.usage, desc.storage_mode); image_info.sharingMode = vk::SharingMode::eExclusive; - VmaAllocationCreateInfo alloc_nfo = {}; + VmaAllocationCreateInfo alloc_create_info = {}; - alloc_nfo.usage = ToVMAMemoryUsage(); - alloc_nfo.preferredFlags = ToVKMemoryPropertyFlags(desc.storage_mode, true); - alloc_nfo.flags = ToVmaAllocationCreateFlags(desc.storage_mode, true); + alloc_create_info.usage = ToVMAMemoryUsage(); + alloc_create_info.preferredFlags = + ToVKMemoryPropertyFlags(desc.storage_mode, true); + alloc_create_info.flags = + ToVmaAllocationCreateFlags(desc.storage_mode, true); auto create_info_native = static_cast(image_info); @@ -246,13 +244,13 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { VmaAllocation allocation = {}; VmaAllocationInfo allocation_info = {}; { - auto result = vk::Result{::vmaCreateImage(allocator, // - &create_info_native, // - &alloc_nfo, // - &vk_image, // - &allocation, // - &allocation_info // - )}; + auto result = vk::Result{vmaCreateImage(allocator, // + &create_info_native, // + &alloc_create_info, // + &vk_image, // + &allocation, // + &allocation_info // + )}; if (result != vk::Result::eSuccess) { VALIDATION_LOG << "Unable to allocate Vulkan Image: " << vk::to_string(result); @@ -264,24 +262,25 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { allocator_ = allocator; allocation_ = allocation; - vk::ImageViewCreateInfo view_info = {}; - view_info.image = image_; - view_info.viewType = ToVKImageViewType(desc.type); - view_info.format = image_info.format; - view_info.subresourceRange.aspectMask = ToVKImageAspectFlags(desc.format); - view_info.subresourceRange.levelCount = image_info.mipLevels; - view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type); + vk::ImageViewCreateInfo view_create_info = {}; + view_create_info.image = image_; + view_create_info.viewType = vk::ImageViewType::e2D; + view_create_info.format = image_info.format; + view_create_info.subresourceRange.aspectMask = + ToVKImageAspectFlags(desc.format); + view_create_info.subresourceRange.levelCount = image_info.mipLevels; + view_create_info.subresourceRange.layerCount = 1u; // Vulkan does not have an image format that is equivalent to // `MTLPixelFormatA8Unorm`, so we use `R8Unorm` instead. Given that the // shaders expect that alpha channel to be set in the cases, we swizzle. // See: https://github.com/flutter/flutter/issues/115461 for more details. if (desc.format == PixelFormat::kA8UNormInt) { - view_info.components.a = vk::ComponentSwizzle::eR; - view_info.components.r = vk::ComponentSwizzle::eA; + view_create_info.components.a = vk::ComponentSwizzle::eR; + view_create_info.components.r = vk::ComponentSwizzle::eA; } - auto [result, image_view] = device.createImageViewUnique(view_info); + auto [result, image_view] = device.createImageViewUnique(view_create_info); if (result != vk::Result::eSuccess) { VALIDATION_LOG << "Unable to create an image view for allocation: " << vk::to_string(result); @@ -295,7 +294,7 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { ~AllocatedTextureSourceVK() { image_view_.reset(); if (image_) { - ::vmaDestroyImage( + vmaDestroyImage( allocator_, // static_cast(image_), // allocation_ // @@ -336,9 +335,9 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { bool IsValid() const { return is_valid_; } - vk::Image GetImage() const override { return image_; } + vk::Image GetVKImage() const override { return image_; } - vk::ImageView GetImageView() const override { return image_view_.get(); } + vk::ImageView GetVKImageView() const override { return image_view_.get(); } private: vk::Image image_ = {}; @@ -363,7 +362,7 @@ std::shared_ptr AllocatorVK::OnCreateTexture( if (!source->IsValid()) { return nullptr; } - return std::make_shared(context_, std::move(source)); + return std::make_shared(desc, context_, std::move(source)); } // |Allocator| diff --git a/impeller/renderer/backend/vulkan/allocator_vk.h b/impeller/renderer/backend/vulkan/allocator_vk.h index 0b4f3541bce98..f4a9e8ee3b297 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.h +++ b/impeller/renderer/backend/vulkan/allocator_vk.h @@ -28,7 +28,7 @@ class AllocatorVK final : public Allocator { VmaAllocator allocator_ = {}; std::weak_ptr context_; vk::Device device_; - ISize max_texture_size_; + ISize max_texture_size_ = {4096, 4096}; bool is_valid_ = false; AllocatorVK(std::weak_ptr context, diff --git a/impeller/renderer/backend/vulkan/blit_command_vk.cc b/impeller/renderer/backend/vulkan/blit_command_vk.cc index 98c8ab0d4ec85..8c27935cf84c8 100644 --- a/impeller/renderer/backend/vulkan/blit_command_vk.cc +++ b/impeller/renderer/backend/vulkan/blit_command_vk.cc @@ -29,27 +29,11 @@ bool BlitCopyTextureToTextureCommandVK::Encode( const auto& src = TextureVK::Cast(*source); const auto& dst = TextureVK::Cast(*destination); - LayoutTransition src_tran; - src_tran.cmd_buffer = cmd_buffer; - src_tran.new_layout = vk::ImageLayout::eTransferSrcOptimal; - src_tran.src_access = vk::AccessFlagBits::eTransferWrite | - vk::AccessFlagBits::eShaderWrite | - vk::AccessFlagBits::eColorAttachmentWrite; - src_tran.src_stage = vk::PipelineStageFlagBits::eTransfer | - vk::PipelineStageFlagBits::eFragmentShader | - vk::PipelineStageFlagBits::eColorAttachmentOutput; - src_tran.dst_access = vk::AccessFlagBits::eTransferRead; - src_tran.dst_stage = vk::PipelineStageFlagBits::eTransfer; - - LayoutTransition dst_tran; - dst_tran.cmd_buffer = cmd_buffer; - dst_tran.new_layout = vk::ImageLayout::eTransferDstOptimal; - dst_tran.src_access = {}; - dst_tran.src_stage = vk::PipelineStageFlagBits::eTopOfPipe; - dst_tran.dst_access = vk::AccessFlagBits::eShaderRead; - dst_tran.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; - - if (!src.SetLayout(src_tran) || !dst.SetLayout(dst_tran)) { + const auto src_layout = vk::ImageLayout::eTransferSrcOptimal; + const auto dst_layout = vk::ImageLayout::eTransferDstOptimal; + + if (!src.SetLayout(src_layout, cmd_buffer) || + !dst.SetLayout(dst_layout, cmd_buffer)) { VALIDATION_LOG << "Could not complete layout transitions."; return false; } @@ -70,11 +54,11 @@ bool BlitCopyTextureToTextureCommandVK::Encode( // Issue the copy command now that the images are already in the right // layouts. - cmd_buffer.copyImage(src.GetImage(), // - src_tran.new_layout, // - dst.GetImage(), // - dst_tran.new_layout, // - image_copy // + cmd_buffer.copyImage(src.GetImage(), // + src_layout, // + dst.GetImage(), // + dst_layout, // + image_copy // ); return true; @@ -95,20 +79,6 @@ bool BlitCopyTextureToBufferCommandVK::Encode(CommandEncoderVK& encoder) const { // cast source and destination to TextureVK const auto& src = TextureVK::Cast(*source); - - LayoutTransition transition; - transition.cmd_buffer = cmd_buffer; - transition.new_layout = vk::ImageLayout::eTransferSrcOptimal; - transition.src_access = vk::AccessFlagBits::eShaderWrite | - vk::AccessFlagBits::eTransferWrite | - vk::AccessFlagBits::eColorAttachmentWrite; - transition.src_stage = vk::PipelineStageFlagBits::eFragmentShader | - vk::PipelineStageFlagBits::eTransfer | - vk::PipelineStageFlagBits::eColorAttachmentOutput; - transition.dst_access = vk::AccessFlagBits::eShaderRead; - transition.dst_stage = vk::PipelineStageFlagBits::eVertexShader | - vk::PipelineStageFlagBits::eFragmentShader; - const auto& dst = DeviceBufferVK::Cast(*destination); vk::BufferImageCopy image_copy; @@ -122,15 +92,15 @@ bool BlitCopyTextureToBufferCommandVK::Encode(CommandEncoderVK& encoder) const { image_copy.setImageExtent( vk::Extent3D(source_region.size.width, source_region.size.height, 1)); - if (!src.SetLayout(transition)) { + if (!src.SetLayout(vk::ImageLayout::eTransferSrcOptimal, cmd_buffer)) { VALIDATION_LOG << "Could not encode layout transition."; return false; } - cmd_buffer.copyImageToBuffer(src.GetImage(), // - transition.new_layout, // - dst.GetBuffer(), // - image_copy // + cmd_buffer.copyImageToBuffer(src.GetImage(), // + vk::ImageLayout::eTransferSrcOptimal, // + dst.GetVKBufferHandle(), // + image_copy // ); return true; @@ -234,12 +204,10 @@ bool BlitGenerateMipmapCommandVK::Encode(CommandEncoderVK& encoder) const { // offsets[0] is origin. blit.srcOffsets[1].x = size.width; blit.srcOffsets[1].y = size.height; - blit.srcOffsets[1].z = 1u; // offsets[0] is origin. - blit.dstOffsets[1].x = std::max(size.width >> mip_level, 1u); - blit.dstOffsets[1].y = std::max(size.height >> mip_level, 1u); - blit.dstOffsets[1].z = 1u; + blit.dstOffsets[1].x = size.width >> mip_level; + blit.dstOffsets[1].y = size.height >> mip_level; cmd.blitImage(image, // src image vk::ImageLayout::eTransferSrcOptimal, // src layout @@ -254,27 +222,27 @@ bool BlitGenerateMipmapCommandVK::Encode(CommandEncoderVK& encoder) const { // Transition all mip levels to shader read. The base mip level has a // different "old" layout than the rest now. InsertImageMemoryBarrier( - cmd, // command buffer - image, // image - vk::AccessFlagBits::eTransferWrite, // src access mask - vk::AccessFlagBits::eShaderRead, // dst access mask - vk::ImageLayout::eTransferSrcOptimal, // old layout - vk::ImageLayout::eShaderReadOnlyOptimal, // new layout - vk::PipelineStageFlagBits::eTransfer, // src stage - vk::PipelineStageFlagBits::eFragmentShader, // dst stage - 0u // mip level + cmd, // command buffer + image, // image + vk::AccessFlagBits::eTransferRead, // src access mask + vk::AccessFlagBits::eShaderRead, // dst access mask + vk::ImageLayout::eTransferSrcOptimal, // old layout + vk::ImageLayout::eShaderReadOnlyOptimal, // new layout + vk::PipelineStageFlagBits::eTransfer, // src stage + vk::PipelineStageFlagBits::eAllGraphics, // dst stage + 0u // mip level ); InsertImageMemoryBarrier( - cmd, // command buffer - image, // image - vk::AccessFlagBits::eTransferWrite, // src access mask - vk::AccessFlagBits::eShaderRead, // dst access mask - vk::ImageLayout::eTransferDstOptimal, // old layout - vk::ImageLayout::eShaderReadOnlyOptimal, // new layout - vk::PipelineStageFlagBits::eTransfer, // src stage - vk::PipelineStageFlagBits::eFragmentShader, // dst stage - 1u, // mip level - mip_count - 1 // mip level count + cmd, // command buffer + image, // image + vk::AccessFlagBits::eTransferRead, // src access mask + vk::AccessFlagBits::eShaderRead, // dst access mask + vk::ImageLayout::eTransferDstOptimal, // old layout + vk::ImageLayout::eShaderReadOnlyOptimal, // new layout + vk::PipelineStageFlagBits::eTransfer, // src stage + vk::PipelineStageFlagBits::eAllGraphics, // dst stage + 1u, // mip level + mip_count - 1 // mip level count ); // We modified the layouts of this image from underneath it. Tell it its new diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc index 048dc3592c645..645ae1cf70375 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -4,337 +4,39 @@ #include "impeller/renderer/backend/vulkan/capabilities_vk.h" -#include - -#include "impeller/base/validation.h" #include "impeller/renderer/backend/vulkan/vk.h" namespace impeller { -static constexpr const char* kInstanceLayer = "ImpellerInstance"; - -CapabilitiesVK::CapabilitiesVK(bool enable_validations) - : enable_validations_(enable_validations) { - auto extensions = vk::enumerateInstanceExtensionProperties(); - auto layers = vk::enumerateInstanceLayerProperties(); - - if (extensions.result != vk::Result::eSuccess || - layers.result != vk::Result::eSuccess) { - return; +CapabilitiesVK::CapabilitiesVK() { + for (const auto& ext : vk::enumerateInstanceExtensionProperties().value) { + extensions_.insert(ext.extensionName); } - for (const auto& ext : extensions.value) { - exts_[kInstanceLayer].insert(ext.extensionName); - } - - for (const auto& layer : layers.value) { - const std::string layer_name = layer.layerName; - auto layer_exts = vk::enumerateInstanceExtensionProperties(layer_name); - if (layer_exts.result != vk::Result::eSuccess) { - return; - } - for (const auto& layer_ext : layer_exts.value) { - exts_[layer_name].insert(layer_ext.extensionName); - } + for (const auto& layer : vk::enumerateInstanceLayerProperties().value) { + layers_.insert(layer.layerName); } - - is_valid_ = true; } CapabilitiesVK::~CapabilitiesVK() = default; -bool CapabilitiesVK::IsValid() const { - return is_valid_; -} - -bool CapabilitiesVK::AreValidationsEnabled() const { - return enable_validations_; -} - -std::optional> CapabilitiesVK::GetRequiredLayers() - const { - std::vector required; - - if (enable_validations_) { - if (!HasLayer("VK_LAYER_KHRONOS_validation")) { - VALIDATION_LOG - << "Requested validations but the validation layer was not found."; - return std::nullopt; - } - required.push_back("VK_LAYER_KHRONOS_validation"); - } - - return required; -} - -std::optional> -CapabilitiesVK::GetRequiredInstanceExtensions() const { - std::vector required; - - if (!HasExtension("VK_KHR_surface")) { - // Swapchain support is required and this is a dependency of - // VK_KHR_swapchain. - VALIDATION_LOG << "Could not find the surface extension."; - return std::nullopt; - } - required.push_back("VK_KHR_surface"); - - auto has_wsi = false; - if (HasExtension("VK_MVK_macos_surface")) { - required.push_back("VK_MVK_macos_surface"); - has_wsi = true; - } - - if (HasExtension("VK_EXT_metal_surface")) { - required.push_back("VK_EXT_metal_surface"); - has_wsi = true; - } - - if (HasExtension("VK_KHR_portability_enumeration")) { - required.push_back("VK_KHR_portability_enumeration"); - has_wsi = true; - } - - if (HasExtension("VK_KHR_win32_surface")) { - required.push_back("VK_KHR_win32_surface"); - has_wsi = true; - } - - if (HasExtension("VK_KHR_android_surface")) { - required.push_back("VK_KHR_android_surface"); - has_wsi = true; - } - - if (HasExtension("VK_KHR_xcb_surface")) { - required.push_back("VK_KHR_xcb_surface"); - has_wsi = true; - } - - if (HasExtension("VK_KHR_xlib_surface")) { - required.push_back("VK_KHR_xlib_surface"); - has_wsi = true; - } - - if (HasExtension("VK_KHR_wayland_surface")) { - required.push_back("VK_KHR_wayland_surface"); - has_wsi = true; - } - - if (!has_wsi) { - // Don't really care which WSI extension there is as long there is at least - // one. - VALIDATION_LOG << "Could not find a WSI extension."; - return std::nullopt; - } - - if (enable_validations_) { - if (!HasExtension("VK_EXT_debug_utils")) { - VALIDATION_LOG << "Requested validations but could not find the " - "VK_EXT_debug_utils extension."; - return std::nullopt; - } - required.push_back("VK_EXT_debug_utils"); - - if (!HasExtension("VK_EXT_validation_features")) { - VALIDATION_LOG << "Requested validations but could not find the " - "VK_EXT_validation_features extension."; - return std::nullopt; - } - required.push_back("VK_EXT_validation_features"); - } - - return required; -} - -std::optional> -CapabilitiesVK::GetRequiredDeviceExtensions( - const vk::PhysicalDevice& physical_device) const { - auto device_extensions = physical_device.enumerateDeviceExtensionProperties(); - if (device_extensions.result != vk::Result::eSuccess) { - return std::nullopt; - } - - std::set exts; - for (const auto& device_extension : device_extensions.value) { - exts.insert(device_extension.extensionName); - } - - std::vector required; - - if (exts.find("VK_KHR_swapchain") == exts.end()) { - VALIDATION_LOG << "Device does not support the swapchain extension."; - return std::nullopt; - } - required.push_back("VK_KHR_swapchain"); - - // Required for non-conformant implementations like MoltenVK. - if (exts.find("VK_KHR_portability_subset") != exts.end()) { - required.push_back("VK_KHR_portability_subset"); - } - return required; -} - -static bool HasSuitableColorFormat(const vk::PhysicalDevice& device, - vk::Format format) { - const auto props = device.getFormatProperties(format); - // This needs to be more comprehensive. - return !!(props.optimalTilingFeatures & - vk::FormatFeatureFlagBits::eColorAttachment); -} - -static bool HasSuitableDepthStencilFormat(const vk::PhysicalDevice& device, - vk::Format format) { - const auto props = device.getFormatProperties(format); - return !!(props.optimalTilingFeatures & - vk::FormatFeatureFlagBits::eDepthStencilAttachment); -} - -static bool PhysicalDeviceSupportsRequiredFormats( - const vk::PhysicalDevice& device) { - const auto has_color_format = - HasSuitableColorFormat(device, vk::Format::eB8G8R8A8Unorm); - const auto has_depth_stencil_format = - HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint) || - HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint); - return has_color_format && has_depth_stencil_format; -} - -static bool HasRequiredProperties(const vk::PhysicalDevice& physical_device) { - auto properties = physical_device.getProperties(); - if (!(properties.limits.framebufferColorSampleCounts & - (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) { - return false; - } - return true; -} - -static bool HasRequiredQueues(const vk::PhysicalDevice& physical_device) { - auto queue_flags = vk::QueueFlags{}; - for (const auto& queue : physical_device.getQueueFamilyProperties()) { - if (queue.queueCount == 0) { - continue; - } - queue_flags |= queue.queueFlags; - } - return static_cast(queue_flags & - (vk::QueueFlagBits::eGraphics | - vk::QueueFlagBits::eCompute | - vk::QueueFlagBits::eTransfer)); -} - -std::optional -CapabilitiesVK::GetRequiredDeviceFeatures( - const vk::PhysicalDevice& device) const { - if (!PhysicalDeviceSupportsRequiredFormats(device)) { - VALIDATION_LOG << "Device doesn't support the required formats."; - return std::nullopt; - } - - if (!HasRequiredProperties(device)) { - VALIDATION_LOG << "Device doesn't support the required properties."; - return std::nullopt; - } - - if (!HasRequiredQueues(device)) { - VALIDATION_LOG << "Device doesn't support the required queues."; - return std::nullopt; - } - - if (!GetRequiredDeviceExtensions(device).has_value()) { - VALIDATION_LOG << "Device doesn't support the required queues."; - return std::nullopt; - } - - const auto device_features = device.getFeatures(); - - vk::PhysicalDeviceFeatures required; - - // We require this for enabling wireframes in the playground. But its not - // necessarily a big deal if we don't have this feature. - required.fillModeNonSolid = device_features.fillModeNonSolid; - - return required; +bool CapabilitiesVK::HasExtension(const std::string& extension) const { + return extensions_.count(extension) == 1u; } bool CapabilitiesVK::HasLayer(const std::string& layer) const { - for (const auto& [found_layer, exts] : exts_) { - if (found_layer == layer) { - return true; - } - } - return false; + return layers_.count(layer) == 1u; } -bool CapabilitiesVK::HasExtension(const std::string& ext) const { - for (const auto& [layer, exts] : exts_) { - if (exts.find(ext) != exts.end()) { +bool CapabilitiesVK::HasLayerExtension(const std::string& layer, + const std::string& extension) { + for (const auto& ext : + vk::enumerateInstanceExtensionProperties(layer).value) { + if (std::string{ext.extensionName} == extension) { return true; } } return false; } -bool CapabilitiesVK::SetDevice(const vk::PhysicalDevice& device) { - if (HasSuitableColorFormat(device, vk::Format::eB8G8R8A8Unorm)) { - color_format_ = PixelFormat::kB8G8R8A8UNormInt; - } else { - return false; - } - - if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) { - depth_stencil_format_ = PixelFormat::kS8UInt; - } else if (HasSuitableDepthStencilFormat(device, - vk::Format::eD24UnormS8Uint)) { - depth_stencil_format_ = PixelFormat::kD32FloatS8UInt; - } else { - return false; - } - return true; -} - -// |Capabilities| -bool CapabilitiesVK::HasThreadingRestrictions() const { - return false; -} - -// |Capabilities| -bool CapabilitiesVK::SupportsOffscreenMSAA() const { - return true; -} - -// |Capabilities| -bool CapabilitiesVK::SupportsSSBO() const { - return false; -} - -// |Capabilities| -bool CapabilitiesVK::SupportsTextureToTextureBlits() const { - return true; -} - -// |Capabilities| -bool CapabilitiesVK::SupportsFramebufferFetch() const { - return false; -} - -// |Capabilities| -bool CapabilitiesVK::SupportsCompute() const { - return false; -} - -// |Capabilities| -bool CapabilitiesVK::SupportsComputeSubgroups() const { - return false; -} - -// |Capabilities| -PixelFormat CapabilitiesVK::GetDefaultColorFormat() const { - return color_format_; -} - -// |Capabilities| -PixelFormat CapabilitiesVK::GetDefaultStencilFormat() const { - return depth_stencil_format_; -} - } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.h b/impeller/renderer/backend/vulkan/capabilities_vk.h index 21545e4384bc7..2b62e05e498ca 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.h +++ b/impeller/renderer/backend/vulkan/capabilities_vk.h @@ -4,81 +4,29 @@ #pragma once -#include #include #include -#include #include "flutter/fml/macros.h" -#include "impeller/renderer/backend/vulkan/vk.h" -#include "impeller/renderer/capabilities.h" namespace impeller { -class ContextVK; - -//------------------------------------------------------------------------------ -/// @brief The Vulkan layers and extensions wrangler. -/// -class CapabilitiesVK final : public Capabilities { +class CapabilitiesVK { public: - CapabilitiesVK(bool enable_validations = false); + CapabilitiesVK(); ~CapabilitiesVK(); - bool IsValid() const; - - bool AreValidationsEnabled() const; - - std::optional> GetRequiredLayers() const; - - std::optional> GetRequiredInstanceExtensions() const; - - std::optional> GetRequiredDeviceExtensions( - const vk::PhysicalDevice& physical_device) const; - - std::optional GetRequiredDeviceFeatures( - const vk::PhysicalDevice& physical_device) const; - - [[nodiscard]] bool SetDevice(const vk::PhysicalDevice& physical_device); - - // |Capabilities| - bool HasThreadingRestrictions() const override; - - // |Capabilities| - bool SupportsOffscreenMSAA() const override; + bool HasExtension(const std::string& extension) const; - // |Capabilities| - bool SupportsSSBO() const override; - - // |Capabilities| - bool SupportsTextureToTextureBlits() const override; - - // |Capabilities| - bool SupportsFramebufferFetch() const override; - - // |Capabilities| - bool SupportsCompute() const override; - - // |Capabilities| - bool SupportsComputeSubgroups() const override; - - // |Capabilities| - PixelFormat GetDefaultColorFormat() const override; + bool HasLayer(const std::string& layer) const; - // |Capabilities| - PixelFormat GetDefaultStencilFormat() const override; + bool HasLayerExtension(const std::string& layer, + const std::string& extension); private: - const bool enable_validations_; - std::map> exts_; - PixelFormat color_format_ = PixelFormat::kUnknown; - PixelFormat depth_stencil_format_ = PixelFormat::kUnknown; - bool is_valid_ = false; - - bool HasExtension(const std::string& ext) const; - - bool HasLayer(const std::string& layer) const; + std::set extensions_; + std::set layers_; FML_DISALLOW_COPY_AND_ASSIGN(CapabilitiesVK); }; diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.cc b/impeller/renderer/backend/vulkan/command_encoder_vk.cc index a65d61249aedd..6fbf12950f49b 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.cc +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.cc @@ -5,91 +5,31 @@ #include "impeller/renderer/backend/vulkan/command_encoder_vk.h" #include "flutter/fml/closure.h" -#include "flutter/fml/trace_event.h" #include "impeller/renderer/backend/vulkan/context_vk.h" -#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h" -#include "impeller/renderer/backend/vulkan/texture_vk.h" namespace impeller { -class TrackedObjectsVK { - public: - explicit TrackedObjectsVK(const vk::Device& device, - const std::shared_ptr& pool) - : desc_pool_(device) { - if (!pool) { - return; - } - auto buffer = pool->CreateGraphicsCommandBuffer(); - if (!buffer) { - return; - } - pool_ = pool; - buffer_ = std::move(buffer); - is_valid_ = true; - } - - ~TrackedObjectsVK() { - if (!buffer_) { - return; - } - auto pool = pool_.lock(); - if (!pool) { - VALIDATION_LOG - << "Command pool died before a command buffer could be recycled."; - return; - } - pool->CollectGraphicsCommandBuffer(std::move(buffer_)); - } - - bool IsValid() const { return is_valid_; } - - void Track(std::shared_ptr object) { - tracked_objects_.insert(std::move(object)); - } - - void Track(std::shared_ptr buffer) { - tracked_buffers_.insert(std::move(buffer)); - } - - void Track(std::shared_ptr texture) { - tracked_textures_.insert(std::move(texture)); - } - - vk::CommandBuffer GetCommandBuffer() const { return *buffer_; } - - DescriptorPoolVK& GetDescriptorPool() { return desc_pool_; } - - private: - DescriptorPoolVK desc_pool_; - std::weak_ptr pool_; - vk::UniqueCommandBuffer buffer_; - std::set> tracked_objects_; - std::set> tracked_buffers_; - std::set> tracked_textures_; - bool is_valid_ = false; - - FML_DISALLOW_COPY_AND_ASSIGN(TrackedObjectsVK); -}; - CommandEncoderVK::CommandEncoderVK(vk::Device device, vk::Queue queue, - const std::shared_ptr& pool, - std::shared_ptr fence_waiter) - : fence_waiter_(std::move(fence_waiter)), - tracked_objects_(std::make_shared(device, pool)) { - if (!fence_waiter_ || !tracked_objects_->IsValid()) { + vk::CommandPool pool) { + vk::CommandBufferAllocateInfo alloc_info; + alloc_info.commandPool = pool; + alloc_info.commandBufferCount = 1u; + alloc_info.level = vk::CommandBufferLevel::ePrimary; + auto [result, buffers] = device.allocateCommandBuffersUnique(alloc_info); + if (result != vk::Result::eSuccess) { + VALIDATION_LOG << "Could not create command buffer."; return; } vk::CommandBufferBeginInfo begin_info; begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; - if (tracked_objects_->GetCommandBuffer().begin(begin_info) != - vk::Result::eSuccess) { + if (buffers[0]->begin(begin_info) != vk::Result::eSuccess) { VALIDATION_LOG << "Could not begin command buffer."; return; } device_ = device; queue_ = queue; + command_buffer_ = std::move(buffers[0]); is_valid_ = true; } @@ -107,40 +47,39 @@ bool CommandEncoderVK::Submit() { // Success or failure, you only get to submit once. fml::ScopedCleanupClosure reset([&]() { Reset(); }); - InsertDebugMarker("QueueSubmit"); - - auto command_buffer = GetCommandBuffer(); - - if (command_buffer.end() != vk::Result::eSuccess) { + if (command_buffer_->end() != vk::Result::eSuccess) { return false; } auto [fence_result, fence] = device_.createFenceUnique({}); if (fence_result != vk::Result::eSuccess) { return false; } - vk::SubmitInfo submit_info; - std::vector buffers = {command_buffer}; - submit_info.setCommandBuffers(buffers); + submit_info.setCommandBuffers(*command_buffer_); if (queue_.submit(submit_info, *fence) != vk::Result::eSuccess) { return false; } + if (device_.waitForFences( + *fence, // fences + true, // wait all + std::numeric_limits::max() // timeout (ns) + ) != vk::Result::eSuccess) { + return false; + } - return fence_waiter_->AddFence( - std::move(fence), [tracked_objects = std::move(tracked_objects_)] { - // Nothing to do, we just drop the tracked objects on the floor. - }); + return true; } -vk::CommandBuffer CommandEncoderVK::GetCommandBuffer() const { - if (tracked_objects_) { - return tracked_objects_->GetCommandBuffer(); - } - return {}; +const vk::CommandBuffer& CommandEncoderVK::GetCommandBuffer() const { + return *command_buffer_; } void CommandEncoderVK::Reset() { - tracked_objects_.reset(); + command_buffer_.reset(); + + tracked_objects_.clear(); + tracked_buffers_.clear(); + tracked_textures_.clear(); queue_ = nullptr; device_ = nullptr; @@ -148,82 +87,34 @@ void CommandEncoderVK::Reset() { } bool CommandEncoderVK::Track(std::shared_ptr object) { - if (!IsValid()) { - return false; - } - tracked_objects_->Track(std::move(object)); + tracked_objects_.push_back(std::move(object)); return true; } bool CommandEncoderVK::Track(std::shared_ptr buffer) { - if (!IsValid()) { - return false; - } - tracked_objects_->Track(std::move(buffer)); + tracked_buffers_.emplace_back(std::move(buffer)); return true; } -bool CommandEncoderVK::Track(std::shared_ptr texture) { - if (!IsValid()) { - return false; - } - tracked_objects_->Track(std::move(texture)); +bool CommandEncoderVK::Track(std::shared_ptr texture) { + tracked_textures_.emplace_back(std::move(texture)); return true; } -bool CommandEncoderVK::Track(const std::shared_ptr& texture) { - if (!texture) { - return false; - } - return Track(TextureVK::Cast(*texture).GetTextureSource()); -} - -std::optional CommandEncoderVK::AllocateDescriptorSet( - const vk::DescriptorSetLayout& layout) { - if (!IsValid()) { - return std::nullopt; - } - return tracked_objects_->GetDescriptorPool().AllocateDescriptorSet(layout); -} - void CommandEncoderVK::PushDebugGroup(const char* label) const { - if (!HasValidationLayers()) { + if (!vk::HasValidationLayers() || !command_buffer_) { return; } vk::DebugUtilsLabelEXT label_info; label_info.pLabelName = label; - if (auto command_buffer = GetCommandBuffer()) { - command_buffer.beginDebugUtilsLabelEXT(label_info); - } - if (queue_) { - queue_.beginDebugUtilsLabelEXT(label_info); - } + command_buffer_->beginDebugUtilsLabelEXT(label_info); } void CommandEncoderVK::PopDebugGroup() const { - if (!HasValidationLayers()) { + if (!vk::HasValidationLayers() || !command_buffer_) { return; } - if (auto command_buffer = GetCommandBuffer()) { - command_buffer.endDebugUtilsLabelEXT(); - } - if (queue_) { - queue_.endDebugUtilsLabelEXT(); - } -} - -void CommandEncoderVK::InsertDebugMarker(const char* label) const { - if (!HasValidationLayers()) { - return; - } - vk::DebugUtilsLabelEXT label_info; - label_info.pLabelName = label; - if (auto command_buffer = GetCommandBuffer()) { - command_buffer.insertDebugUtilsLabelEXT(label_info); - } - if (queue_) { - queue_.insertDebugUtilsLabelEXT(label_info); - } + command_buffer_->endDebugUtilsLabelEXT(); } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.h b/impeller/renderer/backend/vulkan/command_encoder_vk.h index 8db33b50c1a7d..66ac47f39bf68 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.h +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.h @@ -4,12 +4,9 @@ #pragma once -#include -#include +#include #include "flutter/fml/macros.h" -#include "impeller/renderer/backend/vulkan/command_pool_vk.h" -#include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h" #include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" @@ -18,9 +15,6 @@ namespace impeller { class ContextVK; class DeviceBuffer; class Texture; -class TextureSourceVK; -class TrackedObjectsVK; -class FenceWaiterVK; class CommandEncoderVK { public: @@ -34,35 +28,26 @@ class CommandEncoderVK { bool Track(std::shared_ptr buffer); - bool Track(const std::shared_ptr& texture); + bool Track(std::shared_ptr texture); - bool Track(std::shared_ptr texture); - - vk::CommandBuffer GetCommandBuffer() const; + const vk::CommandBuffer& GetCommandBuffer() const; void PushDebugGroup(const char* label) const; void PopDebugGroup() const; - void InsertDebugMarker(const char* label) const; - - std::optional AllocateDescriptorSet( - const vk::DescriptorSetLayout& layout); - private: friend class ContextVK; vk::Device device_ = {}; vk::Queue queue_ = {}; - - std::shared_ptr fence_waiter_; - std::shared_ptr tracked_objects_; + vk::UniqueCommandBuffer command_buffer_; + std::vector> tracked_objects_; + std::vector> tracked_buffers_; + std::vector> tracked_textures_; bool is_valid_ = false; - CommandEncoderVK(vk::Device device, - vk::Queue queue, - const std::shared_ptr& pool, - std::shared_ptr fence_waiter); + CommandEncoderVK(vk::Device device, vk::Queue queue, vk::CommandPool pool); void Reset(); diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.cc b/impeller/renderer/backend/vulkan/command_pool_vk.cc deleted file mode 100644 index 5ed2ed404807c..0000000000000 --- a/impeller/renderer/backend/vulkan/command_pool_vk.cc +++ /dev/null @@ -1,135 +0,0 @@ -// 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 "impeller/renderer/backend/vulkan/command_pool_vk.h" - -#include -#include -#include - -#include "flutter/fml/thread_local.h" -#include "impeller/base/thread.h" -#include "impeller/renderer/backend/vulkan/context_vk.h" - -namespace impeller { - -using CommandPoolMap = - std::map>; - -FML_THREAD_LOCAL fml::ThreadLocalUniquePtr tls_command_pool; - -static Mutex g_all_pools_mutex; -static std::unordered_map>> - g_all_pools IPLR_GUARDED_BY(g_all_pools_mutex); - -std::shared_ptr CommandPoolVK::GetThreadLocal( - const ContextVK* context) { - if (!context) { - return nullptr; - } - if (tls_command_pool.get() == nullptr) { - tls_command_pool.reset(new CommandPoolMap()); - } - CommandPoolMap& pool_map = *tls_command_pool.get(); - auto found = pool_map.find(context); - if (found != pool_map.end() && found->second->IsValid()) { - return found->second; - } - auto pool = std::shared_ptr(new CommandPoolVK(context)); - if (!pool->IsValid()) { - return nullptr; - } - pool_map[context] = pool; - { - Lock pool_lock(g_all_pools_mutex); - g_all_pools[context].push_back(pool); - } - return pool; -} - -void CommandPoolVK::ClearAllPools(const ContextVK* context) { - Lock pool_lock(g_all_pools_mutex); - if (auto found = g_all_pools.find(context); found != g_all_pools.end()) { - for (auto& weak_pool : found->second) { - auto pool = weak_pool.lock(); - if (!pool) { - // The pool has already died because the thread died. - continue; - } - // The pool is reset but its reference in the TLS map remains till the - // thread dies. - pool->Reset(); - } - g_all_pools.erase(found); - } -} - -CommandPoolVK::CommandPoolVK(const ContextVK* context) - : owner_id_(std::this_thread::get_id()) { - vk::CommandPoolCreateInfo pool_info; - - pool_info.queueFamilyIndex = context->GetGraphicsQueueInfo().index; - pool_info.flags = vk::CommandPoolCreateFlagBits::eTransient; - auto pool = context->GetDevice().createCommandPoolUnique(pool_info); - if (pool.result != vk::Result::eSuccess) { - return; - } - - device_ = context->GetDevice(); - graphics_pool_ = std::move(pool.value); - is_valid_ = true; -} - -CommandPoolVK::~CommandPoolVK() = default; - -bool CommandPoolVK::IsValid() const { - return is_valid_; -} - -void CommandPoolVK::Reset() { - Lock lock(buffers_to_collect_mutex_); - GarbageCollectBuffersIfAble(); - graphics_pool_.reset(); - is_valid_ = false; -} - -vk::CommandPool CommandPoolVK::GetGraphicsCommandPool() const { - return graphics_pool_.get(); -} - -vk::UniqueCommandBuffer CommandPoolVK::CreateGraphicsCommandBuffer() { - if (std::this_thread::get_id() != owner_id_) { - return {}; - } - { - Lock lock(buffers_to_collect_mutex_); - GarbageCollectBuffersIfAble(); - } - vk::CommandBufferAllocateInfo alloc_info; - alloc_info.commandPool = graphics_pool_.get(); - alloc_info.commandBufferCount = 1u; - alloc_info.level = vk::CommandBufferLevel::ePrimary; - auto [result, buffers] = device_.allocateCommandBuffersUnique(alloc_info); - if (result != vk::Result::eSuccess) { - return {}; - } - return std::move(buffers[0]); -} - -void CommandPoolVK::CollectGraphicsCommandBuffer( - vk::UniqueCommandBuffer buffer) { - Lock lock(buffers_to_collect_mutex_); - buffers_to_collect_.insert(MakeSharedVK(std::move(buffer))); - GarbageCollectBuffersIfAble(); -} - -void CommandPoolVK::GarbageCollectBuffersIfAble() { - if (std::this_thread::get_id() != owner_id_) { - return; - } - buffers_to_collect_.clear(); -} - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.h b/impeller/renderer/backend/vulkan/command_pool_vk.h deleted file mode 100644 index 7399e22686075..0000000000000 --- a/impeller/renderer/backend/vulkan/command_pool_vk.h +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -#pragma once - -#include -#include -#include - -#include "flutter/fml/macros.h" -#include "impeller/base/thread.h" -#include "impeller/renderer/backend/vulkan/shared_object_vk.h" -#include "impeller/renderer/backend/vulkan/vk.h" - -namespace impeller { - -class ContextVK; - -class CommandPoolVK { - public: - static std::shared_ptr GetThreadLocal( - const ContextVK* context); - - static void ClearAllPools(const ContextVK* context); - - ~CommandPoolVK(); - - bool IsValid() const; - - void Reset(); - - vk::CommandPool GetGraphicsCommandPool() const; - - vk::UniqueCommandBuffer CreateGraphicsCommandBuffer(); - - void CollectGraphicsCommandBuffer(vk::UniqueCommandBuffer buffer); - - private: - const std::thread::id owner_id_; - vk::Device device_ = {}; - vk::UniqueCommandPool graphics_pool_; - Mutex buffers_to_collect_mutex_; - std::set> buffers_to_collect_ - IPLR_GUARDED_BY(buffers_to_collect_mutex_); - bool is_valid_ = false; - - explicit CommandPoolVK(const ContextVK* context); - - void GarbageCollectBuffersIfAble() IPLR_REQUIRES(buffers_to_collect_mutex_); - - FML_DISALLOW_COPY_AND_ASSIGN(CommandPoolVK); -}; - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index c394f3627b353..a7974915d1f81 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -20,30 +20,156 @@ #include "impeller/renderer/backend/vulkan/capabilities_vk.h" #include "impeller/renderer/backend/vulkan/command_buffer_vk.h" #include "impeller/renderer/backend/vulkan/command_encoder_vk.h" -#include "impeller/renderer/backend/vulkan/command_pool_vk.h" -#include "impeller/renderer/backend/vulkan/debug_report_vk.h" -#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/surface_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" -#include "impeller/renderer/capabilities.h" +#include "impeller/renderer/device_capabilities.h" VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE +namespace { + +// TODO(csg): Mimic vulkan_debug_report.cc for prettier reports. +VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsMessengerCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT type, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData) { + // There isn't stable messageIdNumber for this validation failure. + if (strstr(pCallbackData->pMessageIdName, + "CoreValidation-Shader-OutputNotConsumed") != nullptr) { + return VK_FALSE; + } + + if (pCallbackData->messageIdNumber == static_cast(0x82ae5050)) { + // This is a real error but we can't fix it due to our headers being too + // old. More more details see: + // https://vulkan.lunarg.com/doc/view/1.3.224.1/mac/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465 + // This validation error currently only trips on macOS due to the use of + // texture swizzles. + return VK_FALSE; + } + + const auto prefix = impeller::vk::to_string( + impeller::vk::DebugUtilsMessageSeverityFlagBitsEXT(severity)); + // Just so that the log doesn't say FML_DCHECK(false). + constexpr bool kVulkanValidationFailure = false; + FML_DCHECK(kVulkanValidationFailure) + << prefix << "[" << pCallbackData->messageIdNumber << "][" + << pCallbackData->pMessageIdName << "] : " << pCallbackData->pMessage; + + // The return value of this callback controls whether the Vulkan call that + // caused the validation message will be aborted or not We return VK_TRUE as + // we DO want Vulkan calls that cause a validation message to abort + return VK_TRUE; +} + +} // namespace + namespace impeller { -// TODO(csg): Fix this after caps are reworked. -static bool gHasValidationLayers = false; +namespace vk { bool HasValidationLayers() { - return gHasValidationLayers; + auto capabilities = std::make_unique(); + return capabilities->HasLayer(kKhronosValidationLayerName); +} + +} // namespace vk + +static std::set kRequiredDeviceExtensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, +#if FML_OS_MACOSX + "VK_KHR_portability_subset", // For Molten VK. No define present in header. +#endif +}; + +std::vector kRequiredWSIInstanceExtensions = { +#if FML_OS_WIN + "VK_KHR_win32_surface", +#elif FML_OS_ANDROID + "VK_KHR_android_surface", +#elif FML_OS_LINUX + "VK_KHR_xcb_surface", + "VK_KHR_xlib_surface", + "VK_KHR_wayland_surface", +#elif FML_OS_MACOSX + "VK_EXT_metal_surface", +#endif +}; + +#if FML_OS_MACOSX +static const char* MVK_MACOS_SURFACE_EXT = "VK_MVK_macos_surface"; +#endif + +static bool HasRequiredQueues(const vk::PhysicalDevice& device) { + auto present_flags = vk::QueueFlags{}; + for (const auto& queue : device.getQueueFamilyProperties()) { + if (queue.queueCount == 0) { + continue; + } + present_flags |= queue.queueFlags; + } + return static_cast(present_flags & + (vk::QueueFlagBits::eGraphics | + vk::QueueFlagBits::eCompute | + vk::QueueFlagBits::eTransfer)); +} + +static std::vector HasRequiredExtensions( + const vk::PhysicalDevice& device) { + std::set exts; + std::vector missing; + for (const auto& ext : device.enumerateDeviceExtensionProperties().value) { + exts.insert(ext.extensionName); + } + for (const auto& req_ext : kRequiredDeviceExtensions) { + if (exts.count(req_ext) != 1u) { + missing.push_back(req_ext); + } + } + return missing; +} + +static vk::PhysicalDeviceFeatures GetRequiredPhysicalDeviceFeatures() { + vk::PhysicalDeviceFeatures features; +#ifndef NDEBUG + features.setRobustBufferAccess(true); +#endif // NDEBUG + return features; +}; + +static bool HasRequiredProperties(const vk::PhysicalDevice& device) { + auto properties = device.getProperties(); + if (!(properties.limits.framebufferColorSampleCounts & + (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) { + return false; + } + return true; +} + +static bool IsPhysicalDeviceCompatible(const vk::PhysicalDevice& device) { + if (!HasRequiredQueues(device)) { + FML_LOG(ERROR) << "Device doesn't have required queues."; + return false; + } + auto missing_exts = HasRequiredExtensions(device); + if (!missing_exts.empty()) { + FML_LOG(ERROR) << "Device doesn't have required extensions: " + << fml::Join(missing_exts, ", "); + return false; + } + if (!HasRequiredProperties(device)) { + FML_LOG(ERROR) << "Device doesn't have required properties."; + return false; + } + return true; } static std::optional PickPhysicalDevice( - const CapabilitiesVK& caps, const vk::Instance& instance) { for (const auto& device : instance.enumeratePhysicalDevices().value) { - if (caps.GetRequiredDeviceFeatures(device).has_value()) { + if (IsPhysicalDeviceCompatible(device)) { return device; } } @@ -93,37 +219,27 @@ std::shared_ptr ContextVK::Create( const std::shared_ptr& pipeline_cache_data, std::shared_ptr worker_task_runner, const std::string& label) { - auto context = std::shared_ptr(new ContextVK()); - context->Setup(proc_address_callback, // - shader_libraries_data, // - pipeline_cache_data, // - std::move(worker_task_runner), // - label // - ); + auto context = std::shared_ptr(new ContextVK( + proc_address_callback, // + shader_libraries_data, // + pipeline_cache_data, // + std::move(worker_task_runner), // + label // + )); if (!context->IsValid()) { return nullptr; } return context; } -ContextVK::ContextVK() = default; - -ContextVK::~ContextVK() { - if (device_) { - [[maybe_unused]] auto result = device_->waitIdle(); - } - CommandPoolVK::ClearAllPools(this); -} - -void ContextVK::Setup( +ContextVK::ContextVK( PFN_vkGetInstanceProcAddr proc_address_callback, const std::vector>& shader_libraries_data, const std::shared_ptr& pipeline_cache_data, std::shared_ptr worker_task_runner, - const std::string& label) { - TRACE_EVENT0("impeller", "ContextVK::Setup"); - - worker_task_runner_ = std::move(worker_task_runner); + const std::string& label) + : worker_task_runner_(std::move(worker_task_runner)) { + TRACE_EVENT0("impeller", "ContextVK::Create"); if (!worker_task_runner_) { VALIDATION_LOG << "Invalid worker task runner."; @@ -133,41 +249,95 @@ void ContextVK::Setup( auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER; dispatcher.init(proc_address_callback); - auto caps = std::shared_ptr(new CapabilitiesVK()); + auto capabilities = std::make_unique(); - if (!caps->IsValid()) { - VALIDATION_LOG << "Could not determine device capabilities."; + vk::InstanceCreateFlags instance_flags = {}; + std::vector enabled_layers; + std::vector enabled_extensions; + +// This define may need to change into a runtime check if using SwiftShader on +// Mac. +#if FML_OS_MACOSX + //---------------------------------------------------------------------------- + /// Ensure we need any Vulkan implementations that are not fully compliant + /// with the requested Vulkan Spec. This is necessary for MoltenVK on Mac + /// (backed by Metal). + /// + if (!capabilities->HasExtension( + VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) { + VALIDATION_LOG << "On Mac: Required extension " + << VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + << " absent."; return; } + // Molten VK on Mac is not fully compliant. We opt into being OK not getting + // back a fully compliant version of a Vulkan implementation. + enabled_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR; - gHasValidationLayers = caps->AreValidationsEnabled(); - - auto enabled_layers = caps->GetRequiredLayers(); - auto enabled_extensions = caps->GetRequiredInstanceExtensions(); - - if (!enabled_layers.has_value() || !enabled_extensions.has_value()) { - VALIDATION_LOG << "Device has insufficient capabilities."; + if (!capabilities->HasExtension( + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { + VALIDATION_LOG << "On Mac: Required extension " + << VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + << " absent."; return; } + // This is dependency of VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME which + // is a requirement for opting into Molten VK on Mac. + enabled_extensions.push_back( + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - vk::InstanceCreateFlags instance_flags = {}; - - if (std::find(enabled_extensions.value().begin(), - enabled_extensions.value().end(), - "VK_KHR_portability_enumeration") != - enabled_extensions.value().end()) { - instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR; + // Required for glfw macOS surfaces. + if (!capabilities->HasExtension(MVK_MACOS_SURFACE_EXT)) { + VALIDATION_LOG << "On Mac: Required extension " << MVK_MACOS_SURFACE_EXT + << " absent."; + return; } + enabled_extensions.push_back(MVK_MACOS_SURFACE_EXT); +#endif // FML_OS_MACOSX - std::vector enabled_layers_c; - std::vector enabled_extensions_c; + //---------------------------------------------------------------------------- + /// Even though this is a WSI responsibility, require the surface extension + /// for swapchains. + if (!capabilities->HasExtension(VK_KHR_SURFACE_EXTENSION_NAME)) { + VALIDATION_LOG << "Required extension " VK_KHR_SURFACE_EXTENSION_NAME + << " absent."; + return; + } + enabled_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - for (const auto& layer : enabled_layers.value()) { - enabled_layers_c.push_back(layer.c_str()); + //---------------------------------------------------------------------------- + /// Enable WSI Instance Extensions. Having any one of these is sufficient. + /// + bool has_wsi_extensions = false; + for (const auto& wsi_ext : kRequiredWSIInstanceExtensions) { + if (capabilities->HasExtension(wsi_ext)) { + enabled_extensions.push_back(wsi_ext.c_str()); + has_wsi_extensions = true; + } + } + if (!has_wsi_extensions) { + VALIDATION_LOG + << "Instance doesn't have any of the required WSI extensions: " + << fml::Join(kRequiredWSIInstanceExtensions, ", "); + return; } - for (const auto& ext : enabled_extensions.value()) { - enabled_extensions_c.push_back(ext.c_str()); + //---------------------------------------------------------------------------- + /// Enable any and all validation as well as debug toggles. + /// + auto has_debug_utils = false; + if (vk::HasValidationLayers()) { + enabled_layers.push_back(vk::kKhronosValidationLayerName); + if (capabilities->HasLayerExtension(vk::kKhronosValidationLayerName, + VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + enabled_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + has_debug_utils = true; + } else { + FML_LOG(ERROR) << "Vulkan debug utils are absent."; + } + } else { + FML_LOG(ERROR) << "Vulkan validation layers are absent."; } vk::ApplicationInfo application_info; @@ -177,50 +347,52 @@ void ContextVK::Setup( application_info.setPEngineName("Impeller"); application_info.setPApplicationName("Impeller"); - std::vector enabled_validations = { - // vk::ValidationFeatureEnableEXT::eBestPractices, - // vk::ValidationFeatureEnableEXT::eSynchronizationValidation, - }; - - vk::ValidationFeaturesEXT validation; - validation.setEnabledValidationFeatures(enabled_validations); - vk::InstanceCreateInfo instance_info; - if (caps->AreValidationsEnabled()) { - instance_info.pNext = &validation; - } - instance_info.setPEnabledLayerNames(enabled_layers_c); - instance_info.setPEnabledExtensionNames(enabled_extensions_c); + instance_info.setPEnabledLayerNames(enabled_layers); + instance_info.setPEnabledExtensionNames(enabled_extensions); instance_info.setPApplicationInfo(&application_info); instance_info.setFlags(instance_flags); auto instance = vk::createInstanceUnique(instance_info); if (instance.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create instance: " + FML_LOG(ERROR) << "Could not create instance: " << vk::to_string(instance.result); return; } dispatcher.init(instance.value.get()); - //---------------------------------------------------------------------------- - /// Setup the debug report. - /// - /// Do this as early as possible since we could use the debug report from - /// initialization issues. - /// - auto debug_report = - std::make_unique(*caps, instance.value.get()); + vk::UniqueDebugUtilsMessengerEXT debug_messenger; + + if (has_debug_utils) { + vk::DebugUtilsMessengerCreateInfoEXT debug_messenger_info; + debug_messenger_info.messageSeverity = + vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | + vk::DebugUtilsMessageSeverityFlagBitsEXT::eError; + debug_messenger_info.messageType = + vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | + vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | + vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation; + debug_messenger_info.pUserData = nullptr; + debug_messenger_info.pfnUserCallback = DebugUtilsMessengerCallback; + + auto debug_messenger_result = + instance.value->createDebugUtilsMessengerEXTUnique( + debug_messenger_info); + + if (debug_messenger_result.result != vk::Result::eSuccess) { + FML_LOG(ERROR) << "Could not create debug messenger: " + << vk::to_string(debug_messenger_result.result); + return; + } - if (!debug_report->IsValid()) { - VALIDATION_LOG << "Could not setup debug report."; - return; + debug_messenger = std::move(debug_messenger_result.value); } //---------------------------------------------------------------------------- /// Pick the physical device. /// - auto physical_device = PickPhysicalDevice(*caps, instance.value.get()); + auto physical_device = PickPhysicalDevice(instance.value.get()); if (!physical_device.has_value()) { VALIDATION_LOG << "No valid Vulkan device found."; return; @@ -236,44 +408,29 @@ void ContextVK::Setup( auto compute_queue = PickQueue(physical_device.value(), vk::QueueFlagBits::eCompute); + physical_device_ = physical_device.value(); + if (!graphics_queue.has_value() || !transfer_queue.has_value() || !compute_queue.has_value()) { VALIDATION_LOG << "Could not pick device queues."; return; } - //---------------------------------------------------------------------------- - /// Create the logical device. - /// - auto enabled_device_extensions = - caps->GetRequiredDeviceExtensions(physical_device.value()); - if (!enabled_device_extensions.has_value()) { - // This shouldn't happen since we already did device selection. But doesn't - // hurt to check again. - return; - } - - std::vector enabled_device_extensions_c; - for (const auto& ext : enabled_device_extensions.value()) { - enabled_device_extensions_c.push_back(ext.c_str()); + std::vector required_extensions; + for (const auto& ext : kRequiredDeviceExtensions) { + required_extensions.push_back(ext.data()); } const auto queue_create_infos = GetQueueCreateInfos( {graphics_queue.value(), compute_queue.value(), transfer_queue.value()}); - const auto required_features = - caps->GetRequiredDeviceFeatures(physical_device.value()); - if (!required_features.has_value()) { - // This shouldn't happen since the device can't be picked if this was not - // true. But doesn't hurt to check. - return; - } + const auto required_features = GetRequiredPhysicalDeviceFeatures(); vk::DeviceCreateInfo device_info; device_info.setQueueCreateInfos(queue_create_infos); - device_info.setPEnabledExtensionNames(enabled_device_extensions_c); - device_info.setPEnabledFeatures(&required_features.value()); + device_info.setPEnabledExtensionNames(required_extensions); + device_info.setPEnabledFeatures(&required_features); // Device layers are deprecated and ignored. auto device = physical_device->createDeviceUnique(device_info); @@ -282,14 +439,6 @@ void ContextVK::Setup( return; } - if (!caps->SetDevice(physical_device.value())) { - VALIDATION_LOG << "Capabilities could not be updated."; - return; - } - - //---------------------------------------------------------------------------- - /// Create the allocator. - /// auto allocator = std::shared_ptr(new AllocatorVK( weak_from_this(), // application_info.apiVersion, // @@ -330,9 +479,6 @@ void ContextVK::Setup( return; } - //---------------------------------------------------------------------------- - /// Setup the work queues. - /// auto work_queue = WorkQueueCommon::Create(); if (!work_queue) { @@ -341,12 +487,47 @@ void ContextVK::Setup( } //---------------------------------------------------------------------------- - /// Create the fence waiter. + /// Setup the command pool. /// - auto fence_waiter = - std::shared_ptr(new FenceWaiterVK(device.value.get())); - if (!fence_waiter->IsValid()) { - VALIDATION_LOG << "Could not create fence waiter."; + vk::CommandPoolCreateInfo graphics_command_pool_info; + graphics_command_pool_info.queueFamilyIndex = graphics_queue->index; + graphics_command_pool_info.flags = vk::CommandPoolCreateFlagBits::eTransient; + auto graphics_command_pool = + device.value->createCommandPoolUnique(graphics_command_pool_info); + if (graphics_command_pool.result != vk::Result::eSuccess) { + VALIDATION_LOG << "Could not create graphics command pool."; + return; + } + + //---------------------------------------------------------------------------- + /// Setup the descriptor pool. This needs to be dynamic but we just allocate a + /// jumbo pool and hope for the best. + /// + constexpr size_t kPoolSize = 1024 * 3; + + std::vector pool_sizes = { + {vk::DescriptorType::eSampler, kPoolSize}, + {vk::DescriptorType::eCombinedImageSampler, kPoolSize}, + {vk::DescriptorType::eSampledImage, kPoolSize}, + {vk::DescriptorType::eStorageImage, kPoolSize}, + {vk::DescriptorType::eUniformTexelBuffer, kPoolSize}, + {vk::DescriptorType::eStorageTexelBuffer, kPoolSize}, + {vk::DescriptorType::eUniformBuffer, kPoolSize}, + {vk::DescriptorType::eStorageBuffer, kPoolSize}, + {vk::DescriptorType::eUniformBufferDynamic, kPoolSize}, + {vk::DescriptorType::eStorageBufferDynamic, kPoolSize}, + {vk::DescriptorType::eInputAttachment, kPoolSize}, + }; + vk::DescriptorPoolCreateInfo pool_info = { + vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, // flags + static_cast(pool_sizes.size() * kPoolSize), // max sets + static_cast(pool_sizes.size()), // pool sizes count + pool_sizes.data() // pool sizes + }; + + auto descriptor_pool = device.value->createDescriptorPoolUnique(pool_info); + if (descriptor_pool.result != vk::Result::eSuccess) { + VALIDATION_LOG << "Unable to create a descriptor pool"; return; } @@ -354,8 +535,7 @@ void ContextVK::Setup( /// All done! /// instance_ = std::move(instance.value); - debug_report_ = std::move(debug_report); - physical_device_ = physical_device.value(); + debug_messenger_ = std::move(debug_messenger); device_ = std::move(device.value); allocator_ = std::move(allocator); shader_library_ = std::move(shader_library); @@ -368,21 +548,27 @@ void ContextVK::Setup( device_->getQueue(compute_queue->family, compute_queue->index); transfer_queue_ = device_->getQueue(transfer_queue->family, transfer_queue->index); - graphics_queue_info_ = graphics_queue.value(); - compute_queue_info_ = compute_queue.value(); - transfer_queue_info_ = transfer_queue.value(); - device_capabilities_ = std::move(caps); - fence_waiter_ = std::move(fence_waiter); + device_capabilities_ = + DeviceCapabilitiesBuilder() + .SetHasThreadingRestrictions(false) + .SetSupportsOffscreenMSAA(true) + .SetSupportsSSBO(false) + .SetSupportsTextureToTextureBlits(true) + .SetSupportsFramebufferFetch(false) + .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) + .SetDefaultStencilFormat(PixelFormat::kS8UInt) + // TODO(110622): detect this and enable. + .SetSupportsCompute(false, false) + .Build(); + graphics_command_pool_ = std::move(graphics_command_pool.value); + descriptor_pool_ = std::move(descriptor_pool.value); is_valid_ = true; +} - //---------------------------------------------------------------------------- - /// Label all the relevant objects. This happens after setup so that the debug - /// messengers have had a chance to be setup. - /// - SetDebugName(device_.get(), device_.get(), "ImpellerDevice"); - SetDebugName(device_.get(), graphics_queue_, "ImpellerGraphicsQ"); - SetDebugName(device_.get(), compute_queue_, "ImpellerComputeQ"); - SetDebugName(device_.get(), transfer_queue_, "ImpellerTransferQ"); +ContextVK::~ContextVK() { + if (device_) { + [[maybe_unused]] auto result = device_->waitIdle(); + } } bool ContextVK::IsValid() const { @@ -411,13 +597,9 @@ std::shared_ptr ContextVK::GetWorkQueue() const { } std::shared_ptr ContextVK::CreateCommandBuffer() const { - auto encoder = CreateGraphicsCommandEncoder(); - if (!encoder) { - return nullptr; - } return std::shared_ptr( - new CommandBufferVK(shared_from_this(), // - std::move(encoder)) // + new CommandBufferVK(shared_from_this(), // + CreateGraphicsCommandEncoder()) // ); } @@ -464,37 +646,37 @@ bool ContextVK::SetWindowSurface(vk::UniqueSurfaceKHR surface) { return true; } -const std::shared_ptr& ContextVK::GetCapabilities() const { - return device_capabilities_; +PixelFormat ContextVK::GetColorAttachmentPixelFormat() const { + return swapchain_ ? ToPixelFormat(swapchain_->GetSurfaceFormat()) + : PixelFormat::kB8G8R8A8UNormInt; +} + +const IDeviceCapabilities& ContextVK::GetDeviceCapabilities() const { + return *device_capabilities_; } vk::Queue ContextVK::GetGraphicsQueue() const { return graphics_queue_; } -QueueVK ContextVK::GetGraphicsQueueInfo() const { - return graphics_queue_info_; +vk::CommandPool ContextVK::GetGraphicsCommandPool() const { + return *graphics_command_pool_; } -vk::PhysicalDevice ContextVK::GetPhysicalDevice() const { - return physical_device_; +vk::DescriptorPool ContextVK::GetDescriptorPool() const { + return *descriptor_pool_; } -std::shared_ptr ContextVK::GetFenceWaiter() const { - return fence_waiter_; +vk::PhysicalDevice ContextVK::GetPhysicalDevice() const { + return physical_device_; } std::unique_ptr ContextVK::CreateGraphicsCommandEncoder() const { - auto tls_pool = CommandPoolVK::GetThreadLocal(this); - if (!tls_pool) { - return nullptr; - } auto encoder = std::unique_ptr(new CommandEncoderVK( - *device_, // - graphics_queue_, // - tls_pool, // - fence_waiter_ // + *device_, // + graphics_queue_, // + *graphics_command_pool_ // )); if (!encoder->IsValid()) { return nullptr; diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 089417971b960..3cd22bb490b2b 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -15,18 +15,24 @@ #include "impeller/renderer/backend/vulkan/shader_library_vk.h" #include "impeller/renderer/backend/vulkan/swapchain_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" -#include "impeller/renderer/capabilities.h" #include "impeller/renderer/context.h" +#include "impeller/renderer/device_capabilities.h" #include "impeller/renderer/formats.h" #include "impeller/renderer/surface.h" namespace impeller { +namespace vk { + +// TODO(csg): Move this to its own TU for validations. +constexpr const char* kKhronosValidationLayerName = + "VK_LAYER_KHRONOS_validation"; + bool HasValidationLayers(); +} // namespace vk + class CommandEncoderVK; -class DebugReportVK; -class FenceWaiterVK; class ContextVK final : public Context, public BackendCast { public: @@ -58,11 +64,14 @@ class ContextVK final : public Context, public BackendCast { // |Context| std::shared_ptr CreateCommandBuffer() const override; + // |Context| + PixelFormat GetColorAttachmentPixelFormat() const override; + // |Context| std::shared_ptr GetWorkQueue() const override; // |Context| - const std::shared_ptr& GetCapabilities() const override; + const IDeviceCapabilities& GetDeviceCapabilities() const override; template bool SetDebugName(T handle, std::string_view label) const { @@ -73,19 +82,22 @@ class ContextVK final : public Context, public BackendCast { static bool SetDebugName(vk::Device device, T handle, std::string_view label) { - if (!HasValidationLayers()) { + if (!vk::HasValidationLayers()) { // No-op if validation layers are not enabled. return true; } - auto c_handle = static_cast(handle); + uint64_t handle_ptr = + reinterpret_cast(static_cast(handle)); - vk::DebugUtilsObjectNameInfoEXT info; - info.objectType = T::objectType; - info.pObjectName = label.data(); - info.objectHandle = reinterpret_cast(c_handle); + std::string label_str = std::string(label); + auto ret = device.setDebugUtilsObjectNameEXT( + vk::DebugUtilsObjectNameInfoEXT() + .setObjectType(T::objectType) + .setObjectHandle(handle_ptr) + .setPObjectName(label_str.c_str())); - if (device.setDebugUtilsObjectNameEXT(info) != vk::Result::eSuccess) { + if (ret != vk::Result::eSuccess) { VALIDATION_LOG << "Unable to set debug name: " << label; return false; } @@ -107,16 +119,16 @@ class ContextVK final : public Context, public BackendCast { vk::Queue GetGraphicsQueue() const; - QueueVK GetGraphicsQueueInfo() const; + vk::CommandPool GetGraphicsCommandPool() const; - vk::PhysicalDevice GetPhysicalDevice() const; + vk::DescriptorPool GetDescriptorPool() const; - std::shared_ptr GetFenceWaiter() const; + vk::PhysicalDevice GetPhysicalDevice() const; private: std::shared_ptr worker_task_runner_; vk::UniqueInstance instance_; - std::unique_ptr debug_report_; + vk::UniqueDebugUtilsMessengerEXT debug_messenger_; vk::PhysicalDevice physical_device_; vk::UniqueDevice device_; std::shared_ptr allocator_; @@ -126,19 +138,14 @@ class ContextVK final : public Context, public BackendCast { vk::Queue graphics_queue_ = {}; vk::Queue compute_queue_ = {}; vk::Queue transfer_queue_ = {}; - QueueVK graphics_queue_info_ = {}; - QueueVK compute_queue_info_ = {}; - QueueVK transfer_queue_info_ = {}; std::shared_ptr swapchain_; std::shared_ptr work_queue_; - std::shared_ptr device_capabilities_; - std::shared_ptr fence_waiter_; - + std::unique_ptr device_capabilities_; + vk::UniqueCommandPool graphics_command_pool_; + vk::UniqueDescriptorPool descriptor_pool_; bool is_valid_ = false; - ContextVK(); - - void Setup( + ContextVK( PFN_vkGetInstanceProcAddr proc_address_callback, const std::vector>& shader_libraries_data, const std::shared_ptr& pipeline_cache_data, diff --git a/impeller/renderer/backend/vulkan/debug_report_vk.cc b/impeller/renderer/backend/vulkan/debug_report_vk.cc deleted file mode 100644 index c538245aba50d..0000000000000 --- a/impeller/renderer/backend/vulkan/debug_report_vk.cc +++ /dev/null @@ -1,189 +0,0 @@ -// 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 "impeller/renderer/backend/vulkan/debug_report_vk.h" - -#include "impeller/renderer/backend/vulkan/capabilities_vk.h" - -namespace impeller { - -DebugReportVK::DebugReportVK(const CapabilitiesVK& caps, - const vk::Instance& instance) { - if (!caps.AreValidationsEnabled()) { - is_valid_ = true; - return; - } - - vk::DebugUtilsMessengerCreateInfoEXT messenger_info; - messenger_info.messageSeverity = - vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | - vk::DebugUtilsMessageSeverityFlagBitsEXT::eError; - messenger_info.messageType = - vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | - vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | - vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation; - messenger_info.pUserData = this; - messenger_info.pfnUserCallback = DebugUtilsMessengerCallback; - - auto messenger = instance.createDebugUtilsMessengerEXTUnique(messenger_info); - - if (messenger.result != vk::Result::eSuccess) { - FML_LOG(ERROR) << "Could not create debug messenger: " - << vk::to_string(messenger.result); - return; - } - - messenger_ = std::move(messenger.value); - is_valid_ = true; -} - -DebugReportVK::~DebugReportVK() = default; - -bool DebugReportVK::IsValid() const { - return is_valid_; -} - -static std::string JoinLabels(const VkDebugUtilsLabelEXT* labels, - size_t count) { - std::stringstream stream; - for (size_t i = 0u; i < count; i++) { - stream << labels[i].pLabelName; - if (i != count - 1u) { - stream << ", "; - } - } - return stream.str(); -} - -static std::string JoinVKDebugUtilsObjectNameInfoEXT( - const VkDebugUtilsObjectNameInfoEXT* names, - size_t count) { - std::stringstream stream; - for (size_t i = 0u; i < count; i++) { - stream << vk::to_string(vk::ObjectType(names[i].objectType)) << " [" - << names[i].objectHandle << "] ["; - if (names[i].pObjectName != nullptr) { - stream << names[i].pObjectName; - } else { - stream << "UNNAMED"; - } - stream << "]"; - if (i != count - 1u) { - stream << ", "; - } - } - return stream.str(); -} - -VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportVK::DebugUtilsMessengerCallback( - VkDebugUtilsMessageSeverityFlagBitsEXT severity, - VkDebugUtilsMessageTypeFlagsEXT type, - const VkDebugUtilsMessengerCallbackDataEXT* callback_data, - void* debug_report) { - auto result = - reinterpret_cast(debug_report) - ->OnDebugCallback( - static_cast( - severity), // - static_cast(type), // - callback_data // - ); - switch (result) { - case Result::kContinue: - return VK_FALSE; - case Result::kAbort: - return VK_TRUE; - } - return VK_FALSE; -} - -DebugReportVK::Result DebugReportVK::OnDebugCallback( - vk::DebugUtilsMessageSeverityFlagBitsEXT severity, - vk::DebugUtilsMessageTypeFlagsEXT type, - const VkDebugUtilsMessengerCallbackDataEXT* data) { - // Issue in older versions of the SDK. - // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/3554 - if (strstr(data->pMessageIdName, "CoreValidation-Shader-OutputNotConsumed") != - nullptr) { - return Result::kContinue; - } - - // This is a real error but we can't fix it due to our headers being too - // old. More more details see: - // https://vulkan.lunarg.com/doc/view/1.3.224.1/mac/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465 - // This validation error currently only trips on macOS due to the use of - // texture swizzles. - if (data->messageIdNumber == static_cast(0x82ae5050)) { - return Result::kContinue; - } - - std::vector> items; - - items.emplace_back("Severity", vk::to_string(severity)); - - items.emplace_back("Type", vk::to_string(type)); - - if (data->pMessageIdName) { - items.emplace_back("ID Name", data->pMessageIdName); - } - - items.emplace_back("ID Number", std::to_string(data->messageIdNumber)); - - if (auto queues = JoinLabels(data->pQueueLabels, data->queueLabelCount); - !queues.empty()) { - items.emplace_back("Queue Breadcrumbs", std::move(queues)); - } else { - items.emplace_back("Queue Breadcrumbs", "[NONE]"); - } - - if (auto cmd_bufs = JoinLabels(data->pCmdBufLabels, data->cmdBufLabelCount); - !cmd_bufs.empty()) { - items.emplace_back("CMD Buffer Breadcrumbs", std::move(cmd_bufs)); - } else { - items.emplace_back("CMD Buffer Breadcrumbs", "[NONE]"); - } - - if (auto related = - JoinVKDebugUtilsObjectNameInfoEXT(data->pObjects, data->objectCount); - !related.empty()) { - items.emplace_back("Related Objects", std::move(related)); - } - - if (data->pMessage) { - items.emplace_back("Trigger", data->pMessage); - } - - size_t padding = 0; - - for (const auto& item : items) { - padding = std::max(padding, item.first.size()); - } - - padding += 1; - - std::stringstream stream; - - stream << std::endl; - - stream << "--- Vulkan Debug Report ----------------------------------------"; - - stream << std::endl; - - for (const auto& item : items) { - stream << "| " << std::setw(static_cast(padding)) << item.first - << std::setw(0) << ": " << item.second << std::endl; - } - - stream << "-----------------------------------------------------------------"; - - if (type == vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance) { - FML_LOG(INFO) << stream.str(); - } else { - VALIDATION_LOG << stream.str(); - } - - return Result::kAbort; -} - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/debug_report_vk.h b/impeller/renderer/backend/vulkan/debug_report_vk.h deleted file mode 100644 index 387d7f6d28c20..0000000000000 --- a/impeller/renderer/backend/vulkan/debug_report_vk.h +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -#pragma once - -#include "flutter/fml/macros.h" -#include "impeller/renderer/backend/vulkan/vk.h" - -namespace impeller { - -class CapabilitiesVK; - -class DebugReportVK { - public: - DebugReportVK(const CapabilitiesVK& caps, const vk::Instance& instance); - - ~DebugReportVK(); - - bool IsValid() const; - - private: - vk::UniqueDebugUtilsMessengerEXT messenger_; - bool is_valid_ = false; - - enum class Result { - kContinue, - kAbort, - }; - - Result OnDebugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity, - vk::DebugUtilsMessageTypeFlagsEXT type, - const VkDebugUtilsMessengerCallbackDataEXT* data); - - static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsMessengerCallback( - VkDebugUtilsMessageSeverityFlagBitsEXT severity, - VkDebugUtilsMessageTypeFlagsEXT type, - const VkDebugUtilsMessengerCallbackDataEXT* callback_data, - void* user_data); - - FML_DISALLOW_COPY_AND_ASSIGN(DebugReportVK); -}; - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc b/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc deleted file mode 100644 index 5fb1ef74fdcd9..0000000000000 --- a/impeller/renderer/backend/vulkan/descriptor_pool_vk.cc +++ /dev/null @@ -1,74 +0,0 @@ -// 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 "impeller/renderer/backend/vulkan/descriptor_pool_vk.h" - -#include "flutter/fml/trace_event.h" -#include "impeller/base/allocation.h" - -namespace impeller { - -DescriptorPoolVK::DescriptorPoolVK(vk::Device device) : device_(device) {} - -DescriptorPoolVK::~DescriptorPoolVK() = default; - -static vk::UniqueDescriptorPool CreatePool(const vk::Device& device, - uint32_t pool_count) { - TRACE_EVENT0("impeller", "CreateDescriptorPool"); - std::vector pools = { - {vk::DescriptorType::eCombinedImageSampler, pool_count}, - {vk::DescriptorType::eUniformBuffer, pool_count}, - }; - - vk::DescriptorPoolCreateInfo pool_info; - pool_info.setMaxSets(pools.size() * pool_count); - pool_info.setPoolSizes(pools); - - auto [result, pool] = device.createDescriptorPoolUnique(pool_info); - if (result != vk::Result::eSuccess) { - VALIDATION_LOG << "Unable to create a descriptor pool"; - } - return std::move(pool); -} - -std::optional DescriptorPoolVK::AllocateDescriptorSet( - const vk::DescriptorSetLayout& layout) { - auto pool = GetDescriptorPool(); - if (!pool) { - return std::nullopt; - } - vk::DescriptorSetAllocateInfo set_info; - set_info.setDescriptorPool(pool.value()); - set_info.setSetLayouts(layout); - auto [result, sets] = device_.allocateDescriptorSets(set_info); - if (result == vk::Result::eErrorOutOfPoolMemory) { - return GrowPool() ? AllocateDescriptorSet(layout) : std::nullopt; - } - if (result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not allocate descriptor sets: " - << vk::to_string(result); - return std::nullopt; - } - return sets[0]; -} - -std::optional DescriptorPoolVK::GetDescriptorPool() { - if (pools_.empty()) { - return GrowPool() ? GetDescriptorPool() : std::nullopt; - } - return *pools_.back(); -} - -bool DescriptorPoolVK::GrowPool() { - const auto new_pool_size = Allocation::NextPowerOfTwoSize(pool_size_ + 1u); - auto new_pool = CreatePool(device_, new_pool_size); - if (!new_pool) { - return false; - } - pool_size_ = new_pool_size; - pools_.push(std::move(new_pool)); - return true; -} - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/descriptor_pool_vk.h b/impeller/renderer/backend/vulkan/descriptor_pool_vk.h deleted file mode 100644 index 4af9c0bc8b13a..0000000000000 --- a/impeller/renderer/backend/vulkan/descriptor_pool_vk.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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. - -#pragma once - -#include -#include - -#include "flutter/fml/macros.h" -#include "impeller/renderer/backend/vulkan/vk.h" - -namespace impeller { - -//------------------------------------------------------------------------------ -/// @brief A short-lived dynamically-sized descriptor pool. Descriptors -/// from this pool don't need to be freed individually. Instead, the -/// pool must be collected after all the descriptors allocated from -/// it are done being used. -/// -/// The pool or it's descriptors may not be accessed from multiple -/// threads. -/// -/// Encoders create pools as necessary as they have the same -/// threading and lifecycle restrictions. -/// -class DescriptorPoolVK { - public: - explicit DescriptorPoolVK(vk::Device device); - - ~DescriptorPoolVK(); - - std::optional AllocateDescriptorSet( - const vk::DescriptorSetLayout& layout); - - private: - const vk::Device device_; - uint32_t pool_size_ = 31u; - std::queue pools_; - - std::optional GetDescriptorPool(); - - bool GrowPool(); - - FML_DISALLOW_COPY_AND_ASSIGN(DescriptorPoolVK); -}; - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.cc b/impeller/renderer/backend/vulkan/device_buffer_vk.cc index e9859ff9390a5..e38c63fa688fc 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.cc @@ -67,7 +67,7 @@ bool DeviceBufferVK::SetLabel(const std::string& label, Range range) { return SetLabel(label); } -vk::Buffer DeviceBufferVK::GetBuffer() const { +vk::Buffer DeviceBufferVK::GetVKBufferHandle() const { return buffer_; } diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.h b/impeller/renderer/backend/vulkan/device_buffer_vk.h index 2f579c13a1e9c..132be608c3617 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.h +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.h @@ -26,7 +26,7 @@ class DeviceBufferVK final : public DeviceBuffer, // |DeviceBuffer| ~DeviceBufferVK() override; - vk::Buffer GetBuffer() const; + vk::Buffer GetVKBufferHandle() const; private: friend class AllocatorVK; diff --git a/impeller/renderer/backend/vulkan/fence_waiter_vk.cc b/impeller/renderer/backend/vulkan/fence_waiter_vk.cc deleted file mode 100644 index 06c4c094cbf67..0000000000000 --- a/impeller/renderer/backend/vulkan/fence_waiter_vk.cc +++ /dev/null @@ -1,108 +0,0 @@ -// 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 "impeller/renderer/backend/vulkan/fence_waiter_vk.h" - -#include - -#include "flutter/fml/thread.h" - -namespace impeller { - -FenceWaiterVK::FenceWaiterVK(vk::Device device) : device_(device) { - waiter_thread_ = std::make_unique([&]() { Main(); }); - is_valid_ = true; -} - -FenceWaiterVK::~FenceWaiterVK() { - Terminate(); - if (waiter_thread_) { - waiter_thread_->join(); - } -} - -bool FenceWaiterVK::IsValid() const { - return is_valid_; -} - -bool FenceWaiterVK::AddFence(vk::UniqueFence fence, - const fml::closure& callback) { - if (!IsValid() || !fence || !callback) { - return false; - } - { - std::scoped_lock lock(wait_set_mutex_); - wait_set_[MakeSharedVK(std::move(fence))] = callback; - } - wait_set_cv_.notify_one(); - return true; -} - -void FenceWaiterVK::Main() { - fml::Thread::SetCurrentThreadName( - fml::Thread::ThreadConfig{"io.flutter.impeller.fence_waiter"}); - - using namespace std::literals::chrono_literals; - - while (true) { - std::unique_lock lock(wait_set_mutex_); - - wait_set_cv_.wait(lock, [&]() { return !wait_set_.empty() || terminate_; }); - - auto wait_set = TrimAndCreateWaitSetLocked(); - - lock.unlock(); - - if (!wait_set.has_value()) { - break; - } - if (wait_set->empty()) { - continue; - } - - auto result = device_.waitForFences( - wait_set->size(), // fences count - wait_set->data(), // fences - false, // wait for all - std::chrono::nanoseconds{100ms}.count() // timeout (ns) - ); - if (!(result == vk::Result::eSuccess || result == vk::Result::eTimeout)) { - break; - } - } -} - -std::optional> -FenceWaiterVK::TrimAndCreateWaitSetLocked() { - if (terminate_) { - return std::nullopt; - } - std::vector fences; - fences.reserve(wait_set_.size()); - for (auto it = wait_set_.begin(); it != wait_set_.end();) { - switch (device_.getFenceStatus(it->first->Get())) { - case vk::Result::eSuccess: // Signalled. - it->second(); - it = wait_set_.erase(it); - break; - case vk::Result::eNotReady: // Un-signalled. - fences.push_back(it->first->Get()); - it++; - break; - default: - return std::nullopt; - } - } - return fences; -} - -void FenceWaiterVK::Terminate() { - { - std::scoped_lock lock(wait_set_mutex_); - terminate_ = true; - } - wait_set_cv_.notify_one(); -} - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/fence_waiter_vk.h b/impeller/renderer/backend/vulkan/fence_waiter_vk.h deleted file mode 100644 index 0f5087f0d2514..0000000000000 --- a/impeller/renderer/backend/vulkan/fence_waiter_vk.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -#pragma once - -#include -#include -#include -#include -#include - -#include "flutter/fml/closure.h" -#include "flutter/fml/macros.h" -#include "impeller/base/thread.h" -#include "impeller/renderer/backend/vulkan/shared_object_vk.h" -#include "impeller/renderer/backend/vulkan/vk.h" - -namespace impeller { - -class ContextVK; - -class FenceWaiterVK { - public: - ~FenceWaiterVK(); - - bool IsValid() const; - - void Terminate(); - - bool AddFence(vk::UniqueFence fence, const fml::closure& callback); - - private: - friend class ContextVK; - - const vk::Device device_; - std::unique_ptr waiter_thread_; - std::mutex wait_set_mutex_; - std::condition_variable wait_set_cv_; - std::unordered_map, fml::closure> wait_set_; - bool terminate_ = false; - bool is_valid_ = false; - - explicit FenceWaiterVK(vk::Device device); - - void Main(); - - std::optional> TrimAndCreateWaitSetLocked(); - - FML_DISALLOW_COPY_AND_ASSIGN(FenceWaiterVK); -}; - -} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/formats_vk.h b/impeller/renderer/backend/vulkan/formats_vk.h index 64e8f5a6c447d..83ea4acc463b0 100644 --- a/impeller/renderer/backend/vulkan/formats_vk.h +++ b/impeller/renderer/backend/vulkan/formats_vk.h @@ -6,6 +6,7 @@ #include "flutter/fml/macros.h" #include "impeller/renderer/backend/vulkan/vk.h" +#include "impeller/renderer/descriptor_set_layout.h" #include "impeller/renderer/formats.h" #include "impeller/renderer/shader_types.h" #include "vulkan/vulkan_enums.hpp" @@ -204,8 +205,6 @@ constexpr vk::SampleCountFlagBits ToVKSampleCount(SampleCount sample_count) { case SampleCount::kCount4: return vk::SampleCountFlagBits::e4; } - - FML_UNREACHABLE(); } constexpr vk::Filter ToVKSamplerMinMagFilter(MinMagFilter filter) { @@ -270,7 +269,7 @@ constexpr vk::DescriptorSetLayoutBinding ToVKDescriptorSetLayoutBinding( const DescriptorSetLayout& layout) { vk::DescriptorSetLayoutBinding binding; binding.binding = layout.binding; - binding.descriptorCount = 1u; + binding.descriptorCount = layout.descriptor_count; vk::DescriptorType desc_type = vk::DescriptorType(); switch (layout.descriptor_type) { case DescriptorType::kSampledImage: @@ -547,60 +546,9 @@ constexpr uint32_t ToArrayLayerCount(TextureType type) { FML_UNREACHABLE(); } -constexpr vk::ImageViewType ToVKImageViewType(TextureType type) { - switch (type) { - case TextureType::kTexture2D: - case TextureType::kTexture2DMultisample: - return vk::ImageViewType::e2D; - case TextureType::kTextureCube: - return vk::ImageViewType::eCube; - } - FML_UNREACHABLE(); -} - -constexpr vk::ImageCreateFlags ToVKImageCreateFlags(TextureType type) { - switch (type) { - case TextureType::kTexture2D: - case TextureType::kTexture2DMultisample: - return {}; - case TextureType::kTextureCube: - return vk::ImageCreateFlagBits::eCubeCompatible; - } - FML_UNREACHABLE(); -} - vk::PipelineDepthStencilStateCreateInfo ToVKPipelineDepthStencilStateCreateInfo( std::optional depth, std::optional front, std::optional back); -constexpr vk::ImageAspectFlags ToImageAspectFlags(vk::ImageLayout layout) { - switch (layout) { - case vk::ImageLayout::eColorAttachmentOptimal: - case vk::ImageLayout::eShaderReadOnlyOptimal: - case vk::ImageLayout::eTransferSrcOptimal: - case vk::ImageLayout::eTransferDstOptimal: - case vk::ImageLayout::ePresentSrcKHR: - return vk::ImageAspectFlagBits::eColor; - case vk::ImageLayout::eDepthAttachmentOptimal: - return vk::ImageAspectFlagBits::eDepth; - case vk::ImageLayout::eStencilAttachmentOptimal: - return vk::ImageAspectFlagBits::eStencil; - default: - FML_DLOG(INFO) << "Unknown layout to determine aspect: " - << vk::to_string(layout); - return vk::ImageAspectFlagBits::eNone; - } - FML_UNREACHABLE(); -} - -struct LayoutTransition { - vk::CommandBuffer cmd_buffer = {}; - vk::ImageLayout new_layout = vk::ImageLayout::eUndefined; - vk::PipelineStageFlags src_stage = vk::PipelineStageFlagBits::eNone; - vk::AccessFlags src_access = vk::AccessFlagBits::eNone; - vk::PipelineStageFlags dst_stage = vk::PipelineStageFlagBits::eNone; - vk::AccessFlags dst_access = vk::AccessFlagBits::eNone; -}; - } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc index 6016a5bd59836..1cc9e2303612d 100644 --- a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc +++ b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc @@ -53,6 +53,54 @@ bool PipelineLibraryVK::IsValid() const { return is_valid_; } +// |PipelineLibrary| +PipelineFuture PipelineLibraryVK::GetPipeline( + PipelineDescriptor descriptor) { + Lock lock(pipelines_mutex_); + if (auto found = pipelines_.find(descriptor); found != pipelines_.end()) { + return found->second; + } + + if (!IsValid()) { + return { + descriptor, + RealizedFuture>>(nullptr)}; + } + + auto promise = std::make_shared< + std::promise>>>(); + auto pipeline_future = + PipelineFuture{descriptor, promise->get_future()}; + pipelines_[descriptor] = pipeline_future; + + auto weak_this = weak_from_this(); + + worker_task_runner_->PostTask([descriptor, weak_this, promise]() { + auto thiz = weak_this.lock(); + if (!thiz) { + promise->set_value(nullptr); + VALIDATION_LOG << "Pipeline library was collected before the pipeline " + "could be created."; + return; + } + auto pipeline_create_info = + PipelineLibraryVK::Cast(thiz.get())->CreatePipeline(descriptor); + promise->set_value(std::make_shared( + weak_this, descriptor, std::move(pipeline_create_info))); + }); + + return pipeline_future; +} + +// |PipelineLibrary| +PipelineFuture PipelineLibraryVK::GetPipeline( + ComputePipelineDescriptor descriptor) { + auto promise = std::make_shared< + std::promise>>>(); + promise->set_value(nullptr); + return {descriptor, promise->get_future()}; +} + //------------------------------------------------------------------------------ /// @brief Creates an attachment description that does just enough to /// ensure render pass compatibility with the pass associated later @@ -75,6 +123,17 @@ static vk::AttachmentDescription CreatePlaceholderAttachmentDescription( ); } +// |PipelineLibrary| +void PipelineLibraryVK::RemovePipelinesWithEntryPoint( + std::shared_ptr function) { + Lock lock(pipelines_mutex_); + + fml::erase_if(pipelines_, [&](auto item) { + return item->first.GetEntrypointForStage(function->GetStage()) + ->IsEqual(*function); + }); +} + //---------------------------------------------------------------------------- /// Render Pass /// We are NOT going to use the same render pass with the framebuffer (later) @@ -86,8 +145,8 @@ static vk::AttachmentDescription CreatePlaceholderAttachmentDescription( /// StencilAttachmentDescriptor, and, DepthAttachmentDescriptor. /// Right now, these are placeholders. /// -static vk::UniqueRenderPass CreateRenderPass(const vk::Device& device, - const PipelineDescriptor& desc) { +vk::UniqueRenderPass PipelineLibraryVK::CreateRenderPass( + const PipelineDescriptor& desc) { std::vector attachments; std::vector color_refs; @@ -131,7 +190,7 @@ static vk::UniqueRenderPass CreateRenderPass(const vk::Device& device, render_pass_desc.setPSubpasses(&subpass_desc); render_pass_desc.setSubpassCount(1u); - auto [result, pass] = device.createRenderPassUnique(render_pass_desc); + auto [result, pass] = device_.createRenderPassUnique(render_pass_desc); if (result != vk::Result::eSuccess) { VALIDATION_LOG << "Failed to create render pass for pipeline '" << desc.GetLabel() << "'. Error: " << vk::to_string(result); @@ -151,7 +210,7 @@ constexpr vk::FrontFace ToVKFrontFace(WindingOrder order) { FML_UNREACHABLE(); } -std::unique_ptr PipelineLibraryVK::CreatePipeline( +std::unique_ptr PipelineLibraryVK::CreatePipeline( const PipelineDescriptor& desc) { TRACE_EVENT0("flutter", __FUNCTION__); vk::GraphicsPipelineCreateInfo pipeline_info; @@ -239,7 +298,7 @@ std::unique_ptr PipelineLibraryVK::CreatePipeline( blend_state.setAttachments(attachment_blend_state); pipeline_info.setPColorBlendState(&blend_state); - auto render_pass = CreateRenderPass(device_, desc); + auto render_pass = CreateRenderPass(desc); if (render_pass) { pipeline_info.setBasePipelineHandle(VK_NULL_HANDLE); pipeline_info.setSubpass(0); @@ -282,31 +341,33 @@ std::unique_ptr PipelineLibraryVK::CreatePipeline( //---------------------------------------------------------------------------- /// Pipeline Layout a.k.a the descriptor sets and uniforms. /// - std::vector desc_bindings; + std::vector bindings = {}; for (auto layout : desc.GetVertexDescriptor()->GetDescriptorSetLayouts()) { auto vk_desc_layout = ToVKDescriptorSetLayoutBinding(layout); - desc_bindings.push_back(vk_desc_layout); + bindings.push_back(vk_desc_layout); } - vk::DescriptorSetLayoutCreateInfo descs_layout_info; - descs_layout_info.setBindings(desc_bindings); + vk::DescriptorSetLayoutCreateInfo descriptor_set_create; + descriptor_set_create.setBindings(bindings); - auto [descs_result, descs_layout] = - device_.createDescriptorSetLayoutUnique(descs_layout_info); - if (descs_result != vk::Result::eSuccess) { + auto descriptor_set_create_res = + device_.createDescriptorSetLayoutUnique(descriptor_set_create); + if (descriptor_set_create_res.result != vk::Result::eSuccess) { VALIDATION_LOG << "unable to create uniform descriptors"; return nullptr; } - ContextVK::SetDebugName(device_, descs_layout.get(), - "Descriptor Set Layout " + desc.GetLabel()); + vk::UniqueDescriptorSetLayout descriptor_set_layout = + std::move(descriptor_set_create_res.value); + ContextVK::SetDebugName(device_, descriptor_set_layout.get(), + "Descriptor Set Layout" + desc.GetLabel()); //---------------------------------------------------------------------------- /// Create the pipeline layout. /// vk::PipelineLayoutCreateInfo pipeline_layout_info; - pipeline_layout_info.setSetLayouts(descs_layout.get()); + pipeline_layout_info.setSetLayouts(descriptor_set_layout.get()); auto pipeline_layout = device_.createPipelineLayoutUnique(pipeline_layout_info); if (pipeline_layout.result != vk::Result::eSuccess) { @@ -341,81 +402,13 @@ std::unique_ptr PipelineLibraryVK::CreatePipeline( } ContextVK::SetDebugName(device_, *pipeline_layout.value, - "Pipeline Layout " + desc.GetLabel()); + "Pipeline Layout" + desc.GetLabel()); ContextVK::SetDebugName(device_, *pipeline.value, - "Pipeline " + desc.GetLabel()); - - return std::make_unique(weak_from_this(), // - desc, // - std::move(pipeline.value), // - std::move(render_pass), // - std::move(pipeline_layout.value), // - std::move(descs_layout) // - ); -} + "Pipeline" + desc.GetLabel()); -// |PipelineLibrary| -PipelineFuture PipelineLibraryVK::GetPipeline( - PipelineDescriptor descriptor) { - Lock lock(pipelines_mutex_); - if (auto found = pipelines_.find(descriptor); found != pipelines_.end()) { - return found->second; - } - - if (!IsValid()) { - return { - descriptor, - RealizedFuture>>(nullptr)}; - } - - auto promise = std::make_shared< - std::promise>>>(); - auto pipeline_future = - PipelineFuture{descriptor, promise->get_future()}; - pipelines_[descriptor] = pipeline_future; - - auto weak_this = weak_from_this(); - - worker_task_runner_->PostTask([descriptor, weak_this, promise]() { - auto thiz = weak_this.lock(); - if (!thiz) { - promise->set_value(nullptr); - VALIDATION_LOG << "Pipeline library was collected before the pipeline " - "could be created."; - return; - } - - auto pipeline = PipelineLibraryVK::Cast(*thiz).CreatePipeline(descriptor); - if (!pipeline) { - promise->set_value(nullptr); - VALIDATION_LOG << "Could not create pipeline: " << descriptor.GetLabel(); - return; - } - - promise->set_value(std::move(pipeline)); - }); - - return pipeline_future; -} - -// |PipelineLibrary| -PipelineFuture PipelineLibraryVK::GetPipeline( - ComputePipelineDescriptor descriptor) { - auto promise = std::make_shared< - std::promise>>>(); - promise->set_value(nullptr); - return {descriptor, promise->get_future()}; -} - -// |PipelineLibrary| -void PipelineLibraryVK::RemovePipelinesWithEntryPoint( - std::shared_ptr function) { - Lock lock(pipelines_mutex_); - - fml::erase_if(pipelines_, [&](auto item) { - return item->first.GetEntrypointForStage(function->GetStage()) - ->IsEqual(*function); - }); + return std::make_unique( + std::move(pipeline.value), std::move(render_pass), + std::move(pipeline_layout.value), std::move(descriptor_set_layout)); } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/pipeline_library_vk.h b/impeller/renderer/backend/vulkan/pipeline_library_vk.h index 6892ac126d17b..f4cd10b76ffd8 100644 --- a/impeller/renderer/backend/vulkan/pipeline_library_vk.h +++ b/impeller/renderer/backend/vulkan/pipeline_library_vk.h @@ -62,7 +62,10 @@ class PipelineLibraryVK final void RemovePipelinesWithEntryPoint( std::shared_ptr function) override; - std::unique_ptr CreatePipeline(const PipelineDescriptor& desc); + std::unique_ptr CreatePipeline( + const PipelineDescriptor& desc); + + vk::UniqueRenderPass CreateRenderPass(const PipelineDescriptor& desc); FML_DISALLOW_COPY_AND_ASSIGN(PipelineLibraryVK); }; diff --git a/impeller/renderer/backend/vulkan/pipeline_vk.cc b/impeller/renderer/backend/vulkan/pipeline_vk.cc index 208d63ae99fd8..87f65c9c99da6 100644 --- a/impeller/renderer/backend/vulkan/pipeline_vk.cc +++ b/impeller/renderer/backend/vulkan/pipeline_vk.cc @@ -6,40 +6,53 @@ namespace impeller { -PipelineVK::PipelineVK(std::weak_ptr library, - const PipelineDescriptor& desc, - vk::UniquePipeline pipeline, - vk::UniqueRenderPass render_pass, - vk::UniquePipelineLayout layout, - vk::UniqueDescriptorSetLayout descriptor_set_layout) - : Pipeline(std::move(library), desc), - pipeline_(std::move(pipeline)), +PipelineCreateInfoVK::PipelineCreateInfoVK( + vk::UniquePipeline pipeline, + vk::UniqueRenderPass render_pass, + vk::UniquePipelineLayout layout, + vk::UniqueDescriptorSetLayout descriptor_set_layout) + : pipeline_(std::move(pipeline)), render_pass_(std::move(render_pass)), - layout_(std::move(layout)), + pipeline_layout_(std::move(layout)), descriptor_set_layout_(std::move(descriptor_set_layout)) { - is_valid_ = pipeline_ && render_pass_ && layout_ && descriptor_set_layout_; + is_valid_ = + pipeline_ && render_pass_ && pipeline_layout_ && descriptor_set_layout_; } -PipelineVK::~PipelineVK() = default; - -bool PipelineVK::IsValid() const { +bool PipelineCreateInfoVK::IsValid() const { return is_valid_; } -const vk::Pipeline& PipelineVK::GetPipeline() const { +const vk::Pipeline& PipelineCreateInfoVK::GetVKPipeline() const { return *pipeline_; } -const vk::RenderPass& PipelineVK::GetRenderPass() const { +vk::RenderPass PipelineCreateInfoVK::GetRenderPass() const { return *render_pass_; } -const vk::PipelineLayout& PipelineVK::GetPipelineLayout() const { - return *layout_; +vk::PipelineLayout PipelineCreateInfoVK::GetPipelineLayout() const { + return *pipeline_layout_; } -const vk::DescriptorSetLayout& PipelineVK::GetDescriptorSetLayout() const { +vk::DescriptorSetLayout PipelineCreateInfoVK::GetDescriptorSetLayout() const { return *descriptor_set_layout_; } +PipelineVK::PipelineVK(std::weak_ptr library, + const PipelineDescriptor& desc, + std::unique_ptr create_info) + : Pipeline(std::move(library), desc), + pipeline_info_(std::move(create_info)) {} + +PipelineVK::~PipelineVK() = default; + +bool PipelineVK::IsValid() const { + return pipeline_info_->IsValid(); +} + +PipelineCreateInfoVK* PipelineVK::GetCreateInfo() const { + return pipeline_info_.get(); +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/pipeline_vk.h b/impeller/renderer/backend/vulkan/pipeline_vk.h index 7135dcf03eb5f..a10e31e12f176 100644 --- a/impeller/renderer/backend/vulkan/pipeline_vk.h +++ b/impeller/renderer/backend/vulkan/pipeline_vk.h @@ -13,41 +13,51 @@ namespace impeller { +class PipelineCreateInfoVK { + public: + PipelineCreateInfoVK(vk::UniquePipeline pipeline, + vk::UniqueRenderPass render_pass, + vk::UniquePipelineLayout pipeline_layout, + vk::UniqueDescriptorSetLayout descriptor_set_layout); + + bool IsValid() const; + + const vk::Pipeline& GetVKPipeline() const; + + vk::RenderPass GetRenderPass() const; + + vk::PipelineLayout GetPipelineLayout() const; + + vk::DescriptorSetLayout GetDescriptorSetLayout() const; + + private: + bool is_valid_ = false; + vk::UniquePipeline pipeline_; + vk::UniqueRenderPass render_pass_; + vk::UniquePipelineLayout pipeline_layout_; + vk::UniqueDescriptorSetLayout descriptor_set_layout_; +}; + class PipelineVK final : public Pipeline, public BackendCast> { public: PipelineVK(std::weak_ptr library, const PipelineDescriptor& desc, - vk::UniquePipeline pipeline, - vk::UniqueRenderPass render_pass, - vk::UniquePipelineLayout layout, - vk::UniqueDescriptorSetLayout descriptor_set_layout); + std::unique_ptr create_info); // |Pipeline| ~PipelineVK() override; - const vk::Pipeline& GetPipeline() const; - - const vk::RenderPass& GetRenderPass() const; - - const vk::PipelineLayout& GetPipelineLayout() const; - - const vk::DescriptorSetLayout& GetDescriptorSetLayout() const; + PipelineCreateInfoVK* GetCreateInfo() const; private: friend class PipelineLibraryVK; - const vk::UniquePipeline pipeline_; - const vk::UniqueRenderPass render_pass_; - const vk::UniquePipelineLayout layout_; - const vk::UniqueDescriptorSetLayout descriptor_set_layout_; - bool is_valid_ = false; - // |Pipeline| bool IsValid() const override; - std::unique_ptr CreatePipeline(const PipelineDescriptor& desc); + std::unique_ptr pipeline_info_; FML_DISALLOW_COPY_AND_ASSIGN(PipelineVK); }; diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index 091ad5251b127..b929e647e2594 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -6,11 +6,9 @@ #include #include -#include #include -#include "flutter/fml/logging.h" -#include "flutter/fml/trace_event.h" +#include "fml/logging.h" #include "impeller/base/validation.h" #include "impeller/renderer/backend/vulkan/command_encoder_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" @@ -42,9 +40,8 @@ static vk::AttachmentDescription CreateAttachmentDescription( ); } -static SharedHandleVK CreateVKRenderPass( - const vk::Device& device, - const RenderTarget& target) { +static vk::UniqueRenderPass CreateVKRenderPass(const vk::Device& device, + const RenderTarget& target) { std::vector attachments; std::vector color_refs; @@ -111,7 +108,7 @@ static SharedHandleVK CreateVKRenderPass( return {}; } - return MakeSharedVK(std::move(pass)); + return std::move(pass); } RenderPassVK::RenderPassVK(const std::shared_ptr& context, @@ -138,7 +135,7 @@ void RenderPassVK::OnSetLabel(std::string label) { if (!context) { return; } - ContextVK::Cast(*context).SetDebugName(render_pass_->Get(), label.c_str()); + ContextVK::Cast(*context).SetDebugName(*render_pass_, label.c_str()); debug_label_ = std::move(label); } @@ -228,60 +225,34 @@ static vk::UniqueFramebuffer CreateFramebuffer(const vk::Device& device, return std::move(framebuffer); } -static bool ConfigureAttachments(const RenderTarget& target, - const vk::CommandBuffer& command_buffer, - CommandEncoderVK& encoder) { +static bool ConfigureRenderTargetAttachmentLayouts( + const RenderTarget& target, + const vk::CommandBuffer& command_buffer) { for (const auto& [_, color] : target.GetColorAttachments()) { - const auto& color_tex = color.texture; - const auto& color_resolve_tex = color.resolve_texture; - - LayoutTransition color_tran; - color_tran.cmd_buffer = command_buffer; - color_tran.src_access = vk::AccessFlagBits::eColorAttachmentWrite | - vk::AccessFlagBits::eShaderWrite | - vk::AccessFlagBits::eTransferWrite; - color_tran.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput | - vk::PipelineStageFlagBits::eFragmentShader | - vk::PipelineStageFlagBits::eTransfer; - color_tran.dst_access = vk::AccessFlagBits::eShaderRead; - color_tran.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; - - color_tran.new_layout = vk::ImageLayout::eColorAttachmentOptimal; - - // Transition and track the color texture. - if (!TextureVK::Cast(*color_tex).SetLayout(color_tran) || - !encoder.Track(color_tex)) { + if (!TextureVK::Cast(*color.texture) + .SetLayout(vk::ImageLayout::eColorAttachmentOptimal, + command_buffer)) { return false; } - - // Transition and track the resolve texture, if there is one. - if (color_resolve_tex) { - if (!TextureVK::Cast(*color_resolve_tex).SetLayout(color_tran) || - !encoder.Track(color_resolve_tex)) { + if (color.resolve_texture) { + if (!TextureVK::Cast(*color.resolve_texture) + .SetLayout(vk::ImageLayout::eColorAttachmentOptimal, + command_buffer)) { return false; } } } - - LayoutTransition depth_stencil_tran; - depth_stencil_tran.cmd_buffer = command_buffer; - depth_stencil_tran.src_access = {}; - depth_stencil_tran.src_stage = vk::PipelineStageFlagBits::eTopOfPipe; - depth_stencil_tran.dst_access = vk::AccessFlagBits::eShaderRead; - depth_stencil_tran.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; - - depth_stencil_tran.new_layout = vk::ImageLayout::eDepthAttachmentOptimal; if (auto depth = target.GetDepthAttachment(); depth.has_value()) { - if (!TextureVK::Cast(*depth->texture).SetLayout(depth_stencil_tran) || - !encoder.Track(depth->texture)) { + if (!TextureVK::Cast(*depth->texture) + .SetLayout(vk::ImageLayout::eDepthAttachmentOptimal, + command_buffer)) { return false; } } - - depth_stencil_tran.new_layout = vk::ImageLayout::eStencilAttachmentOptimal; if (auto stencil = target.GetStencilAttachment(); stencil.has_value()) { - if (!TextureVK::Cast(*stencil->texture).SetLayout(depth_stencil_tran) || - !encoder.Track(stencil->texture)) { + if (!TextureVK::Cast(*stencil->texture) + .SetLayout(vk::ImageLayout::eStencilAttachmentOptimal, + command_buffer)) { return false; } } @@ -290,19 +261,9 @@ static bool ConfigureAttachments(const RenderTarget& target, static bool UpdateBindingLayouts(const Bindings& bindings, const vk::CommandBuffer& buffer) { - LayoutTransition transition; - transition.cmd_buffer = buffer; - transition.src_access = vk::AccessFlagBits::eColorAttachmentWrite | - vk::AccessFlagBits::eTransferWrite; - transition.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput | - vk::PipelineStageFlagBits::eTransfer; - transition.dst_access = vk::AccessFlagBits::eShaderRead; - transition.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; - - transition.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal; - for (const auto& [_, texture] : bindings.textures) { - if (!TextureVK::Cast(*texture.resource).SetLayout(transition)) { + if (!TextureVK::Cast(*texture.resource) + .SetLayout(vk::ImageLayout::eShaderReadOnlyOptimal, buffer)) { return false; } } @@ -325,124 +286,160 @@ static bool UpdateBindingLayouts(const std::vector& commands, return true; } -static bool AllocateAndBindDescriptorSets(const ContextVK& context, - const Command& command, - CommandEncoderVK& encoder, - const PipelineVK& pipeline) { - auto desc_set = - encoder.AllocateDescriptorSet(pipeline.GetDescriptorSetLayout()); - if (!desc_set) { - return false; - } - - auto& allocator = *context.GetResourceAllocator(); - - std::unordered_map buffers; - std::unordered_map images; +static bool UpdateDescriptorSets(vk::Device device, + const Bindings& bindings, + Allocator& allocator, + vk::DescriptorSet desc_set, + CommandEncoderVK& encoder) { std::vector writes; - auto bind_images = [&encoder, // - &images, // - &writes, // - &desc_set // - ](const Bindings& bindings) -> bool { - for (const auto& [index, sampler_handle] : bindings.samplers) { - if (bindings.textures.find(index) == bindings.textures.end()) { - return false; - } + //---------------------------------------------------------------------------- + /// Setup buffer descriptors. + /// + std::vector buffer_desc; + for (const auto& [buffer_index, view] : bindings.buffers) { + const auto& buffer_view = view.resource.buffer; - auto texture = bindings.textures.at(index).resource; - const auto& texture_vk = TextureVK::Cast(*texture); - const SamplerVK& sampler = SamplerVK::Cast(*sampler_handle.resource); + auto device_buffer = buffer_view->GetDeviceBuffer(allocator); + if (!device_buffer) { + VALIDATION_LOG << "Failed to get device buffer for vertex binding"; + return false; + } - if (!encoder.Track(texture) || - !encoder.Track(sampler.GetSharedSampler())) { - return false; - } + auto buffer = DeviceBufferVK::Cast(*device_buffer).GetVKBufferHandle(); + if (!buffer) { + return false; + } - const SampledImageSlot& slot = bindings.sampled_images.at(index); + // Reserved index used for per-vertex data. + if (buffer_index == VertexDescriptor::kReservedVertexBufferIndex) { + continue; + } - vk::DescriptorImageInfo image_info; - image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal; - image_info.sampler = sampler.GetSampler(); - image_info.imageView = texture_vk.GetImageView(); + if (!encoder.Track(device_buffer)) { + return false; + } - vk::WriteDescriptorSet write_set; - write_set.dstSet = desc_set.value(); - write_set.dstBinding = slot.binding; - write_set.descriptorCount = 1u; - write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler; - write_set.pImageInfo = &(images[slot.binding] = image_info); + uint32_t offset = view.resource.range.offset; - writes.push_back(write_set); - } + vk::DescriptorBufferInfo desc_buffer_info; + desc_buffer_info.setBuffer(buffer); + desc_buffer_info.setOffset(offset); + desc_buffer_info.setRange(view.resource.range.length); + buffer_desc.push_back(desc_buffer_info); - return true; - }; + const ShaderUniformSlot& uniform = bindings.uniforms.at(buffer_index); - auto bind_buffers = [&allocator, // - &encoder, // - &buffers, // - &writes, // - &desc_set // - ](const Bindings& bindings) -> bool { - for (const auto& [buffer_index, view] : bindings.buffers) { - const auto& buffer_view = view.resource.buffer; - - auto device_buffer = buffer_view->GetDeviceBuffer(allocator); - if (!device_buffer) { - VALIDATION_LOG << "Failed to get device buffer for vertex binding"; - return false; - } + vk::WriteDescriptorSet write_set; + write_set.setDstSet(desc_set); + write_set.setDstBinding(uniform.binding); + write_set.setDescriptorCount(1); + write_set.setDescriptorType(vk::DescriptorType::eUniformBuffer); + write_set.setPBufferInfo(&buffer_desc.back()); - auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer(); - if (!buffer) { - return false; - } + writes.push_back(write_set); + } - // Reserved index used for per-vertex data. - if (buffer_index == VertexDescriptor::kReservedVertexBufferIndex) { - continue; - } + //---------------------------------------------------------------------------- + /// Setup image descriptors. + /// + std::vector image_descs; + for (const auto& [index, sampler_handle] : bindings.samplers) { + if (bindings.textures.find(index) == bindings.textures.end()) { + VALIDATION_LOG << "Missing texture for sampler: " << index; + return false; + } - if (!encoder.Track(device_buffer)) { - return false; - } + auto texture = bindings.textures.at(index).resource; + const auto& texture_vk = TextureVK::Cast(*texture); + const SamplerVK& sampler = SamplerVK::Cast(*sampler_handle.resource); - uint32_t offset = view.resource.range.offset; + if (!encoder.Track(texture) || !encoder.Track(sampler.GetSharedSampler())) { + return false; + } - vk::DescriptorBufferInfo buffer_info; - buffer_info.buffer = buffer; - buffer_info.offset = offset; - buffer_info.range = view.resource.range.length; + const SampledImageSlot& slot = bindings.sampled_images.at(index); - const ShaderUniformSlot& uniform = bindings.uniforms.at(buffer_index); + vk::DescriptorImageInfo desc_image_info; + desc_image_info.setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal); + desc_image_info.setSampler(sampler.GetSamplerVK()); + desc_image_info.setImageView(texture_vk.GetImageView()); + image_descs.push_back(desc_image_info); - vk::WriteDescriptorSet write_set; - write_set.dstSet = desc_set.value(); - write_set.dstBinding = uniform.binding; - write_set.descriptorCount = 1u; - write_set.descriptorType = vk::DescriptorType::eUniformBuffer; - write_set.pBufferInfo = &(buffers[uniform.binding] = buffer_info); + vk::WriteDescriptorSet write_set; + write_set.setDstSet(desc_set); + write_set.setDstBinding(slot.binding); + write_set.setDescriptorCount(1); + write_set.setDescriptorType(vk::DescriptorType::eCombinedImageSampler); + write_set.setPImageInfo(&image_descs.back()); - writes.push_back(write_set); - } + writes.push_back(write_set); + } + + if (writes.empty()) { return true; + } + device.updateDescriptorSets(writes, {}); + return true; +} + +static bool AllocateAndBindDescriptorSets( + const ContextVK& context, + const Command& command, + CommandEncoderVK& encoder, + PipelineCreateInfoVK* pipeline_create_info) { + auto& allocator = *context.GetResourceAllocator(); + vk::PipelineLayout pipeline_layout = + pipeline_create_info->GetPipelineLayout(); + + vk::DescriptorSetAllocateInfo alloc_info; + std::array dsls = { + pipeline_create_info->GetDescriptorSetLayout(), }; - if (!bind_buffers(command.vertex_bindings) || - !bind_buffers(command.fragment_bindings) || - !bind_images(command.fragment_bindings)) { + alloc_info.setDescriptorPool(context.GetDescriptorPool()); + alloc_info.setSetLayouts(dsls); + + auto [sets_result, sets] = + context.GetDevice().allocateDescriptorSetsUnique(alloc_info); + if (sets_result != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to allocate descriptor sets: " + << vk::to_string(sets_result); + return false; + } + + const auto set = MakeSharedVK(std::move(sets[0])); + + if (!encoder.Track(set)) { return false; } - context.GetDevice().updateDescriptorSets(writes, {}); + bool update_vertex_descriptors = + UpdateDescriptorSets(context.GetDevice(), // + command.vertex_bindings, // + allocator, // + *set, // + encoder // + ); + if (!update_vertex_descriptors) { + return false; + } + bool update_frag_descriptors = + UpdateDescriptorSets(context.GetDevice(), // + command.fragment_bindings, // + allocator, // + *set, // + encoder // + ); + if (!update_frag_descriptors) { + return false; + } encoder.GetCommandBuffer().bindDescriptorSets( vk::PipelineBindPoint::eGraphics, // bind point - pipeline.GetPipelineLayout(), // layout + pipeline_layout, // layout 0, // first set - {vk::DescriptorSet{*desc_set}}, // sets + {vk::DescriptorSet{*set}}, // sets nullptr // offsets ); return true; @@ -489,18 +486,19 @@ static bool EncodeCommand(const Context& context, const auto& cmd_buffer = encoder.GetCommandBuffer(); - const auto& pipeline_vk = PipelineVK::Cast(*command.pipeline); + auto& pipeline_vk = PipelineVK::Cast(*command.pipeline); + PipelineCreateInfoVK* pipeline_create_info = pipeline_vk.GetCreateInfo(); if (!AllocateAndBindDescriptorSets(ContextVK::Cast(context), // command, // encoder, // - pipeline_vk // + pipeline_create_info // )) { return false; } cmd_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, - pipeline_vk.GetPipeline()); + pipeline_create_info->GetVKPipeline()); // Set the viewport and scissors. SetViewportAndScissor(command, cmd_buffer, target_size); @@ -534,13 +532,15 @@ static bool EncodeCommand(const Context& context, } // Bind the vertex buffer. - auto vertex_buffer_handle = DeviceBufferVK::Cast(*vertex_buffer).GetBuffer(); + auto vertex_buffer_handle = + DeviceBufferVK::Cast(*vertex_buffer).GetVKBufferHandle(); vk::Buffer vertex_buffers[] = {vertex_buffer_handle}; vk::DeviceSize vertex_buffer_offsets[] = {vertex_buffer_view.range.offset}; cmd_buffer.bindVertexBuffers(0u, 1u, vertex_buffers, vertex_buffer_offsets); // Bind the index buffer. - auto index_buffer_handle = DeviceBufferVK::Cast(*index_buffer).GetBuffer(); + auto index_buffer_handle = + DeviceBufferVK::Cast(*index_buffer).GetVKBufferHandle(); cmd_buffer.bindIndexBuffer(index_buffer_handle, index_buffer_view.range.offset, ToVKIndexType(command.index_type)); @@ -556,11 +556,14 @@ static bool EncodeCommand(const Context& context, } bool RenderPassVK::OnEncodeCommands(const Context& context) const { - TRACE_EVENT0("impeller", "RenderPassVK::OnEncodeCommands"); if (!IsValid()) { return false; } + if (commands_.empty()) { + return true; + } + const auto& vk_context = ContextVK::Cast(context); const auto& render_target = GetRenderTarget(); @@ -590,23 +593,16 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { return false; } - if (!ConfigureAttachments(render_target, cmd_buffer, *encoder)) { + if (!ConfigureRenderTargetAttachmentLayouts(render_target, cmd_buffer)) { VALIDATION_LOG << "Could not complete attachment layout transitions."; return false; } - if (commands_.empty()) { - // All the necessary layout transitions of the attchments have been - // completed by this point. If there are no commands, there is nothing - // further to do. - return true; - } - const auto& target_size = render_target.GetRenderTargetSize(); auto framebuffer = MakeSharedVK( CreateFramebuffer(vk_context.GetDevice(), render_target_, *render_pass_)); - if (!encoder->Track(framebuffer) || !encoder->Track(render_pass_)) { + if (!encoder->Track(framebuffer)) { return false; } @@ -621,7 +617,6 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const { pass_info.setClearValues(clear_values); { - TRACE_EVENT0("impeller", "EncodeRenderPassCommands"); cmd_buffer.beginRenderPass(pass_info, vk::SubpassContents::eInline); fml::ScopedCleanupClosure end_render_pass( diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.h b/impeller/renderer/backend/vulkan/render_pass_vk.h index ebb42d15dbafe..eae656062c299 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.h +++ b/impeller/renderer/backend/vulkan/render_pass_vk.h @@ -6,7 +6,6 @@ #include "flutter/fml/macros.h" #include "impeller/renderer/backend/vulkan/context_vk.h" -#include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/backend/vulkan/texture_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/command.h" @@ -23,7 +22,7 @@ class RenderPassVK final : public RenderPass { private: friend class CommandBufferVK; - SharedHandleVK render_pass_; + vk::UniqueRenderPass render_pass_; std::weak_ptr encoder_; std::string debug_label_; bool is_valid_ = false; diff --git a/impeller/renderer/backend/vulkan/sampler_library_vk.cc b/impeller/renderer/backend/vulkan/sampler_library_vk.cc index b62549eb88ad5..149c1ae957d4c 100644 --- a/impeller/renderer/backend/vulkan/sampler_library_vk.cc +++ b/impeller/renderer/backend/vulkan/sampler_library_vk.cc @@ -4,7 +4,6 @@ #include "impeller/renderer/backend/vulkan/sampler_library_vk.h" -#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/sampler_vk.h" @@ -52,11 +51,6 @@ std::shared_ptr SamplerLibraryVK::GetSampler( if (!sampler->IsValid()) { return nullptr; } - - if (!desc.label.empty()) { - ContextVK::SetDebugName(device_, sampler->GetSampler(), desc.label.c_str()); - } - samplers_[desc] = sampler; return sampler; } diff --git a/impeller/renderer/backend/vulkan/sampler_vk.cc b/impeller/renderer/backend/vulkan/sampler_vk.cc index 5b706ce92edca..7d2f9bb5c94d4 100644 --- a/impeller/renderer/backend/vulkan/sampler_vk.cc +++ b/impeller/renderer/backend/vulkan/sampler_vk.cc @@ -14,7 +14,7 @@ SamplerVK::SamplerVK(SamplerDescriptor desc, vk::UniqueSampler sampler) SamplerVK::~SamplerVK() = default; -vk::Sampler SamplerVK::GetSampler() const { +vk::Sampler SamplerVK::GetSamplerVK() const { return *sampler_; } diff --git a/impeller/renderer/backend/vulkan/sampler_vk.h b/impeller/renderer/backend/vulkan/sampler_vk.h index bf78d63a1b271..d0268ced3819a 100644 --- a/impeller/renderer/backend/vulkan/sampler_vk.h +++ b/impeller/renderer/backend/vulkan/sampler_vk.h @@ -22,7 +22,7 @@ class SamplerVK final : public Sampler, public BackendCast { // |Sampler| ~SamplerVK() override; - vk::Sampler GetSampler() const; + vk::Sampler GetSamplerVK() const; const std::shared_ptr>& GetSharedSampler() const; diff --git a/impeller/renderer/backend/vulkan/shared_object_vk.h b/impeller/renderer/backend/vulkan/shared_object_vk.h index fa87547fc9c67..d3c42a50a04ef 100644 --- a/impeller/renderer/backend/vulkan/shared_object_vk.h +++ b/impeller/renderer/backend/vulkan/shared_object_vk.h @@ -25,14 +25,10 @@ class SharedObjectVKT : public SharedObjectVK { explicit SharedObjectVKT(UniqueResource res) : resource_(std::move(res)) {} - operator Resource() const { return Get(); } - - const Resource& Get() const { return *resource_; } + operator Resource() const { return *resource_; } private: UniqueResource resource_; - - FML_DISALLOW_COPY_AND_ASSIGN(SharedObjectVKT); }; template @@ -44,7 +40,4 @@ auto MakeSharedVK( return std::make_shared>(std::move(handle)); } -template -using SharedHandleVK = std::shared_ptr>; - } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/surface_vk.cc b/impeller/renderer/backend/vulkan/surface_vk.cc index 02992a35ebc0f..a1f09a42b3c76 100644 --- a/impeller/renderer/backend/vulkan/surface_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_vk.cc @@ -43,8 +43,9 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( resolve_tex_desc.storage_mode = StorageMode::kDevicePrivate; std::shared_ptr resolve_tex = - std::make_shared(context, // - swapchain_image // + std::make_shared(resolve_tex_desc, // + context, // + swapchain_image // ); if (!resolve_tex) { @@ -64,7 +65,8 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( stencil0_tex.storage_mode = StorageMode::kDeviceTransient; stencil0_tex.type = TextureType::kTexture2D; stencil0_tex.sample_count = SampleCount::kCount4; - stencil0_tex.format = context->GetCapabilities()->GetDefaultStencilFormat(); + stencil0_tex.format = + context->GetDeviceCapabilities().GetDefaultStencilFormat(); stencil0_tex.size = msaa_tex_desc.size; stencil0_tex.usage = static_cast(TextureUsage::kRenderTarget); diff --git a/impeller/renderer/backend/vulkan/swapchain_image_vk.cc b/impeller/renderer/backend/vulkan/swapchain_image_vk.cc index c87797df753ab..843f0b44a8bbd 100644 --- a/impeller/renderer/backend/vulkan/swapchain_image_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain_image_vk.cc @@ -6,22 +6,25 @@ namespace impeller { -SwapchainImageVK::SwapchainImageVK(TextureDescriptor desc, - vk::Device device, - vk::Image image) - : TextureSourceVK(desc), image_(image) { +SwapchainImageVK::SwapchainImageVK(vk::Device device, + vk::Image image, + PixelFormat image_format, + ISize image_size) + : image_(image), image_format_(image_format), image_size_(image_size) { vk::ImageViewCreateInfo view_info; view_info.image = image_; view_info.viewType = vk::ImageViewType::e2D; - view_info.format = ToVKImageFormat(desc.format); + view_info.format = ToVKImageFormat(image_format_); view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; view_info.subresourceRange.baseMipLevel = 0u; + view_info.subresourceRange.levelCount = 1u; view_info.subresourceRange.baseArrayLayer = 0u; - view_info.subresourceRange.levelCount = desc.mip_count; - view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type); + view_info.subresourceRange.layerCount = 1u; auto [view_result, view] = device.createImageViewUnique(view_info); if (view_result != vk::Result::eSuccess) { + VALIDATION_LOG << "Could not create image view: " + << vk::to_string(view_result); return; } @@ -36,20 +39,20 @@ bool SwapchainImageVK::IsValid() const { } PixelFormat SwapchainImageVK::GetPixelFormat() const { - return desc_.format; + return image_format_; } ISize SwapchainImageVK::GetSize() const { - return desc_.size; + return image_size_; } // |TextureSourceVK| -vk::Image SwapchainImageVK::GetImage() const { +vk::Image SwapchainImageVK::GetVKImage() const { return image_; } // |TextureSourceVK| -vk::ImageView SwapchainImageVK::GetImageView() const { +vk::ImageView SwapchainImageVK::GetVKImageView() const { return image_view_.get(); } diff --git a/impeller/renderer/backend/vulkan/swapchain_image_vk.h b/impeller/renderer/backend/vulkan/swapchain_image_vk.h index db905e834948c..9869b689aaa3d 100644 --- a/impeller/renderer/backend/vulkan/swapchain_image_vk.h +++ b/impeller/renderer/backend/vulkan/swapchain_image_vk.h @@ -14,7 +14,10 @@ namespace impeller { class SwapchainImageVK final : public TextureSourceVK { public: - SwapchainImageVK(TextureDescriptor desc, vk::Device device, vk::Image image); + SwapchainImageVK(vk::Device device, + vk::Image image, + PixelFormat image_format, + ISize image_size); // |TextureSourceVK| ~SwapchainImageVK() override; @@ -26,13 +29,15 @@ class SwapchainImageVK final : public TextureSourceVK { ISize GetSize() const; // |TextureSourceVK| - vk::Image GetImage() const override; + vk::Image GetVKImage() const override; // |TextureSourceVK| - vk::ImageView GetImageView() const override; + vk::ImageView GetVKImageView() const override; private: vk::Image image_ = VK_NULL_HANDLE; + PixelFormat image_format_ = PixelFormat::kUnknown; + ISize image_size_; vk::UniqueImageView image_view_ = {}; bool is_valid_ = false; diff --git a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc b/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc index b4e4f2f899d53..ff40400c657a7 100644 --- a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc @@ -150,7 +150,7 @@ SwapchainImplVK::SwapchainImplVK(const std::shared_ptr& context, } const auto format = ChooseSurfaceFormat( - formats, vk_context.GetCapabilities()->GetDefaultColorFormat()); + formats, vk_context.GetDeviceCapabilities().GetDefaultColorFormat()); if (!format.has_value()) { VALIDATION_LOG << "Swapchain has no supported formats."; return; @@ -213,33 +213,19 @@ SwapchainImplVK::SwapchainImplVK(const std::shared_ptr& context, return; } - TextureDescriptor texture_desc; - texture_desc.usage = - static_cast(TextureUsage::kRenderTarget); - texture_desc.storage_mode = StorageMode::kDevicePrivate; - texture_desc.format = ToPixelFormat(swapchain_info.imageFormat); - texture_desc.size = ISize::MakeWH(swapchain_info.imageExtent.width, - swapchain_info.imageExtent.height); - std::vector> swapchain_images; for (const auto& image : images) { - auto swapchain_image = - std::make_shared(texture_desc, // texture descriptor - vk_context.GetDevice(), // device - image // image - ); + auto swapchain_image = std::make_shared( + vk_context.GetDevice(), // + image, // + ToPixelFormat(swapchain_info.imageFormat), // + ISize::MakeWH(swapchain_info.imageExtent.width, + swapchain_info.imageExtent.height) // + ); if (!swapchain_image->IsValid()) { VALIDATION_LOG << "Could not create swapchain image."; return; } - - ContextVK::SetDebugName( - vk_context.GetDevice(), swapchain_image->GetImage(), - "SwapchainImage" + std::to_string(swapchain_images.size())); - ContextVK::SetDebugName( - vk_context.GetDevice(), swapchain_image->GetImageView(), - "SwapchainImageView" + std::to_string(swapchain_images.size())); - swapchain_images.emplace_back(swapchain_image); } @@ -380,19 +366,24 @@ bool SwapchainImplVK::Present(const std::shared_ptr& image, auto vk_cmd_buffer = CommandBufferVK::Cast(*cmd_buffer).GetEncoder()->GetCommandBuffer(); - - LayoutTransition transition; - transition.new_layout = vk::ImageLayout::ePresentSrcKHR; - transition.cmd_buffer = vk_cmd_buffer; - transition.src_access = vk::AccessFlagBits::eColorAttachmentWrite; - transition.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput; - transition.dst_access = {}; - transition.dst_stage = vk::PipelineStageFlagBits::eBottomOfPipe; - - if (!image->SetLayout(transition)) { - return false; - } - + vk::ImageMemoryBarrier image_barrier; + image_barrier.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite; + image_barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead; + image_barrier.image = image->GetVKImage(); + image_barrier.oldLayout = vk::ImageLayout::eColorAttachmentOptimal; + image_barrier.newLayout = vk::ImageLayout::ePresentSrcKHR; + image_barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; + image_barrier.subresourceRange.baseMipLevel = 0u; + image_barrier.subresourceRange.levelCount = 1u; + image_barrier.subresourceRange.baseArrayLayer = 0u; + image_barrier.subresourceRange.layerCount = 1u; + vk_cmd_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, // + vk::PipelineStageFlagBits::eAllGraphics, // + {}, // + nullptr, // + nullptr, // + image_barrier // + ); if (!cmd_buffer->SubmitCommands()) { return false; } diff --git a/impeller/renderer/backend/vulkan/texture_source_vk.cc b/impeller/renderer/backend/vulkan/texture_source_vk.cc index 25f231565e58e..c411c62489cbf 100644 --- a/impeller/renderer/backend/vulkan/texture_source_vk.cc +++ b/impeller/renderer/backend/vulkan/texture_source_vk.cc @@ -6,59 +6,6 @@ namespace impeller { -TextureSourceVK::TextureSourceVK(TextureDescriptor desc) : desc_(desc) {} - -TextureSourceVK::~TextureSourceVK() = default; - -const TextureDescriptor& TextureSourceVK::GetTextureDescriptor() const { - return desc_; -} - -vk::ImageLayout TextureSourceVK::GetLayout() const { - ReaderLock lock(layout_mutex_); - return layout_; -} - -vk::ImageLayout TextureSourceVK::SetLayoutWithoutEncoding( - vk::ImageLayout layout) const { - WriterLock lock(layout_mutex_); - const auto old_layout = layout_; - layout_ = layout; - return old_layout; -} - -bool TextureSourceVK::SetLayout(const LayoutTransition& transition) const { - const auto old_layout = SetLayoutWithoutEncoding(transition.new_layout); - if (transition.new_layout == old_layout) { - return true; - } - - vk::ImageMemoryBarrier image_barrier; - image_barrier.srcAccessMask = transition.src_access; - image_barrier.dstAccessMask = transition.dst_access; - image_barrier.oldLayout = old_layout; - image_barrier.newLayout = transition.new_layout; - image_barrier.image = GetImage(); - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.subresourceRange.aspectMask = - ToImageAspectFlags(transition.new_layout); - image_barrier.subresourceRange.baseMipLevel = 0u; - image_barrier.subresourceRange.levelCount = desc_.mip_count; - image_barrier.subresourceRange.baseArrayLayer = 0u; - image_barrier.subresourceRange.layerCount = ToArrayLayerCount(desc_.type); - - transition.cmd_buffer.pipelineBarrier(transition.src_stage, // src stage - transition.dst_stage, // dst stage - {}, // dependency flags - nullptr, // memory barriers - nullptr, // buffer barriers - image_barrier // image barriers - ); - - return true; -} - bool TextureSourceVK::SetContents(const TextureDescriptor& desc, const uint8_t* contents, size_t length, diff --git a/impeller/renderer/backend/vulkan/texture_source_vk.h b/impeller/renderer/backend/vulkan/texture_source_vk.h index 4b65739427c9b..5fac2ce93980c 100644 --- a/impeller/renderer/backend/vulkan/texture_source_vk.h +++ b/impeller/renderer/backend/vulkan/texture_source_vk.h @@ -5,8 +5,6 @@ #pragma once #include "flutter/fml/macros.h" -#include "impeller/base/thread.h" -#include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/texture_descriptor.h" @@ -14,34 +12,16 @@ namespace impeller { class TextureSourceVK { public: - virtual ~TextureSourceVK(); - - const TextureDescriptor& GetTextureDescriptor() const; + virtual ~TextureSourceVK() = default; virtual bool SetContents(const TextureDescriptor& desc, const uint8_t* contents, size_t length, size_t slice); - virtual vk::Image GetImage() const = 0; - - virtual vk::ImageView GetImageView() const = 0; - - bool SetLayout(const LayoutTransition& transition) const; - - vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const; - - vk::ImageLayout GetLayout() const; - - protected: - const TextureDescriptor desc_; - - explicit TextureSourceVK(TextureDescriptor desc); + virtual vk::Image GetVKImage() const = 0; - private: - mutable RWMutex layout_mutex_; - mutable vk::ImageLayout layout_ IPLR_GUARDED_BY(layout_mutex_) = - vk::ImageLayout::eUndefined; + virtual vk::ImageView GetVKImageView() const = 0; }; } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/texture_vk.cc b/impeller/renderer/backend/vulkan/texture_vk.cc index cc8c57280cc19..70c048e1f459f 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.cc +++ b/impeller/renderer/backend/vulkan/texture_vk.cc @@ -4,17 +4,12 @@ #include "impeller/renderer/backend/vulkan/texture_vk.h" -#include "impeller/renderer/backend/vulkan/command_buffer_vk.h" -#include "impeller/renderer/backend/vulkan/command_encoder_vk.h" -#include "impeller/renderer/backend/vulkan/formats_vk.h" - namespace impeller { -TextureVK::TextureVK(std::weak_ptr context, +TextureVK::TextureVK(TextureDescriptor desc, + std::weak_ptr context, std::shared_ptr source) - : Texture(source->GetTextureDescriptor()), - context_(std::move(context)), - source_(std::move(source)) {} + : Texture(desc), context_(std::move(context)), source_(std::move(source)) {} TextureVK::~TextureVK() = default; @@ -25,7 +20,6 @@ void TextureVK::SetLabel(std::string_view label) { return; } ContextVK::Cast(*context).SetDebugName(GetImage(), label); - ContextVK::Cast(*context).SetDebugName(GetImageView(), label); } bool TextureVK::OnSetContents(const uint8_t* contents, @@ -39,74 +33,11 @@ bool TextureVK::OnSetContents(const uint8_t* contents, // Out of bounds access. if (length != desc.GetByteSizeOfBaseMipLevel()) { - VALIDATION_LOG << "Illegal to set contents for invalid size."; - return false; - } - - auto context = context_.lock(); - if (!context) { - VALIDATION_LOG << "Context died before setting contents on texture."; - return false; - } - - auto staging_buffer = - context->GetResourceAllocator()->CreateBufferWithCopy(contents, length); - - if (!staging_buffer) { - VALIDATION_LOG << "Could not create staging buffer."; - return false; - } - - auto cmd_buffer = context->CreateCommandBuffer(); - - if (!cmd_buffer) { - return false; - } - - const auto encoder = CommandBufferVK::Cast(*cmd_buffer).GetEncoder(); - - if (!encoder->Track(staging_buffer) || !encoder->Track(source_)) { - return false; - } - - const auto& vk_cmd_buffer = encoder->GetCommandBuffer(); - - LayoutTransition transition; - transition.cmd_buffer = vk_cmd_buffer; - transition.new_layout = vk::ImageLayout::eTransferDstOptimal; - transition.src_access = {}; - transition.src_stage = vk::PipelineStageFlagBits::eTopOfPipe; - transition.dst_access = vk::AccessFlagBits::eTransferWrite; - transition.dst_stage = vk::PipelineStageFlagBits::eTransfer; - - if (!SetLayout(transition)) { + VALIDATION_LOG << "illegal to set contents for invalid size"; return false; } - vk::BufferImageCopy copy; - copy.bufferOffset = 0u; - copy.bufferRowLength = 0u; // 0u means tightly packed per spec. - copy.bufferImageHeight = 0u; // 0u means tightly packed per spec. - copy.imageOffset.x = 0u; - copy.imageOffset.y = 0u; - copy.imageOffset.z = 0u; - copy.imageExtent.width = desc.size.width; - copy.imageExtent.height = desc.size.height; - copy.imageExtent.depth = 1u; - copy.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor; - copy.imageSubresource.mipLevel = 0u; - copy.imageSubresource.baseArrayLayer = slice; - copy.imageSubresource.layerCount = 1u; - - vk_cmd_buffer.copyBufferToImage( - DeviceBufferVK::Cast(*staging_buffer).GetBuffer(), // src buffer - GetImage(), // dst image - transition.new_layout, // dst image layout - 1u, // region count - © // regions - ); - - return cmd_buffer->SubmitCommands(); + return source_->SetContents(desc, contents, length, slice); } bool TextureVK::OnSetContents(std::shared_ptr mapping, @@ -125,29 +56,75 @@ ISize TextureVK::GetSize() const { } vk::Image TextureVK::GetImage() const { - return source_->GetImage(); + return source_->GetVKImage(); } vk::ImageView TextureVK::GetImageView() const { - return source_->GetImageView(); + return source_->GetVKImageView(); } -std::shared_ptr TextureVK::GetTextureSource() const { - return source_; +static constexpr vk::ImageAspectFlags ToImageAspectFlags( + vk::ImageLayout layout) { + switch (layout) { + case vk::ImageLayout::eColorAttachmentOptimal: + case vk::ImageLayout::eShaderReadOnlyOptimal: + return vk::ImageAspectFlagBits::eColor; + case vk::ImageLayout::eDepthAttachmentOptimal: + return vk::ImageAspectFlagBits::eDepth; + case vk::ImageLayout::eStencilAttachmentOptimal: + return vk::ImageAspectFlagBits::eStencil; + default: + FML_DLOG(INFO) << "Unknown layout to determine aspect."; + return vk::ImageAspectFlagBits::eNone; + } + FML_UNREACHABLE(); } -bool TextureVK::SetLayout(const LayoutTransition& transition) const { - return source_ ? source_->SetLayout(transition) : false; +vk::ImageLayout TextureVK::GetLayout() const { + ReaderLock lock(layout_mutex_); + return layout_; } vk::ImageLayout TextureVK::SetLayoutWithoutEncoding( vk::ImageLayout layout) const { - return source_ ? source_->SetLayoutWithoutEncoding(layout) - : vk::ImageLayout::eUndefined; + WriterLock lock(layout_mutex_); + const auto old_layout = layout_; + layout_ = layout; + return old_layout; } -vk::ImageLayout TextureVK::GetLayout() const { - return source_ ? source_->GetLayout() : vk::ImageLayout::eUndefined; +bool TextureVK::SetLayout(vk::ImageLayout new_layout, + const vk::CommandBuffer& buffer) const { + const auto old_layout = SetLayoutWithoutEncoding(new_layout); + if (new_layout == old_layout) { + return true; + } + + vk::ImageMemoryBarrier image_barrier; + image_barrier.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | + vk::AccessFlagBits::eTransferWrite; + image_barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | + vk::AccessFlagBits::eShaderRead; + image_barrier.oldLayout = old_layout; + image_barrier.newLayout = new_layout; + image_barrier.image = GetImage(); + image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_barrier.subresourceRange.aspectMask = ToImageAspectFlags(new_layout); + image_barrier.subresourceRange.baseMipLevel = 0u; + image_barrier.subresourceRange.levelCount = GetTextureDescriptor().mip_count; + image_barrier.subresourceRange.baseArrayLayer = 0u; + image_barrier.subresourceRange.layerCount = 1u; + + buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, // src stage + vk::PipelineStageFlagBits::eAllGraphics, // dst stage + {}, // dependency flags + nullptr, // memory barriers + nullptr, // buffer barriers + image_barrier // image barriers + ); + + return true; } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/texture_vk.h b/impeller/renderer/backend/vulkan/texture_vk.h index 5128c2fd66ad5..8ab9a00d27aa3 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.h +++ b/impeller/renderer/backend/vulkan/texture_vk.h @@ -8,9 +8,9 @@ #include "flutter/fml/macros.h" #include "impeller/base/backend_cast.h" +#include "impeller/base/thread.h" #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" -#include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/texture_source_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/texture.h" @@ -19,7 +19,8 @@ namespace impeller { class TextureVK final : public Texture, public BackendCast { public: - TextureVK(std::weak_ptr context, + TextureVK(TextureDescriptor desc, + std::weak_ptr context, std::shared_ptr source); // |Texture| @@ -29,14 +30,12 @@ class TextureVK final : public Texture, public BackendCast { vk::ImageView GetImageView() const; - bool SetLayout(const LayoutTransition& transition) const; + bool SetLayout(vk::ImageLayout layout, const vk::CommandBuffer& buffer) const; vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const; vk::ImageLayout GetLayout() const; - std::shared_ptr GetTextureSource() const; - private: std::weak_ptr context_; std::shared_ptr source_; diff --git a/impeller/renderer/capabilities.cc b/impeller/renderer/capabilities.cc deleted file mode 100644 index b7e6b944211c2..0000000000000 --- a/impeller/renderer/capabilities.cc +++ /dev/null @@ -1,159 +0,0 @@ -// 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 "impeller/renderer/capabilities.h" - -namespace impeller { - -Capabilities::Capabilities() = default; - -Capabilities::~Capabilities() = default; - -class StandardCapabilities final : public Capabilities { - public: - // |Capabilities| - ~StandardCapabilities() override = default; - - // |Capabilities| - bool HasThreadingRestrictions() const override { - return has_threading_restrictions_; - } - - // |Capabilities| - bool SupportsOffscreenMSAA() const override { - return supports_offscreen_msaa_; - } - - // |Capabilities| - bool SupportsSSBO() const override { return supports_ssbo_; } - - // |Capabilities| - bool SupportsTextureToTextureBlits() const override { - return supports_texture_to_texture_blits_; - } - - // |Capabilities| - bool SupportsFramebufferFetch() const override { - return supports_framebuffer_fetch_; - } - - // |Capabilities| - bool SupportsCompute() const override { return supports_compute_; } - - // |Capabilities| - bool SupportsComputeSubgroups() const override { - return supports_compute_subgroups_; - } - - // |Capabilities| - PixelFormat GetDefaultColorFormat() const override { - return default_color_format_; - } - - // |Capabilities| - PixelFormat GetDefaultStencilFormat() const override { - return default_stencil_format_; - } - - private: - StandardCapabilities(bool has_threading_restrictions, - bool supports_offscreen_msaa, - bool supports_ssbo, - bool supports_texture_to_texture_blits, - bool supports_framebuffer_fetch, - bool supports_compute, - bool supports_compute_subgroups, - PixelFormat default_color_format, - PixelFormat default_stencil_format) - : has_threading_restrictions_(has_threading_restrictions), - supports_offscreen_msaa_(supports_offscreen_msaa), - supports_ssbo_(supports_ssbo), - supports_texture_to_texture_blits_(supports_texture_to_texture_blits), - supports_framebuffer_fetch_(supports_framebuffer_fetch), - supports_compute_(supports_compute), - supports_compute_subgroups_(supports_compute_subgroups), - default_color_format_(default_color_format), - default_stencil_format_(default_stencil_format) {} - - friend class CapabilitiesBuilder; - - bool has_threading_restrictions_ = false; - bool supports_offscreen_msaa_ = false; - bool supports_ssbo_ = false; - bool supports_texture_to_texture_blits_ = false; - bool supports_framebuffer_fetch_ = false; - bool supports_compute_ = false; - bool supports_compute_subgroups_ = false; - PixelFormat default_color_format_ = PixelFormat::kUnknown; - PixelFormat default_stencil_format_ = PixelFormat::kUnknown; - - FML_DISALLOW_COPY_AND_ASSIGN(StandardCapabilities); -}; - -CapabilitiesBuilder::CapabilitiesBuilder() = default; - -CapabilitiesBuilder::~CapabilitiesBuilder() = default; - -CapabilitiesBuilder& CapabilitiesBuilder::SetHasThreadingRestrictions( - bool value) { - has_threading_restrictions_ = value; - return *this; -} - -CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsOffscreenMSAA(bool value) { - supports_offscreen_msaa_ = value; - return *this; -} - -CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsSSBO(bool value) { - supports_ssbo_ = value; - return *this; -} - -CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsTextureToTextureBlits( - bool value) { - supports_texture_to_texture_blits_ = value; - return *this; -} - -CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsFramebufferFetch( - bool value) { - supports_framebuffer_fetch_ = value; - return *this; -} - -CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsCompute(bool compute, - bool subgroups) { - supports_compute_ = compute; - supports_compute_subgroups_ = subgroups; - return *this; -} - -CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultColorFormat( - PixelFormat value) { - default_color_format_ = value; - return *this; -} - -CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultStencilFormat( - PixelFormat value) { - default_stencil_format_ = value; - return *this; -} - -std::unique_ptr CapabilitiesBuilder::Build() { - return std::unique_ptr(new StandardCapabilities( // - has_threading_restrictions_, // - supports_offscreen_msaa_, // - supports_ssbo_, // - supports_texture_to_texture_blits_, // - supports_framebuffer_fetch_, // - supports_compute_, // - supports_compute_subgroups_, // - *default_color_format_, // - *default_stencil_format_ // - )); -} - -} // namespace impeller diff --git a/impeller/renderer/capabilities.h b/impeller/renderer/capabilities.h deleted file mode 100644 index 945e9fde3fbc2..0000000000000 --- a/impeller/renderer/capabilities.h +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -#pragma once - -#include - -#include "flutter/fml/macros.h" -#include "impeller/renderer/formats.h" - -namespace impeller { - -class Capabilities { - public: - virtual ~Capabilities(); - - virtual bool HasThreadingRestrictions() const = 0; - - virtual bool SupportsOffscreenMSAA() const = 0; - - virtual bool SupportsSSBO() const = 0; - - virtual bool SupportsTextureToTextureBlits() const = 0; - - virtual bool SupportsFramebufferFetch() const = 0; - - virtual bool SupportsCompute() const = 0; - - virtual bool SupportsComputeSubgroups() const = 0; - - virtual PixelFormat GetDefaultColorFormat() const = 0; - - virtual PixelFormat GetDefaultStencilFormat() const = 0; - - protected: - Capabilities(); - - FML_DISALLOW_COPY_AND_ASSIGN(Capabilities); -}; - -class CapabilitiesBuilder { - public: - CapabilitiesBuilder(); - - ~CapabilitiesBuilder(); - - CapabilitiesBuilder& SetHasThreadingRestrictions(bool value); - - CapabilitiesBuilder& SetSupportsOffscreenMSAA(bool value); - - CapabilitiesBuilder& SetSupportsSSBO(bool value); - - CapabilitiesBuilder& SetSupportsTextureToTextureBlits(bool value); - - CapabilitiesBuilder& SetSupportsFramebufferFetch(bool value); - - CapabilitiesBuilder& SetSupportsCompute(bool compute, bool subgroups); - - CapabilitiesBuilder& SetDefaultColorFormat(PixelFormat value); - - CapabilitiesBuilder& SetDefaultStencilFormat(PixelFormat value); - - std::unique_ptr Build(); - - private: - bool has_threading_restrictions_ = false; - bool supports_offscreen_msaa_ = false; - bool supports_ssbo_ = false; - bool supports_texture_to_texture_blits_ = false; - bool supports_framebuffer_fetch_ = false; - bool supports_compute_ = false; - bool supports_compute_subgroups_ = false; - std::optional default_color_format_ = std::nullopt; - std::optional default_stencil_format_ = std::nullopt; - - FML_DISALLOW_COPY_AND_ASSIGN(CapabilitiesBuilder); -}; - -} // namespace impeller diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc index f5305f278da57..1b93ae66ec243 100644 --- a/impeller/renderer/compute_subgroup_unittests.cc +++ b/impeller/renderer/compute_subgroup_unittests.cc @@ -39,7 +39,7 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups()); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups()); auto cmd_buffer = context->CreateCommandBuffer(); auto pass = cmd_buffer->CreateComputePass(); @@ -258,7 +258,7 @@ TEST_P(ComputeTest, QuadsToPolyline) { using QS = QuadPolylineComputeShader; auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups()); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups()); auto cmd_buffer = context->CreateCommandBuffer(); auto pass = cmd_buffer->CreateComputePass(); diff --git a/impeller/renderer/compute_unittests.cc b/impeller/renderer/compute_unittests.cc index 62ddeadb44b49..ffed4bd7e8502 100644 --- a/impeller/renderer/compute_unittests.cc +++ b/impeller/renderer/compute_unittests.cc @@ -28,7 +28,7 @@ TEST_P(ComputeTest, CanCreateComputePass) { using CS = SampleComputeShader; auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsCompute()); using SamplePipelineBuilder = ComputePipelineBuilder; auto pipeline_desc = @@ -111,7 +111,7 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) { auto context = GetContext(); ASSERT_TRUE(context); - ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsCompute()); auto pipeline_desc_1 = Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context); diff --git a/impeller/renderer/context.cc b/impeller/renderer/context.cc index 1525dfc1bf0f9..9d8aad55e681a 100644 --- a/impeller/renderer/context.cc +++ b/impeller/renderer/context.cc @@ -14,8 +14,8 @@ std::shared_ptr Context::GetGPUTracer() const { return nullptr; } -bool Context::UpdateOffscreenLayerPixelFormat(PixelFormat format) { - return false; +PixelFormat Context::GetColorAttachmentPixelFormat() const { + return GetDeviceCapabilities().GetDefaultColorFormat(); } } // namespace impeller diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index f78d2e3d00f12..a6a485c3e6de3 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -8,7 +8,7 @@ #include #include "flutter/fml/macros.h" -#include "impeller/renderer/capabilities.h" +#include "impeller/renderer/device_capabilities.h" #include "impeller/renderer/formats.h" namespace impeller { @@ -27,11 +27,9 @@ class Context : public std::enable_shared_from_this { virtual bool IsValid() const = 0; - virtual const std::shared_ptr& GetCapabilities() - const = 0; - - virtual bool UpdateOffscreenLayerPixelFormat(PixelFormat format); - + //---------------------------------------------------------------------------- + /// @return A resource allocator. + /// virtual std::shared_ptr GetResourceAllocator() const = 0; virtual std::shared_ptr GetShaderLibrary() const = 0; @@ -44,8 +42,15 @@ class Context : public std::enable_shared_from_this { virtual std::shared_ptr GetWorkQueue() const = 0; + //---------------------------------------------------------------------------- + /// @return A GPU Tracer to trace gpu rendering. + /// virtual std::shared_ptr GetGPUTracer() const; + virtual PixelFormat GetColorAttachmentPixelFormat() const; + + virtual const IDeviceCapabilities& GetDeviceCapabilities() const = 0; + protected: Context(); diff --git a/impeller/renderer/descriptor_set_layout.h b/impeller/renderer/descriptor_set_layout.h new file mode 100644 index 0000000000000..d853f0a663086 --- /dev/null +++ b/impeller/renderer/descriptor_set_layout.h @@ -0,0 +1,27 @@ +// 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. + +#pragma once + +#include +#include + +#include "flutter/fml/macros.h" +#include "impeller/renderer/shader_types.h" + +namespace impeller { + +enum class DescriptorType { + kSampledImage, + kUniformBuffer, +}; + +struct DescriptorSetLayout { + uint32_t binding; + DescriptorType descriptor_type; + uint32_t descriptor_count; + ShaderStage shader_stage; +}; + +} // namespace impeller diff --git a/impeller/renderer/device_capabilities.cc b/impeller/renderer/device_capabilities.cc new file mode 100644 index 0000000000000..bf88bbc4c5f6b --- /dev/null +++ b/impeller/renderer/device_capabilities.cc @@ -0,0 +1,141 @@ +// 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 "impeller/renderer/device_capabilities.h" +#include "device_capabilities.h" + +namespace impeller { + +IDeviceCapabilities::IDeviceCapabilities(bool has_threading_restrictions, + bool supports_offscreen_msaa, + bool supports_ssbo, + bool supports_texture_to_texture_blits, + bool supports_framebuffer_fetch, + PixelFormat default_color_format, + PixelFormat default_stencil_format, + bool supports_compute, + bool supports_compute_subgroups) + : has_threading_restrictions_(has_threading_restrictions), + supports_offscreen_msaa_(supports_offscreen_msaa), + supports_ssbo_(supports_ssbo), + supports_texture_to_texture_blits_(supports_texture_to_texture_blits), + supports_framebuffer_fetch_(supports_framebuffer_fetch), + default_color_format_(default_color_format), + default_stencil_format_(default_stencil_format), + supports_compute_(supports_compute), + supports_compute_subgroups_(supports_compute_subgroups) {} + +IDeviceCapabilities::~IDeviceCapabilities() = default; + +bool IDeviceCapabilities::HasThreadingRestrictions() const { + return has_threading_restrictions_; +} + +bool IDeviceCapabilities::SupportsOffscreenMSAA() const { + return supports_offscreen_msaa_; +} + +bool IDeviceCapabilities::SupportsSSBO() const { + return supports_ssbo_; +} + +bool IDeviceCapabilities::SupportsTextureToTextureBlits() const { + return supports_texture_to_texture_blits_; +} + +bool IDeviceCapabilities::SupportsFramebufferFetch() const { + return supports_framebuffer_fetch_; +} + +PixelFormat IDeviceCapabilities::GetDefaultColorFormat() const { + return default_color_format_; +} + +PixelFormat IDeviceCapabilities::GetDefaultStencilFormat() const { + return default_stencil_format_; +} + +bool IDeviceCapabilities::SupportsCompute() const { + return supports_compute_; +} + +bool IDeviceCapabilities::SupportsComputeSubgroups() const { + return supports_compute_subgroups_; +} + +DeviceCapabilitiesBuilder::DeviceCapabilitiesBuilder() = default; + +DeviceCapabilitiesBuilder::~DeviceCapabilitiesBuilder() = default; + +DeviceCapabilitiesBuilder& +DeviceCapabilitiesBuilder::SetHasThreadingRestrictions(bool value) { + has_threading_restrictions_ = value; + return *this; +} + +DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetSupportsOffscreenMSAA( + bool value) { + supports_offscreen_msaa_ = value; + return *this; +} + +DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetSupportsSSBO( + bool value) { + supports_ssbo_ = value; + return *this; +} + +DeviceCapabilitiesBuilder& +DeviceCapabilitiesBuilder::SetSupportsTextureToTextureBlits(bool value) { + supports_texture_to_texture_blits_ = value; + return *this; +} + +DeviceCapabilitiesBuilder& +DeviceCapabilitiesBuilder::SetSupportsFramebufferFetch(bool value) { + supports_framebuffer_fetch_ = value; + return *this; +} + +DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetDefaultColorFormat( + PixelFormat value) { + default_color_format_ = value; + return *this; +} + +DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetDefaultStencilFormat( + PixelFormat value) { + default_stencil_format_ = value; + return *this; +} + +DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetSupportsCompute( + bool value, + bool subgroups) { + supports_compute_ = value; + supports_compute_subgroups_ = subgroups; + return *this; +} + +std::unique_ptr DeviceCapabilitiesBuilder::Build() { + FML_CHECK(default_color_format_.has_value()) + << "Default color format not set"; + FML_CHECK(default_stencil_format_.has_value()) + << "Default stencil format not set"; + + IDeviceCapabilities* capabilities = new IDeviceCapabilities( // + has_threading_restrictions_, // + supports_offscreen_msaa_, // + supports_ssbo_, // + supports_texture_to_texture_blits_, // + supports_framebuffer_fetch_, // + *default_color_format_, // + *default_stencil_format_, // + supports_compute_, // + supports_compute_subgroups_ // + ); + return std::unique_ptr(capabilities); +} + +} // namespace impeller diff --git a/impeller/renderer/device_capabilities.h b/impeller/renderer/device_capabilities.h new file mode 100644 index 0000000000000..f74d95c27f494 --- /dev/null +++ b/impeller/renderer/device_capabilities.h @@ -0,0 +1,99 @@ +// 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. + +#pragma once + +#include + +#include "flutter/fml/macros.h" +#include "impeller/renderer/formats.h" + +namespace impeller { + +class IDeviceCapabilities { + public: + ~IDeviceCapabilities(); + + bool HasThreadingRestrictions() const; + + bool SupportsOffscreenMSAA() const; + + bool SupportsSSBO() const; + + bool SupportsTextureToTextureBlits() const; + + bool SupportsFramebufferFetch() const; + + PixelFormat GetDefaultColorFormat() const; + + PixelFormat GetDefaultStencilFormat() const; + + bool SupportsCompute() const; + bool SupportsComputeSubgroups() const; + + private: + IDeviceCapabilities(bool has_threading_restrictions, + bool supports_offscreen_msaa, + bool supports_ssbo, + bool supports_texture_to_texture_blits, + bool supports_framebuffer_fetch, + PixelFormat default_color_format, + PixelFormat default_stencil_format, + bool supports_compute, + bool supports_compute_subgroups); + + friend class DeviceCapabilitiesBuilder; + + bool has_threading_restrictions_ = false; + bool supports_offscreen_msaa_ = false; + bool supports_ssbo_ = false; + bool supports_texture_to_texture_blits_ = false; + bool supports_framebuffer_fetch_ = false; + PixelFormat default_color_format_; + PixelFormat default_stencil_format_; + bool supports_compute_ = false; + bool supports_compute_subgroups_ = false; + + FML_DISALLOW_COPY_AND_ASSIGN(IDeviceCapabilities); +}; + +class DeviceCapabilitiesBuilder { + public: + DeviceCapabilitiesBuilder(); + + ~DeviceCapabilitiesBuilder(); + + DeviceCapabilitiesBuilder& SetHasThreadingRestrictions(bool value); + + DeviceCapabilitiesBuilder& SetSupportsOffscreenMSAA(bool value); + + DeviceCapabilitiesBuilder& SetSupportsSSBO(bool value); + + DeviceCapabilitiesBuilder& SetSupportsTextureToTextureBlits(bool value); + + DeviceCapabilitiesBuilder& SetSupportsFramebufferFetch(bool value); + + DeviceCapabilitiesBuilder& SetDefaultColorFormat(PixelFormat value); + + DeviceCapabilitiesBuilder& SetDefaultStencilFormat(PixelFormat value); + + DeviceCapabilitiesBuilder& SetSupportsCompute(bool value, bool subgroups); + + std::unique_ptr Build(); + + private: + bool has_threading_restrictions_ = false; + bool supports_offscreen_msaa_ = false; + bool supports_ssbo_ = false; + bool supports_texture_to_texture_blits_ = false; + bool supports_framebuffer_fetch_ = false; + bool supports_compute_ = false; + bool supports_compute_subgroups_ = false; + std::optional default_color_format_ = std::nullopt; + std::optional default_stencil_format_ = std::nullopt; + + FML_DISALLOW_COPY_AND_ASSIGN(DeviceCapabilitiesBuilder); +}; + +} // namespace impeller diff --git a/impeller/renderer/formats.h b/impeller/renderer/formats.h index 79daace56ff96..170a068da607f 100644 --- a/impeller/renderer/formats.h +++ b/impeller/renderer/formats.h @@ -188,10 +188,6 @@ enum class TextureUsage : TextureUsageMask { kRenderTarget = 1 << 2, }; -constexpr bool TextureUsageIsRenderTarget(TextureUsageMask mask) { - return static_cast(TextureUsage::kRenderTarget) & mask; -} - enum class TextureIntent { kUploadFromHost, kRenderToTexture, diff --git a/impeller/renderer/pipeline_builder.h b/impeller/renderer/pipeline_builder.h index c1c3fbb94781c..efaab15e65865 100644 --- a/impeller/renderer/pipeline_builder.h +++ b/impeller/renderer/pipeline_builder.h @@ -117,7 +117,7 @@ struct PipelineBuilder { // Configure the sole color attachments pixel format. This is by // convention. ColorAttachmentDescriptor color0; - color0.format = context.GetCapabilities()->GetDefaultColorFormat(); + color0.format = context.GetColorAttachmentPixelFormat(); color0.blending_enabled = true; desc.SetColorAttachmentDescriptor(0u, color0); } @@ -128,7 +128,7 @@ struct PipelineBuilder { stencil0.stencil_compare = CompareFunction::kEqual; desc.SetStencilAttachmentDescriptors(stencil0); desc.SetStencilPixelFormat( - context.GetCapabilities()->GetDefaultStencilFormat()); + context.GetDeviceCapabilities().GetDefaultStencilFormat()); } return true; diff --git a/impeller/renderer/render_target.cc b/impeller/renderer/render_target.cc index 167a4d3d37b34..aba17fd6532ef 100644 --- a/impeller/renderer/render_target.cc +++ b/impeller/renderer/render_target.cc @@ -210,7 +210,7 @@ RenderTarget RenderTarget::CreateOffscreen( } RenderTarget target; - PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat(); + PixelFormat pixel_format = context.GetColorAttachmentPixelFormat(); TextureDescriptor color_tex0; color_tex0.storage_mode = color_attachment_config.storage_mode; color_tex0.format = pixel_format; @@ -233,7 +233,8 @@ RenderTarget RenderTarget::CreateOffscreen( if (stencil_attachment_config.has_value()) { TextureDescriptor stencil_tex0; stencil_tex0.storage_mode = stencil_attachment_config->storage_mode; - stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); + stencil_tex0.format = + context.GetDeviceCapabilities().GetDefaultStencilFormat(); stencil_tex0.size = size; stencil_tex0.usage = static_cast(TextureUsage::kRenderTarget); @@ -268,7 +269,7 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( } RenderTarget target; - PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat(); + PixelFormat pixel_format = context.GetColorAttachmentPixelFormat(); // Create MSAA color texture. @@ -326,7 +327,8 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( stencil_tex0.storage_mode = stencil_attachment_config->storage_mode; stencil_tex0.type = TextureType::kTexture2DMultisample; stencil_tex0.sample_count = SampleCount::kCount4; - stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); + stencil_tex0.format = + context.GetDeviceCapabilities().GetDefaultStencilFormat(); stencil_tex0.size = size; stencil_tex0.usage = static_cast(TextureUsage::kRenderTarget); diff --git a/impeller/renderer/sampler.h b/impeller/renderer/sampler.h index 41a16f5b74865..2b14d2843c5a3 100644 --- a/impeller/renderer/sampler.h +++ b/impeller/renderer/sampler.h @@ -20,7 +20,7 @@ class Sampler { protected: SamplerDescriptor desc_; - explicit Sampler(SamplerDescriptor desc); + Sampler(SamplerDescriptor desc); private: FML_DISALLOW_COPY_AND_ASSIGN(Sampler); diff --git a/impeller/renderer/shader_types.h b/impeller/renderer/shader_types.h index b29bffd6f1260..400607c1f55f6 100644 --- a/impeller/renderer/shader_types.h +++ b/impeller/renderer/shader_types.h @@ -123,17 +123,6 @@ struct SampledImageSlot { constexpr bool HasSampler() const { return sampler_index < 32u; } }; -enum class DescriptorType { - kSampledImage, - kUniformBuffer, -}; - -struct DescriptorSetLayout { - uint32_t binding; - DescriptorType descriptor_type; - ShaderStage shader_stage; -}; - template struct Padding { private: diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index 7357cec41514c..1f387ee58e05a 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -97,8 +97,9 @@ class MockImpellerContext : public Context { MOCK_CONST_METHOD0(GetGPUTracer, std::shared_ptr()); - MOCK_CONST_METHOD0(GetCapabilities, - const std::shared_ptr&()); + MOCK_CONST_METHOD0(GetColorAttachmentPixelFormat, PixelFormat()); + + MOCK_CONST_METHOD0(GetDeviceCapabilities, const IDeviceCapabilities&()); }; class MockTexture : public Texture { diff --git a/impeller/renderer/vertex_descriptor.h b/impeller/renderer/vertex_descriptor.h index 8d145bb0f503e..dffe6694f7caf 100644 --- a/impeller/renderer/vertex_descriptor.h +++ b/impeller/renderer/vertex_descriptor.h @@ -8,6 +8,7 @@ #include "flutter/fml/macros.h" #include "impeller/base/comparable.h" +#include "impeller/renderer/descriptor_set_layout.h" #include "impeller/renderer/shader_types.h" namespace impeller { diff --git a/impeller/runtime_stage/runtime_stage_unittests.cc b/impeller/runtime_stage/runtime_stage_unittests.cc index d5596afa6748f..896ecab89e824 100644 --- a/impeller/runtime_stage/runtime_stage_unittests.cc +++ b/impeller/runtime_stage/runtime_stage_unittests.cc @@ -242,13 +242,13 @@ TEST_P(RuntimeStageTest, CanCreatePipelineFromRuntimeStage) { ASSERT_TRUE(vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs)); desc.SetVertexDescriptor(std::move(vertex_descriptor)); ColorAttachmentDescriptor color0; - color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat(); + color0.format = GetContext()->GetColorAttachmentPixelFormat(); StencilAttachmentDescriptor stencil0; stencil0.stencil_compare = CompareFunction::kEqual; desc.SetColorAttachmentDescriptor(0u, color0); desc.SetStencilAttachmentDescriptors(stencil0); const auto stencil_fmt = - GetContext()->GetCapabilities()->GetDefaultStencilFormat(); + GetContext()->GetDeviceCapabilities().GetDefaultStencilFormat(); desc.SetStencilPixelFormat(stencil_fmt); auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get(); ASSERT_NE(pipeline, nullptr); diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc index 45c02e5b28b1b..04c4cd84b26c6 100644 --- a/lib/ui/painting/image_decoder_impeller.cc +++ b/lib/ui/painting/image_decoder_impeller.cc @@ -325,7 +325,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr descriptor, // Depending on whether the context has threading restrictions, stay on // the concurrent runner to perform texture upload or move to an IO // runner. - if (context->GetCapabilities()->HasThreadingRestrictions()) { + if (context->GetDeviceCapabilities().HasThreadingRestrictions()) { io_runner->PostTask(upload_texture_and_invoke_result); } else { upload_texture_and_invoke_result(); diff --git a/shell/platform/darwin/ios/ios_surface_metal_impeller.mm b/shell/platform/darwin/ios/ios_surface_metal_impeller.mm index a74343ba1fe26..c1696ff309d70 100644 --- a/shell/platform/darwin/ios/ios_surface_metal_impeller.mm +++ b/shell/platform/darwin/ios/ios_surface_metal_impeller.mm @@ -8,9 +8,8 @@ #include "flutter/impeller/renderer/context.h" #include "flutter/shell/gpu/gpu_surface_metal_impeller.h" -namespace flutter { - -static impeller::PixelFormat InferOffscreenLayerPixelFormat(impeller::PixelFormat pixel_format) { +namespace { +impeller::PixelFormat InferOffscreenLayerPixelFormat(impeller::PixelFormat pixel_format) { switch (pixel_format) { case impeller::PixelFormat::kB10G10R10XR: return impeller::PixelFormat::kB10G10R10A10XR; @@ -18,6 +17,66 @@ return pixel_format; } } +} // namespace + +namespace impeller { +namespace { +// This appears to be the only safe way to override the +// GetColorAttachmentPixelFormat method. It is assumed in the Context that +// there will be one pixel format for the whole app which is not true. So, it +// is unsafe to mutate the Context and you cannot clone the Context at this +// level since the Context does not safely manage the MTLDevice. +class CustomColorAttachmentPixelFormatContext final : public Context { + public: + CustomColorAttachmentPixelFormatContext(const std::shared_ptr& context, + PixelFormat color_attachment_pixel_format) + : context_(context), color_attachment_pixel_format_(color_attachment_pixel_format) {} + + bool IsValid() const override { return context_->IsValid(); } + + std::shared_ptr GetResourceAllocator() const override { + return context_->GetResourceAllocator(); + } + + std::shared_ptr GetShaderLibrary() const override { + return context_->GetShaderLibrary(); + } + + std::shared_ptr GetSamplerLibrary() const override { + return context_->GetSamplerLibrary(); + } + + std::shared_ptr GetPipelineLibrary() const override { + return context_->GetPipelineLibrary(); + } + + std::shared_ptr CreateCommandBuffer() const override { + return context_->CreateCommandBuffer(); + } + + std::shared_ptr GetWorkQueue() const override { return context_->GetWorkQueue(); } + + std::shared_ptr GetGPUTracer() const override { return context_->GetGPUTracer(); } + + PixelFormat GetColorAttachmentPixelFormat() const override { + return color_attachment_pixel_format_; + } + + const IDeviceCapabilities& GetDeviceCapabilities() const override { + return context_->GetDeviceCapabilities(); + } + + private: + std::shared_ptr context_; + PixelFormat color_attachment_pixel_format_; +}; +} // namespace +} // namespace impeller + +namespace flutter { + +using impeller::CustomColorAttachmentPixelFormatContext; +using impeller::FromMTLPixelFormat; IOSSurfaceMetalImpeller::IOSSurfaceMetalImpeller(const fml::scoped_nsobject& layer, const std::shared_ptr& context) @@ -28,8 +87,7 @@ if (!impeller_context_) { return; } - is_valid_ = impeller_context_->UpdateOffscreenLayerPixelFormat( - InferOffscreenLayerPixelFormat(impeller::FromMTLPixelFormat(layer_.get().pixelFormat))); + is_valid_ = true; } // |IOSSurface| @@ -47,8 +105,11 @@ // |IOSSurface| std::unique_ptr IOSSurfaceMetalImpeller::CreateGPUSurface(GrDirectContext*) { - return std::make_unique(this, // - impeller_context_ // + auto context = std::make_shared( + impeller_context_, + InferOffscreenLayerPixelFormat(FromMTLPixelFormat(layer_.get().pixelFormat))); + return std::make_unique(this, // + context // ); } From 3d545ad93eaa700ae94608518bb23525b834b60d Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 13 Mar 2023 09:22:28 -0700 Subject: [PATCH 15/16] [Impeller][Compute] Fix visual issues with heart (#40240) --- impeller/fixtures/cubic_to_quads.comp | 2 +- impeller/fixtures/golden_heart.h | 440 +++++++++--------- impeller/fixtures/stroke.comp | 9 +- .../renderer/compute_subgroup_unittests.cc | 10 +- 4 files changed, 235 insertions(+), 226 deletions(-) diff --git a/impeller/fixtures/cubic_to_quads.comp b/impeller/fixtures/cubic_to_quads.comp index 723e2e3a280bd..4d83d1805d2c3 100644 --- a/impeller/fixtures/cubic_to_quads.comp +++ b/impeller/fixtures/cubic_to_quads.comp @@ -49,7 +49,7 @@ void main() { CubicData cubic = cubics.data[ident]; - vec2 err_v = 3.0 * (cubic.cp2 - cubic.cp1) + cubic.p1 - cubic.p2; + vec2 err_v = (3.0 * cubic.cp2 - cubic.p2) - (3.0 * cubic.cp1 - cubic.p1); float err = dot(err_v, err_v); float quad_count = max(1., ceil(pow(err * (1.0 / max_hypot2), 1. / 6.0))); diff --git a/impeller/fixtures/golden_heart.h b/impeller/fixtures/golden_heart.h index def3f465d4593..2325c1ea6ad0b 100644 --- a/impeller/fixtures/golden_heart.h +++ b/impeller/fixtures/golden_heart.h @@ -71,7 +71,7 @@ std::vector golden_heart_quads = { // easier storage and reading, but still precise enough to work visually. std::vector golden_heart_points = { {140, 20}, {131.765, 20.3023}, {123.672, 21.1078}, - {115.734, 22.4239}, {107.965, 24.2554}, {100.378, 26.6041}, + {115.734, 22.4238}, {107.965, 24.2553}, {100.378, 26.604}, {92.9844, 29.4688}, {85.9188, 32.7537}, {79.1253, 36.4472}, {72.615, 40.5481}, {66.3979, 45.0528}, {60.4823, 49.956}, {54.875, 55.25}, {49.6196, 60.8847}, {44.7551, 66.8194}, @@ -80,242 +80,242 @@ std::vector golden_heart_points = { {22.387, 116.001}, {21.0895, 123.861}, {20.296, 131.865}, {20, 140}, {20.2534, 149.197}, {20.906, 158.214}, {21.9689, 167.034}, {23.4519, 175.646}, {25.3637, 184.033}, - {27.7113, 192.183}, {30.5, 200.083}, {34.1384, 208.814}, - {38.2033, 217.323}, {42.6928, 225.603}, {47.6033, 233.646}, + {27.7113, 192.184}, {30.5, 200.083}, {34.1384, 208.814}, + {38.2033, 217.323}, {42.6928, 225.603}, {47.6032, 233.646}, {52.9299, 241.447}, {58.6667, 249}, {66.101, 257.978}, - {73.9106, 266.793}, {82.0865, 275.443}, {90.6194, 283.929}, + {73.9105, 266.793}, {82.0864, 275.443}, {90.6194, 283.929}, {99.5, 292.25}, {115.262, 306.476}, {131.433, 320.838}, - {148, 335.333}, {160.921, 346.811}, {173.757, 358.715}, - {186.506, 371.032}, {199.167, 383.75}, {207.755, 392.805}, - {216.163, 402.198}, {224.391, 411.923}, {232.439, 421.971}, - {240.309, 432.333}, {248, 443}, {255.407, 432.366}, - {263.018, 422.027}, {270.835, 411.988}, {278.857, 402.258}, - {287.085, 392.843}, {295.519, 383.75}, {308.072, 370.878}, - {320.75, 358.4}, {333.554, 346.326}, {346.481, 334.667}, + {148, 335.333}, {160.921, 346.811}, {173.756, 358.715}, + {186.505, 371.032}, {199.167, 383.75}, {207.755, 392.805}, + {216.162, 402.199}, {224.39, 411.923}, {232.439, 421.971}, + {240.308, 432.333}, {248, 443}, {255.407, 432.367}, + {263.018, 422.027}, {270.834, 411.988}, {278.856, 402.258}, + {287.084, 392.843}, {295.519, 383.75}, {308.072, 370.878}, + {320.751, 358.4}, {333.554, 346.326}, {346.481, 334.667}, {363.181, 319.87}, {379.524, 305.229}, {395.5, 290.75}, {404.531, 282.291}, {413.224, 273.686}, {421.57, 264.936}, {429.56, 256.04}, {437.185, 247}, {443.055, 239.45}, - {448.516, 231.675}, {453.562, 223.678}, {458.186, 215.466}, + {448.516, 231.674}, {453.562, 223.678}, {458.186, 215.466}, {462.382, 207.043}, {466.148, 198.417}, {469.016, 190.697}, - {471.436, 182.748}, {473.412, 174.582}, {474.949, 166.212}, - {476.053, 157.649}, {476.734, 148.908}, {477, 140}, - {476.697, 131.863}, {475.889, 123.857}, {474.571, 115.997}, + {471.437, 182.748}, {473.413, 174.582}, {474.949, 166.211}, + {476.054, 157.649}, {476.734, 148.908}, {477, 140}, + {476.697, 131.863}, {475.889, 123.858}, {474.571, 115.997}, {472.739, 108.293}, {470.392, 100.759}, {467.531, 93.4062}, - {464.244, 86.3502}, {460.548, 79.5599}, {456.446, 73.0461}, - {451.942, 66.8181}, {447.041, 60.884}, {441.75, 55.25}, + {464.244, 86.3502}, {460.548, 79.56}, {456.446, 73.0462}, + {451.942, 66.8182}, {447.041, 60.884}, {441.75, 55.25}, {436.116, 49.9595}, {430.182, 45.0581}, {423.954, 40.5537}, - {417.44, 36.452}, {410.65, 32.7565}, {403.594, 29.4688}, - {396.241, 26.6084}, {388.707, 24.2609}, {381.004, 22.4286}, + {417.44, 36.4519}, {410.65, 32.7564}, {403.594, 29.4688}, + {396.241, 26.6083}, {388.707, 24.2609}, {381.004, 22.4285}, {373.143, 21.1106}, {365.137, 20.3032}, {357, 20}, {349.102, 20.2777}, {341.323, 21.0241}, {333.676, 22.2452}, - {326.171, 23.9443}, {318.819, 26.1224}, {311.63, 28.7778}, - {304.722, 31.8337}, {298.058, 35.2778}, {291.65, 39.1093}, + {326.17, 23.9443}, {318.818, 26.1223}, {311.63, 28.7778}, + {304.721, 31.8336}, {298.058, 35.2778}, {291.65, 39.1093}, {285.505, 43.3251}, {279.632, 47.9205}, {274.037, 52.8889}, {268.767, 58.1866}, {263.861, 63.7819}, {259.326, 69.6689}, {255.169, 75.8403}, {251.393, 82.2873}, {248, 89}, {244.622, 82.2933}, {240.874, 75.8498}, {236.755, 69.6796}, - {232.27, 63.7913}, {227.423, 58.1924}, {222.222, 52.8889}, - {216.709, 47.922}, {210.917, 43.3271}, {204.854, 39.1112}, - {198.525, 35.2793}, {191.941, 31.8344}, {185.111, 28.7778}, + {232.27, 63.7913}, {227.424, 58.1923}, {222.222, 52.8889}, + {216.709, 47.922}, {210.918, 43.3271}, {204.854, 39.1112}, + {198.525, 35.2792}, {191.941, 31.8344}, {185.111, 28.7778}, {177.988, 26.1195}, {170.693, 23.9406}, {163.234, 22.242}, {155.625, 21.0222}, {147.876, 20.277}, {140, 20}}; std::vector golden_heart_vertices = { - {139.95, 19.5025}, {140.05, 20.4975}, {131.715, 19.8048}, - {131.815, 20.7998}, {131.683, 19.809}, {131.847, 20.7956}, - {123.59, 20.6145}, {123.753, 21.601}, {123.557, 20.6211}, - {123.786, 21.5944}, {115.619, 21.9372}, {115.848, 22.9105}, - {115.586, 21.9462}, {115.882, 22.9015}, {107.817, 23.7777}, - {108.113, 24.733}, {107.784, 23.7891}, {108.146, 24.7215}, - {100.197, 26.1378}, {100.558, 27.0703}, {100.167, 26.1506}, - {100.589, 27.0574}, {92.7736, 29.0154}, {93.1952, 29.9221}, - {92.7456, 29.0295}, {93.2232, 29.908}, {85.68, 32.3144}, - {86.1576, 33.193}, {85.6523, 32.3306}, {86.1853, 33.1768}, - {78.8588, 36.0242}, {79.3918, 36.8703}, {78.8319, 36.0423}, - {79.4187, 36.8521}, {72.3216, 40.1432}, {72.9084, 40.9529}, - {72.2959, 40.1631}, {72.9341, 40.933}, {66.0788, 44.6679}, - {66.717, 45.4378}, {66.0546, 44.6893}, {66.7411, 45.4164}, - {60.139, 49.5924}, {60.8255, 50.3196}, {60.1166, 49.615}, - {60.8479, 50.297}, {54.5094, 54.909}, {55.2406, 55.591}, - {54.4883, 54.933}, {55.2617, 55.567}, {49.2329, 60.5677}, - {50.0063, 61.2016}, {49.2133, 60.5933}, {50.026, 61.176}, - {44.3488, 66.5281}, {45.1614, 67.1108}, {44.3308, 66.5549}, - {45.1794, 67.084}, {39.8648, 72.7832}, {40.7133, 73.3123}, - {39.8488, 72.8108}, {40.7293, 73.2847}, {35.7869, 79.3246}, - {36.6675, 79.7985}, {35.7729, 79.3526}, {36.6815, 79.7705}, - {32.1188, 86.1424}, {33.0273, 86.5603}, {32.1062, 86.1723}, - {33.0399, 86.5304}, {28.8613, 93.2272}, {29.795, 93.5853}, - {28.8502, 93.2595}, {29.8061, 93.553}, {26.0288, 100.615}, - {26.9847, 100.908}, {26.0199, 100.648}, {26.9935, 100.876}, - {23.7056, 108.183}, {24.6792, 108.411}, {23.6991, 108.215}, - {24.6857, 108.378}, {21.8937, 115.919}, {22.8804, 116.082}, - {21.8895, 115.951}, {22.8846, 116.05}, {20.592, 123.812}, - {21.5871, 123.91}, {20.5899, 123.843}, {21.5892, 123.879}, - {19.7964, 131.847}, {20.7957, 131.883}, {19.7962, 131.879}, - {20.7958, 131.851}, {19.5002, 140.014}, {20.4998, 139.986}, - {19.5013, 140.036}, {20.4987, 139.964}, {19.7547, 149.234}, - {20.7521, 149.161}, {19.757, 149.257}, {20.7498, 149.138}, - {20.4096, 158.273}, {21.4024, 158.154}, {20.4133, 158.299}, - {21.3987, 158.129}, {21.4761, 167.119}, {22.4616, 166.95}, - {21.4814, 167.146}, {22.4564, 166.923}, {22.9644, 175.757}, - {23.9394, 175.535}, {22.9715, 175.784}, {23.9324, 175.507}, - {24.8833, 184.172}, {25.8442, 183.895}, {24.8923, 184.2}, - {25.8352, 183.867}, {27.2398, 192.35}, {28.1828, 192.017}, - {27.2498, 192.376}, {28.1728, 191.991}, {30.0385, 200.276}, - {30.9615, 199.891}, {30.0488, 200.299}, {30.9512, 199.868}, - {33.6872, 209.03}, {34.5896, 208.599}, {33.6989, 209.053}, - {34.5779, 208.576}, {37.7638, 217.562}, {38.6429, 217.085}, - {37.7766, 217.584}, {38.6301, 217.063}, {42.266, 225.863}, - {43.1195, 225.342}, {42.2799, 225.885}, {43.1057, 225.321}, - {47.1903, 233.928}, {48.0162, 233.364}, {47.2051, 233.949}, - {48.0014, 233.344}, {52.5317, 241.749}, {53.3281, 241.144}, - {52.5448, 241.766}, {53.315, 241.128}, {58.2816, 249.319}, - {59.0518, 248.681}, {58.2924, 249.332}, {59.0409, 248.668}, - {65.7267, 258.309}, {66.4752, 257.646}, {65.7376, 258.321}, - {66.4644, 257.634}, {73.5471, 267.136}, {74.2739, 266.449}, - {73.558, 267.147}, {74.2631, 266.438}, {81.7338, 275.798}, - {82.439, 275.089}, {81.7445, 275.808}, {82.4283, 275.078}, - {90.2775, 284.294}, {90.9613, 283.564}, {90.2844, 284.3}, - {90.9544, 283.558}, {99.165, 292.621}, {99.835, 291.879}, - {99.168, 292.624}, {99.832, 291.876}, {114.93, 306.849}, - {115.594, 306.102}, {114.933, 306.852}, {115.591, 306.099}, - {131.104, 321.215}, {131.762, 320.462}, {131.101, 321.212}, - {131.765, 320.464}, {147.668, 335.707}, {148.332, 334.96}, - {147.66, 335.7}, {148.34, 334.967}, {160.581, 347.178}, - {161.261, 346.445}, {160.573, 347.171}, {161.268, 346.452}, - {173.409, 359.074}, {174.104, 358.355}, {173.402, 359.068}, - {174.111, 358.362}, {186.151, 371.385}, {186.86, 370.679}, - {186.143, 371.376}, {186.868, 370.688}, {198.804, 384.094}, - {199.529, 383.406}, {198.794, 384.084}, {199.539, 383.417}, - {207.382, 393.138}, {208.127, 392.471}, {207.373, 393.128}, - {208.136, 392.482}, {215.781, 402.522}, {216.544, 401.876}, - {215.772, 402.511}, {216.553, 401.886}, {224, 412.236}, - {224.781, 411.611}, {223.992, 412.226}, {224.789, 411.621}, - {232.041, 422.273}, {232.837, 421.668}, {232.033, 422.263}, - {232.844, 421.678}, {239.903, 432.625}, {240.714, 432.04}, - {240.719, 432.618}, {239.898, 432.047}, {248.41, 443.286}, - {247.59, 442.714}, {248.403, 443.296}, {247.597, 442.704}, - {255.809, 432.663}, {255.004, 432.07}, {255.801, 432.674}, - {255.012, 432.059}, {263.412, 422.334}, {262.623, 421.72}, - {263.404, 422.345}, {262.632, 421.709}, {271.22, 412.306}, - {270.448, 411.67}, {271.211, 412.317}, {270.458, 411.659}, - {279.233, 402.587}, {278.48, 401.929}, {279.223, 402.598}, - {278.49, 401.918}, {287.451, 393.183}, {286.718, 392.503}, - {287.442, 393.192}, {286.727, 392.494}, {295.876, 384.099}, - {295.161, 383.401}, {295.869, 384.106}, {295.168, 383.394}, - {308.423, 371.234}, {307.721, 370.522}, {308.415, 371.242}, - {307.729, 370.514}, {321.094, 358.764}, {320.408, 358.036}, - {321.086, 358.771}, {320.416, 358.029}, {333.889, 346.697}, - {333.219, 345.955}, {333.886, 346.7}, {333.222, 345.952}, - {346.813, 335.041}, {346.15, 334.292}, {346.815, 335.039}, - {346.148, 334.294}, {363.515, 320.242}, {362.848, 319.497}, - {363.517, 320.24}, {362.846, 319.499}, {379.86, 305.6}, - {379.189, 304.859}, {379.866, 305.594}, {379.183, 304.864}, - {395.842, 291.115}, {395.158, 290.385}, {395.852, 291.105}, - {395.148, 290.395}, {404.882, 282.647}, {404.179, 281.936}, - {404.892, 282.636}, {404.169, 281.946}, {413.586, 274.032}, - {412.862, 273.341}, {413.596, 274.021}, {412.852, 273.352}, - {421.942, 265.27}, {421.198, 264.602}, {421.952, 265.258}, - {421.188, 264.613}, {429.943, 256.362}, {429.178, 255.718}, - {429.955, 256.347}, {429.166, 255.733}, {437.58, 247.307}, - {436.79, 246.693}, {437.594, 247.287}, {436.776, 246.713}, - {443.464, 239.737}, {442.646, 239.163}, {443.478, 239.717}, - {442.632, 239.183}, {448.939, 231.941}, {448.094, 231.408}, - {448.952, 231.92}, {448.081, 231.429}, {453.998, 223.923}, - {453.126, 223.433}, {454.01, 223.901}, {453.115, 223.455}, - {458.633, 215.689}, {457.738, 215.243}, {458.644, 215.666}, - {457.727, 215.266}, {462.841, 207.243}, {461.924, 206.843}, - {462.851, 207.217}, {461.914, 206.869}, {466.617, 198.591}, - {465.679, 198.243}, {466.626, 198.562}, {465.67, 198.271}, - {469.494, 190.842}, {468.538, 190.551}, {469.502, 190.814}, - {468.53, 190.579}, {471.922, 182.865}, {470.951, 182.63}, - {471.928, 182.838}, {470.945, 182.657}, {473.904, 174.672}, - {472.921, 174.492}, {473.908, 174.646}, {472.917, 174.518}, - {475.445, 166.275}, {474.453, 166.147}, {475.448, 166.25}, - {474.451, 166.173}, {476.552, 157.688}, {475.555, 157.61}, - {476.553, 157.664}, {475.554, 157.634}, {477.234, 148.922}, - {476.234, 148.893}, {477.234, 148.889}, {476.234, 148.926}, - {477.5, 139.981}, {476.5, 140.019}, {477.497, 139.95}, - {476.503, 140.05}, {477.194, 131.813}, {476.199, 131.913}, - {477.19, 131.78}, {476.204, 131.946}, {476.383, 123.775}, - {475.396, 123.94}, {476.376, 123.742}, {475.403, 123.973}, - {475.058, 115.881}, {474.085, 116.112}, {475.049, 115.848}, - {474.094, 116.145}, {473.216, 108.144}, {472.262, 108.442}, - {473.205, 108.112}, {472.273, 108.474}, {470.858, 100.578}, - {469.926, 100.94}, {470.845, 100.548}, {469.938, 100.97}, - {467.984, 93.1951}, {467.078, 93.6174}, {467.97, 93.1672}, - {467.092, 93.6453}, {464.683, 86.1112}, {463.804, 86.5892}, - {464.667, 86.0838}, {463.821, 86.6167}, {460.971, 79.2935}, - {460.125, 79.8264}, {460.953, 79.267}, {460.143, 79.853}, - {456.851, 72.7531}, {456.041, 73.3392}, {456.832, 72.7278}, - {456.061, 73.3646}, {452.327, 66.4998}, {451.556, 67.1366}, - {452.306, 66.4759}, {451.577, 67.1604}, {447.405, 60.5417}, - {446.676, 61.2262}, {447.383, 60.5195}, {446.698, 61.2485}, - {442.092, 54.8855}, {441.408, 55.6145}, {442.068, 54.8645}, - {441.432, 55.6355}, {436.434, 49.5739}, {435.798, 50.345}, - {436.409, 49.5543}, {435.823, 50.3646}, {430.475, 44.653}, - {429.889, 45.4633}, {430.448, 44.635}, {429.915, 45.4812}, - {424.22, 40.1306}, {423.687, 40.9768}, {424.193, 40.1145}, - {423.715, 40.9929}, {417.679, 36.0127}, {417.201, 36.8911}, - {417.651, 35.9987}, {417.229, 36.9051}, {410.861, 32.3032}, - {410.439, 33.2096}, {410.831, 32.2904}, {410.469, 33.2224}, - {403.775, 29.0028}, {403.412, 29.9347}, {403.742, 28.9914}, - {403.445, 29.9461}, {396.39, 26.131}, {396.092, 27.0857}, - {396.357, 26.1219}, {396.125, 27.0948}, {388.823, 23.7744}, - {388.591, 24.7473}, {388.79, 23.7677}, {388.624, 24.754}, - {381.086, 21.9354}, {380.921, 22.9217}, {381.054, 21.9311}, - {380.953, 22.926}, {373.193, 20.6131}, {373.092, 21.608}, - {373.161, 20.6109}, {373.124, 21.6102}, {365.156, 19.8036}, - {365.118, 20.8029}, {365.119, 19.8035}, {365.154, 20.8029}, - {356.982, 19.5003}, {357.018, 20.4997}, {356.952, 19.5023}, - {357.048, 20.4977}, {349.054, 19.7799}, {349.15, 20.7754}, - {349.023, 19.7839}, {349.181, 20.7714}, {341.244, 20.5304}, - {341.402, 21.5179}, {341.213, 20.5365}, {341.434, 21.5118}, - {333.565, 21.7575}, {333.786, 22.7329}, {333.534, 21.7658}, - {333.818, 22.7246}, {326.028, 23.4649}, {326.312, 24.4237}, - {325.997, 23.4753}, {326.343, 24.4133}, {318.645, 25.6533}, - {318.991, 26.5914}, {318.616, 25.6651}, {319.02, 26.5796}, - {311.427, 28.3205}, {311.832, 29.235}, {311.4, 28.3336}, - {311.859, 29.2219}, {304.492, 31.3895}, {304.951, 32.2778}, - {304.465, 31.4045}, {304.978, 32.2628}, {297.801, 34.8487}, - {298.314, 35.707}, {297.775, 34.8655}, {298.341, 35.6901}, - {291.367, 38.697}, {291.932, 39.5216}, {291.341, 38.7155}, - {291.958, 39.5031}, {285.197, 42.9313}, {285.813, 43.7189}, - {285.173, 42.9512}, {285.837, 43.699}, {279.3, 47.5467}, - {279.964, 48.2944}, {279.278, 47.5679}, {279.987, 48.2732}, - {273.683, 52.5363}, {274.392, 53.2415}, {273.661, 52.5592}, - {274.413, 53.2185}, {268.391, 57.857}, {269.143, 58.5163}, - {268.371, 57.8815}, {269.163, 58.4917}, {263.465, 63.4768}, - {264.257, 64.087}, {263.446, 63.5026}, {264.276, 64.0613}, - {258.912, 69.3896}, {259.741, 69.9483}, {258.895, 69.4162}, - {259.758, 69.9216}, {254.738, 75.5876}, {255.601, 76.093}, - {254.723, 75.6147}, {255.615, 76.0659}, {250.947, 82.0618}, - {251.839, 82.5129}, {251.84, 82.0624}, {250.947, 82.5122}, - {248.447, 88.7751}, {247.553, 89.2249}, {248.432, 88.7486}, - {247.568, 89.2514}, {245.055, 82.0419}, {244.19, 82.5447}, - {245.038, 82.0157}, {244.207, 82.5709}, {241.29, 75.5723}, - {240.458, 76.1274}, {241.271, 75.5469}, {240.476, 76.1528}, - {237.153, 69.3766}, {236.357, 69.9825}, {237.133, 69.3523}, - {236.377, 70.0068}, {232.648, 63.464}, {231.892, 64.1185}, - {232.627, 63.4412}, {231.913, 64.1414}, {227.781, 57.8422}, - {227.067, 58.5424}, {227.758, 57.8209}, {227.089, 58.5638}, - {222.557, 52.5174}, {221.888, 53.2604}, {222.533, 52.4972}, - {221.911, 53.2806}, {217.02, 47.5303}, {216.398, 48.3137}, - {216.995, 47.5114}, {216.424, 48.3325}, {211.203, 42.9166}, - {210.632, 43.7376}, {211.176, 42.8994}, {210.659, 43.7548}, - {205.113, 38.6835}, {204.595, 39.5389}, {205.086, 38.6682}, - {204.622, 39.5542}, {198.757, 34.8362}, {198.294, 35.7223}, - {198.73, 34.8229}, {198.321, 35.7356}, {192.145, 31.378}, - {191.737, 32.2908}, {192.116, 31.3659}, {191.766, 32.3028}, - {185.286, 28.3093}, {184.936, 29.2462}, {185.254, 28.2987}, - {184.968, 29.2569}, {178.132, 25.6404}, {177.845, 26.5986}, - {178.1, 25.632}, {177.877, 26.607}, {170.804, 23.4531}, - {170.582, 24.4281}, {170.772, 23.4469}, {170.614, 24.4343}, - {163.313, 21.7483}, {163.155, 22.7357}, {163.282, 21.7443}, - {163.186, 22.7397}, {155.673, 20.5245}, {155.577, 21.5199}, - {155.642, 20.5225}, {155.607, 21.5219}, {147.893, 19.7773}, - {147.858, 20.7767}, {147.947, 19.782}, {147.805, 20.772}, - {140.071, 19.505}, {139.929, 20.495}, -}; + {139.982, 19.5003}, {140.018, 20.4997}, {131.747, 19.8026}, + {131.783, 20.802}, {131.715, 19.8048}, {131.815, 20.7998}, + {123.622, 20.6102}, {123.721, 21.6053}, {123.59, 20.6145}, + {123.753, 21.601}, {115.652, 21.9306}, {115.816, 22.9171}, + {115.619, 21.9372}, {115.848, 22.9105}, {107.85, 23.7687}, + {108.08, 24.742}, {107.817, 23.7777}, {108.113, 24.733}, + {100.23, 26.1264}, {100.526, 27.0817}, {100.197, 26.1378}, + {100.558, 27.0703}, {92.8037, 29.0025}, {93.165, 29.935}, + {92.7736, 29.0154}, {93.1952, 29.9221}, {85.708, 32.3003}, + {86.1296, 33.2071}, {85.68, 32.3144}, {86.1576, 33.193}, + {78.8865, 36.008}, {79.3641, 36.8865}, {78.8588, 36.0242}, + {79.3918, 36.8703}, {72.3485, 40.125}, {72.8815, 40.9711}, + {72.3216, 40.1432}, {72.9084, 40.9529}, {66.1045, 44.6479}, + {66.6913, 45.4577}, {66.0788, 44.6679}, {66.717, 45.4378}, + {60.1632, 49.5711}, {60.8014, 50.341}, {60.139, 49.5924}, + {60.8255, 50.3196}, {54.5317, 54.8864}, {55.2183, 55.6136}, + {54.5094, 54.909}, {55.2406, 55.591}, {49.254, 60.5436}, + {49.9853, 61.2257}, {49.2329, 60.5677}, {50.0063, 61.2016}, + {44.3684, 66.5025}, {45.1418, 67.1364}, {44.3488, 66.5281}, + {45.1614, 67.1108}, {39.8827, 72.7564}, {40.6954, 73.3391}, + {39.8648, 72.7832}, {40.7133, 73.3123}, {35.8029, 79.297}, + {36.6515, 79.8261}, {35.7869, 79.3246}, {36.6675, 79.7985}, + {32.1328, 86.1144}, {33.0134, 86.5883}, {32.1188, 86.1424}, + {33.0273, 86.5603}, {28.8739, 93.1973}, {29.7824, 93.6152}, + {28.8613, 93.2272}, {29.795, 93.5853}, {26.0399, 100.583}, + {26.9736, 100.941}, {26.0288, 100.615}, {26.9847, 100.908}, + {23.7144, 108.15}, {24.6704, 108.444}, {23.7056, 108.183}, + {24.6792, 108.411}, {21.9002, 115.886}, {22.8738, 116.115}, + {21.8937, 115.919}, {22.8804, 116.082}, {20.5962, 123.779}, + {21.5828, 123.942}, {20.592, 123.812}, {21.5871, 123.91}, + {19.7985, 131.816}, {20.7936, 131.914}, {19.7964, 131.847}, + {20.7957, 131.883}, {19.5003, 139.982}, {20.4997, 140.018}, + {19.5002, 140.014}, {20.4998, 139.986}, {19.7536, 149.211}, + {20.7532, 149.184}, {19.7547, 149.234}, {20.7521, 149.161}, + {20.4073, 158.25}, {21.4047, 158.178}, {20.4096, 158.273}, + {21.4024, 158.154}, {21.4725, 167.094}, {22.4653, 166.975}, + {21.4761, 167.119}, {22.4616, 166.95}, {22.9592, 175.73}, + {23.9447, 175.561}, {22.9644, 175.757}, {23.9394, 175.535}, + {24.8762, 184.144}, {25.8512, 183.922}, {24.8833, 184.172}, + {25.8442, 183.895}, {27.2309, 192.322}, {28.1918, 192.045}, + {27.2398, 192.35}, {28.1828, 192.017}, {30.0285, 200.25}, + {30.9715, 199.917}, {30.0385, 200.276}, {30.9615, 199.891}, + {33.6769, 209.007}, {34.5999, 208.622}, {33.6872, 209.03}, + {34.5896, 208.599}, {37.7522, 217.539}, {38.6545, 217.108}, + {37.7638, 217.562}, {38.6429, 217.085}, {42.2532, 225.841}, + {43.1323, 225.365}, {42.266, 225.863}, {43.1195, 225.342}, + {47.1765, 233.907}, {48.03, 233.386}, {47.1903, 233.928}, + {48.0162, 233.364}, {52.517, 241.729}, {53.3428, 241.165}, + {52.5317, 241.749}, {53.3281, 241.144}, {58.2685, 249.302}, + {59.0648, 248.698}, {58.2816, 249.319}, {59.0518, 248.681}, + {65.7159, 258.297}, {66.4861, 257.659}, {65.7267, 258.309}, + {66.4752, 257.646}, {73.5363, 267.124}, {74.2848, 266.461}, + {73.5471, 267.136}, {74.2739, 266.449}, {81.723, 275.787}, + {82.4498, 275.1}, {81.7338, 275.798}, {82.439, 275.089}, + {90.2668, 284.284}, {90.972, 283.575}, {90.2775, 284.294}, + {90.9613, 283.564}, {99.1581, 292.615}, {99.8419, 291.885}, + {99.165, 292.621}, {99.835, 291.879}, {114.927, 306.847}, + {115.597, 306.104}, {114.93, 306.849}, {115.594, 306.102}, + {131.101, 321.212}, {131.765, 320.464}, {131.104, 321.215}, + {131.762, 320.462}, {147.671, 335.71}, {148.329, 334.957}, + {147.668, 335.707}, {148.332, 334.96}, {160.589, 347.185}, + {161.253, 346.437}, {160.581, 347.178}, {161.261, 346.445}, + {173.416, 359.081}, {174.096, 358.348}, {173.409, 359.074}, + {174.104, 358.355}, {186.158, 371.391}, {186.853, 370.672}, + {186.151, 371.385}, {186.86, 370.679}, {198.812, 384.103}, + {199.521, 383.397}, {198.804, 384.094}, {199.529, 383.406}, + {207.392, 393.149}, {208.117, 392.461}, {207.382, 393.138}, + {208.127, 392.471}, {215.79, 402.532}, {216.535, 401.865}, + {215.781, 402.522}, {216.544, 401.876}, {224.009, 412.246}, + {224.772, 411.6}, {224, 412.236}, {224.781, 411.611}, + {232.049, 422.283}, {232.829, 421.658}, {232.041, 422.273}, + {232.837, 421.668}, {239.91, 432.635}, {240.707, 432.03}, + {239.903, 432.625}, {240.714, 432.04}, {247.594, 443.292}, + {248.406, 442.708}, {248.41, 443.286}, {247.59, 442.714}, + {255.817, 432.652}, {254.996, 432.081}, {255.809, 432.663}, + {255.004, 432.07}, {263.421, 422.323}, {262.615, 421.73}, + {263.412, 422.334}, {262.623, 421.72}, {271.229, 412.296}, + {270.44, 411.681}, {271.22, 412.306}, {270.448, 411.67}, + {279.242, 402.576}, {278.471, 401.94}, {279.233, 402.587}, + {278.48, 401.929}, {287.461, 393.172}, {286.708, 392.514}, + {287.451, 393.183}, {286.718, 392.503}, {295.885, 384.09}, + {295.152, 383.41}, {295.876, 384.099}, {295.161, 383.401}, + {308.43, 371.227}, {307.714, 370.529}, {308.423, 371.234}, + {307.721, 370.522}, {321.101, 358.756}, {320.4, 358.043}, + {321.094, 358.764}, {320.408, 358.036}, {333.897, 346.69}, + {333.211, 345.962}, {333.889, 346.697}, {333.219, 345.955}, + {346.816, 335.038}, {346.147, 334.295}, {346.813, 335.041}, + {346.15, 334.292}, {363.513, 320.244}, {362.85, 319.495}, + {363.515, 320.242}, {362.848, 319.497}, {379.858, 305.602}, + {379.191, 304.857}, {379.86, 305.6}, {379.189, 304.859}, + {395.836, 291.12}, {395.164, 290.38}, {395.842, 291.115}, + {395.158, 290.385}, {404.872, 282.656}, {404.189, 281.926}, + {404.882, 282.647}, {404.179, 281.936}, {413.576, 274.042}, + {412.872, 273.331}, {413.586, 274.032}, {412.862, 273.341}, + {421.932, 265.281}, {421.208, 264.591}, {421.942, 265.27}, + {421.198, 264.602}, {429.932, 256.374}, {429.188, 255.706}, + {429.943, 256.362}, {429.178, 255.718}, {437.567, 247.322}, + {436.803, 246.678}, {437.58, 247.307}, {436.79, 246.693}, + {443.45, 239.757}, {442.66, 239.143}, {443.464, 239.737}, + {442.646, 239.163}, {448.926, 231.962}, {448.107, 231.387}, + {448.939, 231.941}, {448.094, 231.408}, {453.985, 223.945}, + {453.139, 223.411}, {453.998, 223.923}, {453.126, 223.433}, + {458.621, 215.711}, {457.75, 215.22}, {458.633, 215.689}, + {457.738, 215.243}, {462.83, 207.266}, {461.935, 206.82}, + {462.841, 207.243}, {461.924, 206.843}, {466.606, 198.617}, + {465.69, 198.217}, {466.617, 198.591}, {465.679, 198.243}, + {469.485, 190.871}, {468.547, 190.522}, {469.494, 190.842}, + {468.538, 190.551}, {471.915, 182.893}, {470.958, 182.602}, + {471.922, 182.865}, {470.951, 182.63}, {473.898, 174.7}, + {472.927, 174.464}, {473.904, 174.672}, {472.921, 174.492}, + {475.441, 166.302}, {474.457, 166.121}, {475.445, 166.275}, + {474.453, 166.147}, {476.55, 157.713}, {475.558, 157.585}, + {476.552, 157.688}, {475.555, 157.61}, {477.232, 148.946}, + {476.235, 148.869}, {477.234, 148.922}, {476.234, 148.893}, + {477.5, 140.015}, {476.5, 139.985}, {477.5, 139.981}, + {476.5, 140.019}, {477.196, 131.844}, {476.197, 131.882}, + {477.194, 131.813}, {476.199, 131.913}, {476.387, 123.807}, + {475.392, 123.908}, {476.383, 123.775}, {475.396, 123.94}, + {475.065, 115.914}, {474.078, 116.079}, {475.058, 115.881}, + {474.085, 116.112}, {473.226, 108.177}, {472.253, 108.409}, + {473.216, 108.144}, {472.262, 108.442}, {470.869, 100.61}, + {469.914, 100.908}, {470.858, 100.578}, {469.926, 100.94}, + {467.997, 93.225}, {467.065, 93.5875}, {467.984, 93.1951}, + {467.078, 93.6174}, {464.697, 86.1391}, {463.79, 86.5614}, + {464.683, 86.1112}, {463.804, 86.5892}, {460.987, 79.321}, + {460.109, 79.799}, {460.971, 79.2935}, {460.125, 79.8264}, + {456.869, 72.7797}, {456.023, 73.3126}, {456.851, 72.7531}, + {456.041, 73.3392}, {452.347, 66.5252}, {451.537, 67.1112}, + {452.327, 66.4998}, {451.556, 67.1366}, {447.426, 60.5656}, + {446.655, 61.2024}, {447.405, 60.5417}, {446.676, 61.2262}, + {442.115, 54.9077}, {441.385, 55.5923}, {442.092, 54.8855}, + {441.408, 55.6145}, {436.458, 49.595}, {435.774, 50.3239}, + {436.434, 49.5739}, {435.798, 50.345}, {430.5, 44.6726}, + {429.863, 45.4436}, {430.475, 44.653}, {429.889, 45.4633}, + {424.247, 40.1486}, {423.661, 40.9588}, {424.22, 40.1306}, + {423.687, 40.9768}, {417.706, 36.0288}, {417.174, 36.875}, + {417.679, 36.0127}, {417.201, 36.8911}, {410.889, 32.3172}, + {410.411, 33.1956}, {410.861, 32.3032}, {410.439, 33.2096}, + {403.805, 29.0155}, {403.383, 29.922}, {403.775, 29.0028}, + {403.412, 29.9347}, {396.422, 26.1423}, {396.06, 27.0743}, + {396.39, 26.131}, {396.092, 27.0857}, {388.856, 23.7835}, + {388.558, 24.7382}, {388.823, 23.7744}, {388.591, 24.7473}, + {381.119, 21.9421}, {380.888, 22.915}, {381.086, 21.9354}, + {380.921, 22.9217}, {373.225, 20.6175}, {373.06, 21.6037}, + {373.193, 20.6131}, {373.092, 21.608}, {365.187, 19.8057}, + {365.087, 20.8007}, {365.156, 19.8036}, {365.118, 20.8029}, + {357.019, 19.5003}, {356.981, 20.4997}, {356.982, 19.5003}, + {357.018, 20.4997}, {349.084, 19.778}, {349.12, 20.7773}, + {349.054, 19.7799}, {349.15, 20.7754}, {341.275, 20.5264}, + {341.371, 21.5218}, {341.244, 20.5304}, {341.402, 21.5179}, + {333.597, 21.7514}, {333.754, 22.7389}, {333.565, 21.7575}, + {333.786, 22.7329}, {326.06, 23.4566}, {326.281, 24.4319}, + {326.028, 23.4649}, {326.312, 24.4237}, {318.676, 25.6429}, + {318.96, 26.6017}, {318.645, 25.6533}, {318.991, 26.5914}, + {311.456, 28.3088}, {311.803, 29.2468}, {311.427, 28.3205}, + {311.832, 29.235}, {304.519, 31.3764}, {304.923, 32.2909}, + {304.492, 31.3895}, {304.951, 32.2778}, {297.828, 34.8336}, + {298.287, 35.722}, {297.801, 34.8487}, {298.314, 35.707}, + {291.393, 38.6801}, {291.906, 39.5384}, {291.367, 38.697}, + {291.932, 39.5216}, {285.222, 42.9128}, {285.788, 43.7374}, + {285.197, 42.9313}, {285.813, 43.7189}, {279.324, 47.5267}, + {279.94, 48.3143}, {279.3, 47.5467}, {279.964, 48.2944}, + {273.705, 52.515}, {274.369, 53.2628}, {273.683, 52.5363}, + {274.392, 53.2415}, {268.412, 57.834}, {269.121, 58.5393}, + {268.391, 57.857}, {269.143, 58.5163}, {263.485, 63.4523}, + {264.237, 64.1116}, {263.465, 63.4768}, {264.257, 64.087}, + {258.93, 69.3638}, {259.722, 69.974}, {258.912, 69.3896}, + {259.741, 69.9483}, {254.754, 75.561}, {255.584, 76.1196}, + {254.738, 75.5876}, {255.601, 76.093}, {250.962, 82.0346}, + {251.825, 82.54}, {250.947, 82.0618}, {251.839, 82.5129}, + {247.554, 88.7744}, {248.446, 89.2256}, {248.447, 88.7751}, + {247.553, 89.2249}, {245.069, 82.0684}, {244.176, 82.5182}, + {245.055, 82.0419}, {244.19, 82.5447}, {241.306, 75.5984}, + {240.442, 76.1013}, {241.29, 75.5723}, {240.458, 76.1274}, + {237.171, 69.402}, {236.339, 69.9572}, {237.153, 69.3766}, + {236.357, 69.9825}, {232.668, 63.4883}, {231.872, 64.0942}, + {232.648, 63.464}, {231.892, 64.1185}, {227.802, 57.8651}, + {227.046, 58.5196}, {227.781, 57.8422}, {227.067, 58.5424}, + {222.579, 52.5388}, {221.865, 53.239}, {222.557, 52.5174}, + {221.888, 53.2604}, {217.044, 47.5505}, {216.374, 48.2934}, + {217.02, 47.5303}, {216.398, 48.3137}, {211.228, 42.9354}, + {210.607, 43.7188}, {211.203, 42.9166}, {210.632, 43.7376}, + {205.139, 38.7007}, {204.568, 39.5217}, {205.113, 38.6835}, + {204.595, 39.5389}, {198.784, 34.8515}, {198.266, 35.7069}, + {198.757, 34.8362}, {198.294, 35.7223}, {192.173, 31.3913}, + {191.709, 32.2774}, {192.145, 31.378}, {191.737, 32.2908}, + {185.315, 28.3214}, {184.907, 29.2342}, {185.286, 28.3093}, + {184.936, 29.2462}, {178.163, 25.6511}, {177.814, 26.588}, + {178.132, 25.6404}, {177.845, 26.5986}, {170.836, 23.4615}, + {170.55, 24.4197}, {170.804, 23.4531}, {170.582, 24.4281}, + {163.345, 21.7545}, {163.123, 22.7295}, {163.313, 21.7483}, + {163.155, 22.7357}, {155.704, 20.5285}, {155.546, 21.5159}, + {155.673, 20.5245}, {155.577, 21.5199}, {147.924, 19.7793}, + {147.828, 20.7747}, {147.893, 19.7773}, {147.858, 20.7767}, + {140.018, 19.5003}, {139.982, 20.4997}, {140, 20}, + {140, 20}}; } // namespace testing } // namespace impeller diff --git a/impeller/fixtures/stroke.comp b/impeller/fixtures/stroke.comp index 5a48a29c61e1e..7f5453cd0cd62 100644 --- a/impeller/fixtures/stroke.comp +++ b/impeller/fixtures/stroke.comp @@ -47,10 +47,17 @@ void main() { atomicAdd(vertex_buffer_count.count, 4); - vec2 offset = compute_offset(ident); uint index = ident - 1; + vec2 offset = compute_offset(index); vertex_buffer.position[index * 4 + 0] = polyline.data[ident - 1] + offset; vertex_buffer.position[index * 4 + 1] = polyline.data[ident - 1] - offset; vertex_buffer.position[index * 4 + 2] = polyline.data[ident] + offset; vertex_buffer.position[index * 4 + 3] = polyline.data[ident] - offset; + + // TODO(dnfield): Implement other cap/join mechanisms. + if (ident == polyline.count - 1) { + vertex_buffer.position[index * 4 + 4] = vec2(140, 20); + vertex_buffer.position[index * 4 + 5] = vec2(140, 20); + atomicAdd(vertex_buffer_count.count, 2); + } } diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc index 1b93ae66ec243..e0f6b86dfecd1 100644 --- a/impeller/renderer/compute_subgroup_unittests.cc +++ b/impeller/renderer/compute_subgroup_unittests.cc @@ -136,7 +136,7 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { pass->SetThreadGroupSize(ISize(1024, 1)); ComputeCommand cmd; - cmd.label = "Draw Stroke"; + cmd.label = "Compute Stroke"; cmd.pipeline = compute_pipeline; SS::Config config{.width = 1.0f, .cap = 1, .join = 1, .miter_limit = 4.0f}; @@ -161,7 +161,7 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { quads->AsBufferView().contents); EXPECT_EQ(q->count, golden_heart_quads.size()); - for (size_t i = 0; i < golden_heart_quads.size(); i++) { + for (size_t i = 0; i < q->count; i++) { EXPECT_LT(std::abs(golden_heart_quads[i].p1.x - q->data[i].p1.x), 1e-3); EXPECT_LT(std::abs(golden_heart_quads[i].p1.y - q->data[i].p1.y), 1e-3); @@ -185,7 +185,7 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { auto* v_count = reinterpret_cast( vertex_buffer_count->AsBufferView().contents); EXPECT_EQ(v_count->count, golden_heart_vertices.size()); - for (size_t i = 0; i < golden_heart_vertices.size(); i += 1) { + for (size_t i = 0; i < v_count->count; i += 1) { EXPECT_LT(std::abs(golden_heart_vertices[i].x - v->position[i].x), 1e-3); EXPECT_LT(std::abs(golden_heart_vertices[i].y - v->position[i].y), 1e-3); } @@ -221,7 +221,9 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { cmd.pipeline = renderer.GetSolidFillPipeline(options); - auto count = golden_heart_vertices.size(); + auto count = reinterpret_cast( + vertex_buffer_count->AsBufferView().contents) + ->count; auto& host_buffer = pass.GetTransientsBuffer(); std::vector indices(count); std::iota(std::begin(indices), std::end(indices), 0); From 7c5a9d5e7e7a1ed0b8457a8eba082f7474426813 Mon Sep 17 00:00:00 2001 From: Jackson Gardner Date: Mon, 13 Mar 2023 09:54:22 -0700 Subject: [PATCH 16/16] Use plain Uint32List objects with the fragmenter APIs. (#40239) Use plain Uint32List objects with the fragmenter APIs. --- .../src/engine/canvaskit/canvaskit_api.dart | 12 ++++---- .../src/engine/canvaskit/text_fragmenter.dart | 14 ++++----- .../test/canvaskit/text_fragmenter_test.dart | 30 ++++++++----------- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart index c5f739dca7326..d588da5a54c39 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart @@ -1911,12 +1911,12 @@ extension SkParagraphBuilderExtension on SkParagraphBuilder { // into a utf16 string. String getText() => utf8.decode(getTextUtf8().codeUnits); - external void setWordsUtf8(SkUint32List words); - external void setWordsUtf16(SkUint32List words); - external void setGraphemeBreaksUtf8(SkUint32List graphemes); - external void setGraphemeBreaksUtf16(SkUint32List graphemes); - external void setLineBreaksUtf8(SkUint32List lineBreaks); - external void setLineBreaksUtf16(SkUint32List lineBreaks); + external void setWordsUtf8(Uint32List words); + external void setWordsUtf16(Uint32List words); + external void setGraphemeBreaksUtf8(Uint32List graphemes); + external void setGraphemeBreaksUtf16(Uint32List graphemes); + external void setLineBreaksUtf8(Uint32List lineBreaks); + external void setLineBreaksUtf16(Uint32List lineBreaks); external SkParagraph build(); external void delete(); diff --git a/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart b/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart index 762b617885751..dabee617230b0 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart @@ -43,7 +43,7 @@ final Map _intlSegmenters = fragments = breakLinesUsingV8BreakIterator(text, _v8LineBreaker); final int size = (fragments.length + 1) * 2; - final SkUint32List mallocedList = mallocUint32List(size); - final Uint32List typedArray = mallocedList.toTypedArray(); + final Uint32List typedArray = Uint32List(size); typedArray[0] = 0; // start index typedArray[1] = _kSoftLineBreak; // break type @@ -87,5 +83,5 @@ SkUint32List fragmentUsingV8LineBreaker(String text) { : _kSoftLineBreak; } - return mallocedList; + return typedArray; } diff --git a/lib/web_ui/test/canvaskit/text_fragmenter_test.dart b/lib/web_ui/test/canvaskit/text_fragmenter_test.dart index e444321062b67..7d44c3bc9dd29 100644 --- a/lib/web_ui/test/canvaskit/text_fragmenter_test.dart +++ b/lib/web_ui/test/canvaskit/text_fragmenter_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:typed_data'; + import 'package:test/bootstrap/browser.dart'; import 'package:test/test.dart'; import 'package:ui/src/engine.dart'; @@ -15,33 +17,25 @@ void main() { void testMain() { setUpCanvasKitTest(); - late SkUint32List breaks; - - tearDown(() { - if (browserSupportsCanvaskitChromium) { - free(breaks); - } - }); - group('$fragmentUsingIntlSegmenter', () { test('fragments text into words', () { - breaks = fragmentUsingIntlSegmenter( + final Uint32List breaks = fragmentUsingIntlSegmenter( 'Hello world 你好世界', IntlSegmenterGranularity.word, ); expect( - breaks.toTypedArray(), + breaks, orderedEquals([0, 5, 6, 11, 12, 14, 16]), ); }); test('fragments multi-line text into words', () { - breaks = fragmentUsingIntlSegmenter( + final Uint32List breaks = fragmentUsingIntlSegmenter( 'Lorem ipsum\ndolor 你好世界 sit\namet', IntlSegmenterGranularity.word, ); expect( - breaks.toTypedArray(), + breaks, orderedEquals([ 0, 5, 6, 11, 12, // "Lorem ipsum\n" 17, 18, 20, 22, 23, 26, 27, // "dolor 你好世界 sit\n" @@ -53,12 +47,12 @@ void testMain() { test('fragments text into grapheme clusters', () { // The smiley emoji has a length of 2. // The family emoji has a length of 11. - breaks = fragmentUsingIntlSegmenter( + final Uint32List breaks = fragmentUsingIntlSegmenter( 'Lorem🙂ipsum👨‍👩‍👧‍👦', IntlSegmenterGranularity.grapheme, ); expect( - breaks.toTypedArray(), + breaks, orderedEquals([ 0, 1, 2, 3, 4, 5, 7, // "Lorem🙂" 8, 9, 10, 11, 12, 23, // "ipsum👨‍👩‍👧‍👦" @@ -69,12 +63,12 @@ void testMain() { test('fragments multi-line text into grapheme clusters', () { // The smiley emojis have a length of 2 each. // The family emoji has a length of 11. - breaks = fragmentUsingIntlSegmenter( + final Uint32List breaks = fragmentUsingIntlSegmenter( 'Lorem🙂\nipsum👨‍👩‍👧‍👦dolor\n😄', IntlSegmenterGranularity.grapheme, ); expect( - breaks.toTypedArray(), + breaks, orderedEquals([ 0, 1, 2, 3, 4, 5, 7, 8, // "Lorem🙂\n" 9, 10, 11, 12, 13, 24, // "ipsum👨‍👩‍👧‍👦" @@ -89,11 +83,11 @@ void testMain() { const int kHard = 1; test('fragments text into soft and hard line breaks', () { - breaks = fragmentUsingV8LineBreaker( + final Uint32List breaks = fragmentUsingV8LineBreaker( 'Lorem-ipsum 你好🙂\nDolor sit', ); expect( - breaks.toTypedArray(), + breaks, orderedEquals([ 0, kSoft, 6, kSoft, // "Lorem-"