From 099512c00218a089282ddde5b6dba97e16104c42 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 24 Sep 2024 17:43:40 -0700 Subject: [PATCH 1/2] [Flutter GPU] Use vm.Vector4 for clear colors instead of ui.Color --- lib/gpu/lib/gpu.dart | 2 ++ lib/gpu/lib/src/render_pass.dart | 37 +++++++++++++++++++------------- lib/gpu/pubspec.yaml | 5 +++++ lib/gpu/render_pass.cc | 15 ++++++------- lib/gpu/render_pass.h | 5 ++++- testing/dart/gpu_test.dart | 15 +++++++++++-- 6 files changed, 52 insertions(+), 27 deletions(-) diff --git a/lib/gpu/lib/gpu.dart b/lib/gpu/lib/gpu.dart index 368585eb28dae..3fd13133dbd7e 100644 --- a/lib/gpu/lib/gpu.dart +++ b/lib/gpu/lib/gpu.dart @@ -26,6 +26,8 @@ import 'dart:typed_data'; // ignore: uri_does_not_exist import 'dart:ui' as ui; +import 'package:vector_math/vector_math.dart' as vm; + part 'src/buffer.dart'; part 'src/command_buffer.dart'; part 'src/context.dart'; diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart index 8e382a2b488a3..f301eb3b327a6 100644 --- a/lib/gpu/lib/src/render_pass.dart +++ b/lib/gpu/lib/src/render_pass.dart @@ -10,14 +10,15 @@ base class ColorAttachment { ColorAttachment({ this.loadAction = LoadAction.clear, this.storeAction = StoreAction.store, - this.clearValue = const ui.Color(0x00000000), + // TODO(bdero): Why can't vm.Vector4 constructors be const? + vm.Vector4? clearValue = null, required this.texture, this.resolveTexture = null, - }); + }) : clearValue = clearValue ?? vm.Vector4.zero(); LoadAction loadAction; StoreAction storeAction; - ui.Color clearValue; + vm.Vector4 clearValue; Texture texture; Texture? resolveTexture; @@ -121,15 +122,6 @@ base class RenderTarget { final DepthStencilAttachment? depthStencilAttachment; } -// TODO(gaaclarke): Refactor this to support wide gamut colors. -int _colorToInt(ui.Color color) { - assert(color.colorSpace == ui.ColorSpace.sRGB); - return ((color.a * 255.0).round() << 24) | - ((color.r * 255.0).round() << 16) | - ((color.g * 255.0).round() << 8) | - ((color.b * 255.0).round() << 0); -} - base class RenderPass extends NativeFieldWrapperClass1 { /// Creates a new RenderPass. RenderPass._(CommandBuffer commandBuffer, RenderTarget renderTarget) { @@ -140,7 +132,10 @@ base class RenderPass extends NativeFieldWrapperClass1 { index, color.loadAction.index, color.storeAction.index, - _colorToInt(color.clearValue), + color.clearValue.r, + color.clearValue.g, + color.clearValue.b, + color.clearValue.a, color.texture, color.resolveTexture); if (error != null) { @@ -276,13 +271,25 @@ base class RenderPass extends NativeFieldWrapperClass1 { external void _initialize(); @Native< - Handle Function(Pointer, Int, Int, Int, Int, Pointer, + Handle Function( + Pointer, + Int, + Int, + Int, + Float, + Float, + Float, + Float, + Pointer, Handle)>(symbol: 'InternalFlutterGpu_RenderPass_SetColorAttachment') external String? _setColorAttachment( int colorAttachmentIndex, int loadAction, int storeAction, - int clearColor, + double clearColorR, + double clearColorG, + double clearColorB, + double clearColorA, Texture texture, Texture? resolveTexture); diff --git a/lib/gpu/pubspec.yaml b/lib/gpu/pubspec.yaml index 56af69cc6d6c0..910d8f816abe6 100644 --- a/lib/gpu/pubspec.yaml +++ b/lib/gpu/pubspec.yaml @@ -11,5 +11,10 @@ environment: sdk: '>=3.2.0-0 <4.0.0' dependencies: + # To update these, use "flutter update-packages --force-upgrade". + # + # For detailed instructions, refer to: + # https://github.com/flutter/flutter/blob/main/docs/infra/Updating-dependencies-in-Flutter.md + vector_math: ^2.1.4 sky_engine: sdk: flutter diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index c01c554b94cef..8b920c9ffcf56 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -190,13 +190,6 @@ bool RenderPass::Draw() { } // namespace gpu } // namespace flutter -static impeller::Color ToImpellerColor(uint32_t argb) { - return impeller::Color::MakeRGBA8((argb >> 16) & 0xFF, // R - (argb >> 8) & 0xFF, // G - argb & 0xFF, // B - argb >> 24); // A -} - //---------------------------------------------------------------------------- /// Exports /// @@ -211,13 +204,17 @@ Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( int color_attachment_index, int load_action, int store_action, - int clear_color, + float clear_color_r, + float clear_color_g, + float clear_color_b, + float clear_color_a, flutter::gpu::Texture* texture, Dart_Handle resolve_texture_wrapper) { impeller::ColorAttachment desc; desc.load_action = flutter::gpu::ToImpellerLoadAction(load_action); desc.store_action = flutter::gpu::ToImpellerStoreAction(store_action); - desc.clear_color = ToImpellerColor(static_cast(clear_color)); + desc.clear_color = impeller::Color(clear_color_r, clear_color_g, + clear_color_b, clear_color_a); desc.texture = texture->GetTexture(); if (!Dart_IsNull(resolve_texture_wrapper)) { flutter::gpu::Texture* resolve_texture = diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h index 7367d0fc5bac6..4bd7a551d881f 100644 --- a/lib/gpu/render_pass.h +++ b/lib/gpu/render_pass.h @@ -105,7 +105,10 @@ extern Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( int color_attachment_index, int load_action, int store_action, - int clear_color, + float clear_color_r, + float clear_color_g, + float clear_color_b, + float clear_color_a, flutter::gpu::Texture* texture, Dart_Handle resolve_texture_wrapper); diff --git a/testing/dart/gpu_test.dart b/testing/dart/gpu_test.dart index 8810cd3063fd3..0183fd817dcd3 100644 --- a/testing/dart/gpu_test.dart +++ b/testing/dart/gpu_test.dart @@ -11,6 +11,7 @@ import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:test/test.dart'; +import 'package:vector_math/vector_math.dart'; import '../../lib/gpu/lib/gpu.dart' as gpu; @@ -41,7 +42,7 @@ class RenderPassState { } /// Create a simple RenderPass with simple color and depth-stencil attachments. -RenderPassState createSimpleRenderPass() { +RenderPassState createSimpleRenderPass({Vector4? clearColor}) { final gpu.Texture? renderTexture = gpu.gpuContext.createTexture(gpu.StorageMode.devicePrivate, 100, 100); assert(renderTexture != null); @@ -53,7 +54,7 @@ RenderPassState createSimpleRenderPass() { final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor( - gpu.ColorAttachment(texture: renderTexture!), + gpu.ColorAttachment(texture: renderTexture!, clearValue: clearColor), depthStencilAttachment: gpu.DepthStencilAttachment(texture: depthStencilTexture!)); @@ -313,6 +314,16 @@ void main() async { } }, skip: !impellerEnabled); + // Performs no draw calls. Just clears the render target to a solid green color. + test('Can render clear color', () async { + final state = createSimpleRenderPass(clearColor: Colors.lime); + + state.commandBuffer.submit(); + + final ui.Image image = state.renderTexture.asImage(); + await comparer.addGoldenImage(image, 'flutter_gpu_test_clear_color.png'); + }, skip: !impellerEnabled); + // Renders a green triangle pointing downwards. test('Can render triangle', () async { final state = createSimpleRenderPass(); From 88f82f3a498a70370811c21ae359ce7476c1b1ff Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 24 Sep 2024 18:04:33 -0700 Subject: [PATCH 2/2] Remove TODO --- lib/gpu/lib/src/render_pass.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart index f301eb3b327a6..05198723f4c71 100644 --- a/lib/gpu/lib/src/render_pass.dart +++ b/lib/gpu/lib/src/render_pass.dart @@ -10,7 +10,6 @@ base class ColorAttachment { ColorAttachment({ this.loadAction = LoadAction.clear, this.storeAction = StoreAction.store, - // TODO(bdero): Why can't vm.Vector4 constructors be const? vm.Vector4? clearValue = null, required this.texture, this.resolveTexture = null,