From 4367ca66ae378597ec708ac16fb65a4b1797ca8a Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 15 Aug 2023 12:40:09 -0700 Subject: [PATCH] [Impeller] Make porter duff blended atlas calls faster. (flutter/engine#44059) This implements part of https://github.com/flutter/flutter/issues/131345 --- Makes all porter-duff draw atlas blending avoid subpass creation, by tweaking the existing porter duff shader to support per-vertex colors and output opacity. This requires a small trick: What the blend shaders and what (drawAtlas/drawVertices) consider the source and destination is reversed. That is a blend mode color filter treats the color as the source whereas drawVertices/drawAtlas treat their per-vertex colors as the destination. Therefore I cannot simply make all color inputs per vertex and use the exact same shaders :( However, for the porter duff blends we should just be able to reverse the blend mode (srcover -> dstOver, xor->xor) (I'm pretty sure I did this correctly) so that the blending is still correct. I don't think we can do this for the advanced blends, but supporting those is less important than the common atlas blending parameters like dstIn. This PR only updates drawAtlas. --- .../ci/licenses_golden/licenses_flutter | 2 + engine/src/flutter/impeller/entity/BUILD.gn | 1 + .../entity/contents/atlas_contents.cc | 83 +++++ .../entity/contents/content_context.h | 3 +- .../contents/filters/blend_filter_contents.cc | 70 ++-- .../contents/filters/blend_filter_contents.h | 22 ++ .../shaders/blending/porter_duff_blend.frag | 6 +- .../shaders/blending/porter_duff_blend.vert | 26 ++ engine/src/flutter/impeller/tools/malioc.json | 333 ++++++++++++++++-- 9 files changed, 483 insertions(+), 63 deletions(-) create mode 100644 engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.vert diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index fbd02b52eb5..86d58b4deda 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -1308,6 +1308,7 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_ ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/border_mask_blur.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/border_mask_blur.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/clip.frag + ../../../flutter/LICENSE @@ -4028,6 +4029,7 @@ FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_sa FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag FILE: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.vert FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.frag FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.vert FILE: ../../../flutter/impeller/entity/shaders/clip.frag diff --git a/engine/src/flutter/impeller/entity/BUILD.gn b/engine/src/flutter/impeller/entity/BUILD.gn index 30da46ffc8b..bf5bbf83285 100644 --- a/engine/src/flutter/impeller/entity/BUILD.gn +++ b/engine/src/flutter/impeller/entity/BUILD.gn @@ -71,6 +71,7 @@ impeller_shaders("entity_shaders") { "shaders/yuv_to_rgb_filter.frag", "shaders/yuv_to_rgb_filter.vert", "shaders/blending/porter_duff_blend.frag", + "shaders/blending/porter_duff_blend.vert", ] if (impeller_debug) { diff --git a/engine/src/flutter/impeller/entity/contents/atlas_contents.cc b/engine/src/flutter/impeller/entity/contents/atlas_contents.cc index 8102fb324ff..7194fd0231b 100644 --- a/engine/src/flutter/impeller/entity/contents/atlas_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/atlas_contents.cc @@ -11,6 +11,7 @@ #include "impeller/core/formats.h" #include "impeller/entity/contents/atlas_contents.h" #include "impeller/entity/contents/content_context.h" +#include "impeller/entity/contents/filters/blend_filter_contents.h" #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/framebuffer_blend_contents.h" @@ -19,6 +20,7 @@ #include "impeller/entity/geometry/geometry.h" #include "impeller/entity/texture_fill.frag.h" #include "impeller/entity/texture_fill.vert.h" +#include "impeller/geometry/color.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/sampler_library.h" #include "impeller/renderer/vertex_buffer_builder.h" @@ -210,6 +212,87 @@ bool AtlasContents::Render(const ContentContext& renderer, return child_contents.Render(renderer, entity, pass); } + constexpr size_t indices[6] = {0, 1, 2, 1, 2, 3}; + constexpr Scalar width[6] = {0, 1, 0, 1, 0, 1}; + constexpr Scalar height[6] = {0, 0, 1, 0, 1, 1}; + + if (blend_mode_ <= BlendMode::kModulate) { + // Simple Porter-Duff blends can be accomplished without a subpass. + using VS = PorterDuffBlendPipeline::VertexShader; + using FS = PorterDuffBlendPipeline::FragmentShader; + + VertexBufferBuilder vtx_builder; + vtx_builder.Reserve(texture_coords_.size() * 6); + const auto texture_size = texture_->GetSize(); + auto& host_buffer = pass.GetTransientsBuffer(); + + for (size_t i = 0; i < texture_coords_.size(); i++) { + auto sample_rect = texture_coords_[i]; + auto matrix = transforms_[i]; + auto transformed_points = + Rect::MakeSize(sample_rect.size).GetTransformedPoints(matrix); + auto color = colors_[i].Premultiply(); + for (size_t j = 0; j < 6; j++) { + VS::PerVertexData data; + data.vertices = transformed_points[indices[j]]; + data.texture_coords = + (sample_rect.origin + Point(sample_rect.size.width * width[j], + sample_rect.size.height * height[j])) / + texture_size; + data.color = color; + vtx_builder.AppendVertex(data); + } + } + + auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer); + + Command cmd; + DEBUG_COMMAND_INFO( + cmd, SPrintF("DrawAtlas Blend (%s)", BlendModeToString(blend_mode_))); + cmd.BindVertices(vtx_buffer); + cmd.stencil_reference = entity.GetStencilDepth(); + auto options = OptionsFromPass(pass); + cmd.pipeline = renderer.GetPorterDuffBlendPipeline(options); + + FS::FragInfo frag_info; + VS::FrameInfo frame_info; + + auto dst_sampler_descriptor = sampler_descriptor_; + if (renderer.GetDeviceCapabilities().SupportsDecalTileMode()) { + dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal; + dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal; + } + auto dst_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler( + dst_sampler_descriptor); + FS::BindTextureSamplerDst(cmd, texture_, dst_sampler); + frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale(); + + frag_info.output_alpha = alpha_; + frag_info.input_alpha = 1.0; + + auto inverted_blend_mode = + InvertPorterDuffBlend(blend_mode_).value_or(BlendMode::kSource); + auto blend_coefficients = + kPorterDuffCoefficients[static_cast(inverted_blend_mode)]; + frag_info.src_coeff = blend_coefficients[0]; + frag_info.src_coeff_dst_alpha = blend_coefficients[1]; + frag_info.dst_coeff = blend_coefficients[2]; + frag_info.dst_coeff_src_alpha = blend_coefficients[3]; + frag_info.dst_coeff_src_color = blend_coefficients[4]; + + FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); + + frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation(); + + auto uniform_view = host_buffer.EmplaceUniform(frame_info); + VS::BindFrameInfo(cmd, uniform_view); + + return pass.AddCommand(std::move(cmd)); + } + + // Advanced blends. + auto sub_atlas = GenerateSubAtlas(); auto sub_coverage = Rect::MakeSize(sub_atlas->size); diff --git a/engine/src/flutter/impeller/entity/contents/content_context.h b/engine/src/flutter/impeller/entity/contents/content_context.h index 423d9a1d87d..71bda2eccc3 100644 --- a/engine/src/flutter/impeller/entity/contents/content_context.h +++ b/engine/src/flutter/impeller/entity/contents/content_context.h @@ -44,6 +44,7 @@ #include "impeller/entity/morphology_filter.vert.h" #include "impeller/entity/points.comp.h" #include "impeller/entity/porter_duff_blend.frag.h" +#include "impeller/entity/porter_duff_blend.vert.h" #include "impeller/entity/radial_gradient_fill.frag.h" #include "impeller/entity/rrect_blur.frag.h" #include "impeller/entity/rrect_blur.vert.h" @@ -182,7 +183,7 @@ using GlyphAtlasPipeline = using GlyphAtlasColorPipeline = RenderPipelineT; using PorterDuffBlendPipeline = - RenderPipelineT; + RenderPipelineT; // Instead of requiring new shaders for clips, the solid fill stages are used // to redirect writing to the stencil instead of color attachments. using ClipPipeline = RenderPipelineT; diff --git a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc index 2cd875724bf..663e0a048be 100644 --- a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc @@ -24,6 +24,41 @@ namespace impeller { +std::optional InvertPorterDuffBlend(BlendMode blend_mode) { + switch (blend_mode) { + case BlendMode::kClear: + return BlendMode::kClear; + case BlendMode::kSource: + return BlendMode::kDestination; + case BlendMode::kDestination: + return BlendMode::kSource; + case BlendMode::kSourceOver: + return BlendMode::kDestinationOver; + case BlendMode::kDestinationOver: + return BlendMode::kSourceOver; + case BlendMode::kSourceIn: + return BlendMode::kDestinationIn; + case BlendMode::kDestinationIn: + return BlendMode::kSourceIn; + case BlendMode::kSourceOut: + return BlendMode::kDestinationOut; + case BlendMode::kDestinationOut: + return BlendMode::kSourceOut; + case BlendMode::kSourceATop: + return BlendMode::kDestinationATop; + case BlendMode::kDestinationATop: + return BlendMode::kSourceATop; + case BlendMode::kXor: + return BlendMode::kXor; + case BlendMode::kPlus: + return BlendMode::kPlus; + case BlendMode::kModulate: + return BlendMode::kModulate; + default: + return std::nullopt; + } +} + BlendFilterContents::BlendFilterContents() { SetBlendMode(BlendMode::kSourceOver); } @@ -352,24 +387,6 @@ std::optional BlendFilterContents::CreateForegroundAdvancedBlend( return sub_entity; } -constexpr std::array, 15> kPorterDuffCoefficients = {{ - {0, 0, 0, 0, 0}, // Clear - {1, 0, 0, 0, 0}, // Source - {0, 0, 1, 0, 0}, // Destination - {1, 0, 1, -1, 0}, // SourceOver - {1, -1, 1, 0, 0}, // DestinationOver - {0, 1, 0, 0, 0}, // SourceIn - {0, 0, 0, 1, 0}, // DestinationIn - {1, -1, 0, 0, 0}, // SourceOut - {0, 0, 1, -1, 0}, // DestinationOut - {0, 1, 1, -1, 0}, // SourceATop - {1, -1, 0, 1, 0}, // DestinationATop - {1, -1, 1, -1, 0}, // Xor - {1, 0, 1, 0, 0}, // Plus - {0, 0, 0, 0, 1}, // Modulate - {0, 0, 1, 0, -1}, // Screen -}}; - std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( const std::shared_ptr& input, const ContentContext& renderer, @@ -423,14 +440,17 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( auto size = coverage.size; auto origin = coverage.origin; + auto color = foreground_color.Premultiply(); VertexBufferBuilder vtx_builder; vtx_builder.AddVertices({ - {origin, dst_uvs[0]}, - {Point(origin.x + size.width, origin.y), dst_uvs[1]}, - {Point(origin.x + size.width, origin.y + size.height), dst_uvs[3]}, - {origin, dst_uvs[0]}, - {Point(origin.x + size.width, origin.y + size.height), dst_uvs[3]}, - {Point(origin.x, origin.y + size.height), dst_uvs[2]}, + {origin, dst_uvs[0], color}, + {Point(origin.x + size.width, origin.y), dst_uvs[1], color}, + {Point(origin.x + size.width, origin.y + size.height), dst_uvs[3], + color}, + {origin, dst_uvs[0], color}, + {Point(origin.x + size.width, origin.y + size.height), dst_uvs[3], + color}, + {Point(origin.x, origin.y + size.height), dst_uvs[2], color}, }); auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer); @@ -456,9 +476,9 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( frame_info.texture_sampler_y_coord_scale = dst_snapshot->texture->GetYCoordScale(); - frag_info.color = foreground_color.Premultiply(); frag_info.input_alpha = absorb_opacity ? dst_snapshot->opacity * alpha.value_or(1.0) : 1.0; + frag_info.output_alpha = 1.0; auto blend_coefficients = kPorterDuffCoefficients[static_cast(blend_mode)]; diff --git a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h index fc602fb85da..f279f7f926b 100644 --- a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h +++ b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.h @@ -4,11 +4,33 @@ #pragma once +#include #include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" +#include "impeller/geometry/color.h" namespace impeller { +constexpr std::array, 15> kPorterDuffCoefficients = {{ + {0, 0, 0, 0, 0}, // Clear + {1, 0, 0, 0, 0}, // Source + {0, 0, 1, 0, 0}, // Destination + {1, 0, 1, -1, 0}, // SourceOver + {1, -1, 1, 0, 0}, // DestinationOver + {0, 1, 0, 0, 0}, // SourceIn + {0, 0, 0, 1, 0}, // DestinationIn + {1, -1, 0, 0, 0}, // SourceOut + {0, 0, 1, -1, 0}, // DestinationOut + {0, 1, 1, -1, 0}, // SourceATop + {1, -1, 0, 1, 0}, // DestinationATop + {1, -1, 1, -1, 0}, // Xor + {1, 0, 1, 0, 0}, // Plus + {0, 0, 0, 0, 1}, // Modulate + {0, 0, 1, 0, -1}, // Screen +}}; + +std::optional InvertPorterDuffBlend(BlendMode blend_mode); + class BlendFilterContents : public ColorFilterContents { public: using AdvancedBlendProc = diff --git a/engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.frag b/engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.frag index 01ba70310f1..a24b523c070 100644 --- a/engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.frag +++ b/engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.frag @@ -18,11 +18,12 @@ uniform FragInfo { float16_t dst_coeff_src_alpha; float16_t dst_coeff_src_color; float16_t input_alpha; - f16vec4 color; + float16_t output_alpha; } frag_info; in vec2 v_texture_coords; +in f16vec4 v_color; out f16vec4 frag_color; @@ -38,9 +39,10 @@ f16vec4 Sample(f16sampler2D texture_sampler, vec2 texture_coords) { void main() { f16vec4 dst = texture(texture_sampler_dst, v_texture_coords) * frag_info.input_alpha; - f16vec4 src = frag_info.color; + f16vec4 src = v_color; frag_color = src * (frag_info.src_coeff + dst.a * frag_info.src_coeff_dst_alpha) + dst * (frag_info.dst_coeff + src.a * frag_info.dst_coeff_src_alpha + src * frag_info.dst_coeff_src_color); + frag_color *= frag_info.output_alpha; } diff --git a/engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.vert b/engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.vert new file mode 100644 index 00000000000..ca266ff6686 --- /dev/null +++ b/engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.vert @@ -0,0 +1,26 @@ +// 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; + float texture_sampler_y_coord_scale; +} +frame_info; + +in vec2 vertices; +in vec2 texture_coords; +in vec4 color; + +out vec2 v_texture_coords; +out f16vec4 v_color; + +void main() { + gl_Position = frame_info.mvp * vec4(vertices, 0.0, 1.0); + v_color = f16vec4(color); + v_texture_coords = + IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale); +} diff --git a/engine/src/flutter/impeller/tools/malioc.json b/engine/src/flutter/impeller/tools/malioc.json index 540d8f6d073..a0aeed92e69 100644 --- a/engine/src/flutter/impeller/tools/malioc.json +++ b/engine/src/flutter/impeller/tools/malioc.json @@ -8963,7 +8963,7 @@ "core": "Mali-G78", "filename": "flutter/impeller/entity/gles/porter_duff_blend.frag.gles", "has_side_effects": false, - "has_uniform_computation": true, + "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", @@ -8971,20 +8971,19 @@ "uses_late_zs_update": false, "variants": { "Main": { - "fp16_arithmetic": 100, + "fp16_arithmetic": 71, "has_stack_spilling": false, "performance": { "longest_path_bound_pipelines": [ - "varying", - "texture" + "varying" ], "longest_path_cycles": [ - 0.09375, - 0.09375, + 0.21875, + 0.21875, 0.03125, 0.0, 0.0, - 0.25, + 0.5, 0.25 ], "pipelines": [ @@ -8997,35 +8996,33 @@ "texture" ], "shortest_path_bound_pipelines": [ - "varying", - "texture" + "varying" ], "shortest_path_cycles": [ - 0.09375, - 0.09375, + 0.21875, + 0.21875, 0.0, 0.0, 0.0, - 0.25, + 0.5, 0.25 ], "total_bound_pipelines": [ - "varying", - "texture" + "varying" ], "total_cycles": [ - 0.09375, - 0.09375, + 0.21875, + 0.21875, 0.03125, 0.0, 0.0, - 0.25, + 0.5, 0.25 ] }, "stack_spill_bytes": 0, "thread_occupancy": 100, - "uniform_registers_used": 10, + "uniform_registers_used": 8, "work_registers_used": 19 } } @@ -9070,7 +9067,164 @@ ] }, "thread_occupancy": 100, - "uniform_registers_used": 2, + "uniform_registers_used": 1, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/porter_duff_blend.vert.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/porter_duff_blend.vert.gles", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.140625, + 0.140625, + 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.140625, + 0.140625, + 0.0, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.140625, + 0.140625, + 0.0, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 22, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.015625, + 0.015625, + 0.015625, + 0.0, + 5.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.015625, + 0.015625, + 0.015625, + 0.0, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.015625, + 0.015625, + 0.015625, + 0.0, + 5.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 12 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/porter_duff_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.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": 6, "work_registers_used": 2 } } @@ -12298,20 +12452,19 @@ "uses_late_zs_update": false, "variants": { "Main": { - "fp16_arithmetic": 55, + "fp16_arithmetic": 100, "has_stack_spilling": false, "performance": { "longest_path_bound_pipelines": [ - "varying", - "texture" + "varying" ], "longest_path_cycles": [ - 0.140625, - 0.140625, + 0.21875, + 0.21875, 0.0, 0.0, 0.0, - 0.25, + 0.5, 0.25 ], "pipelines": [ @@ -12324,35 +12477,145 @@ "texture" ], "shortest_path_bound_pipelines": [ - "varying", - "texture" + "varying" ], "shortest_path_cycles": [ - 0.140625, - 0.140625, + 0.21875, + 0.21875, 0.0, 0.0, 0.0, - 0.25, + 0.5, 0.25 ], "total_bound_pipelines": [ - "varying", - "texture" + "varying" ], "total_cycles": [ - 0.140625, - 0.140625, + 0.21875, + 0.21875, 0.0, 0.0, 0.0, - 0.25, + 0.5, 0.25 ] }, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 14, + "work_registers_used": 11 + } + } + } + }, + "flutter/impeller/entity/porter_duff_blend.vert.vkspv": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/porter_duff_blend.vert.vkspv", + "has_uniform_computation": true, + "type": "Vertex", + "variants": { + "Position": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.125, + 0.125, + 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.125, + 0.125, + 0.0, + 0.0, + 2.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.125, + 0.125, + 0.0, + 0.0, + 2.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 30, + "work_registers_used": 32 + }, + "Varying": { + "fp16_arithmetic": 0, + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "load_store" + ], + "longest_path_cycles": [ + 0.015625, + 0.015625, + 0.015625, + 0.0, + 5.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.015625, + 0.015625, + 0.015625, + 0.0, + 5.0, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.015625, + 0.015625, + 0.015625, + 0.0, + 5.0, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 22, "work_registers_used": 10 } }