From f4657d2bcd1fd1d3812d6dc752de89d18f537155 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 20 Nov 2023 22:54:14 -0800 Subject: [PATCH 01/11] [Flutter GPU] Add shader libraries. --- impeller/compiler/impellerc_main.cc | 6 +- impeller/compiler/runtime_stage_data.cc | 2 +- impeller/compiler/switches.cc | 4 + impeller/compiler/switches.h | 1 + impeller/fixtures/BUILD.gn | 21 +++++ impeller/fixtures/dart_tests.dart | 8 ++ impeller/fixtures/flutter_gpu_unlit.frag | 10 ++ impeller/fixtures/flutter_gpu_unlit.vert | 12 +++ impeller/renderer/BUILD.gn | 12 +-- impeller/renderer/renderer_dart_unittests.cc | 40 ++++++-- impeller/runtime_stage/runtime_stage.cc | 12 ++- impeller/tools/impeller.gni | 4 + lib/gpu/BUILD.gn | 4 + lib/gpu/context.cc | 2 +- lib/gpu/device_buffer.cc | 2 +- lib/gpu/host_buffer.cc | 2 +- lib/gpu/lib/gpu.dart | 2 + lib/gpu/lib/src/shader.dart | 17 ++++ lib/gpu/lib/src/shader_library.dart | 38 ++++++++ lib/gpu/shader.cc | 64 +++++++++++++ lib/gpu/shader.h | 64 +++++++++++++ lib/gpu/shader_library.cc | 98 ++++++++++++++++++++ lib/gpu/shader_library.h | 73 +++++++++++++++ lib/gpu/smoketest.cc | 2 +- lib/gpu/texture.cc | 2 +- 25 files changed, 467 insertions(+), 35 deletions(-) create mode 100644 impeller/fixtures/flutter_gpu_unlit.frag create mode 100644 impeller/fixtures/flutter_gpu_unlit.vert create mode 100644 lib/gpu/lib/src/shader.dart create mode 100644 lib/gpu/lib/src/shader_library.dart create mode 100644 lib/gpu/shader.cc create mode 100644 lib/gpu/shader.h create mode 100644 lib/gpu/shader_library.cc create mode 100644 lib/gpu/shader_library.h diff --git a/impeller/compiler/impellerc_main.cc b/impeller/compiler/impellerc_main.cc index f09f323fae4f7..9c7b58b6d760b 100644 --- a/impeller/compiler/impellerc_main.cc +++ b/impeller/compiler/impellerc_main.cc @@ -8,15 +8,12 @@ #include "flutter/fml/backtrace.h" #include "flutter/fml/command_line.h" #include "flutter/fml/file.h" -#include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" -#include "impeller/base/strings.h" #include "impeller/compiler/compiler.h" #include "impeller/compiler/source_options.h" #include "impeller/compiler/switches.h" #include "impeller/compiler/types.h" #include "impeller/compiler/utilities.h" -#include "third_party/shaderc/libshaderc/include/shaderc/shaderc.hpp" namespace impeller { namespace compiler { @@ -88,7 +85,8 @@ bool Main(const fml::CommandLine& command_line) { // Generate SkSL if needed. std::shared_ptr sksl_mapping; - if (switches.iplr && TargetPlatformBundlesSkSL(switches.target_platform)) { + if (switches.iplr && TargetPlatformBundlesSkSL(switches.target_platform) && + switches.iplr_bundle.empty()) { SourceOptions sksl_options = options; sksl_options.target_platform = TargetPlatform::kSkSL; diff --git a/impeller/compiler/runtime_stage_data.cc b/impeller/compiler/runtime_stage_data.cc index 0a15de1f6f0cb..942a08963a29d 100644 --- a/impeller/compiler/runtime_stage_data.cc +++ b/impeller/compiler/runtime_stage_data.cc @@ -319,7 +319,7 @@ std::shared_ptr RuntimeStageData::CreateMapping() const { shader_->GetMapping() + shader_->GetSize()}; } // It is not an error for the SkSL to be ommitted. - if (sksl_->GetSize() > 0u) { + if (sksl_ && sksl_->GetSize() > 0u) { runtime_stage.sksl = {sksl_->GetMapping(), sksl_->GetMapping() + sksl_->GetSize()}; } diff --git a/impeller/compiler/switches.cc b/impeller/compiler/switches.cc index c539ed423228f..83c1ccaf3fb47 100644 --- a/impeller/compiler/switches.cc +++ b/impeller/compiler/switches.cc @@ -63,6 +63,9 @@ void Switches::PrintHelp(std::ostream& stream) { << std::endl; stream << "[optional] --iplr (causes --sl file to be emitted in iplr format)" << std::endl; + stream << "[optional] --iplr-bundle= (causes --sl file to be " + "emitted in the iplr bundle format)" + << std::endl; stream << "[optional] --reflection-json=" << std::endl; stream << "[optional] --reflection-header=" << std::endl; @@ -121,6 +124,7 @@ Switches::Switches(const fml::CommandLine& command_line) input_type(SourceTypeFromCommandLine(command_line)), sl_file_name(command_line.GetOptionValueWithDefault("sl", "")), iplr(command_line.HasOption("iplr")), + iplr_bundle(command_line.GetOptionValueWithDefault("iplr-bundle", "")), spirv_file_name(command_line.GetOptionValueWithDefault("spirv", "")), reflection_json_name( command_line.GetOptionValueWithDefault("reflection-json", "")), diff --git a/impeller/compiler/switches.h b/impeller/compiler/switches.h index c159f1a9cc545..c02e344fa4a88 100644 --- a/impeller/compiler/switches.h +++ b/impeller/compiler/switches.h @@ -24,6 +24,7 @@ struct Switches { SourceType input_type = SourceType::kUnknown; std::string sl_file_name = ""; bool iplr = false; + std::string iplr_bundle = ""; std::string spirv_file_name = ""; std::string reflection_json_name = ""; std::string reflection_header_name = ""; diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn index bcd37254b2327..35bd4134bca43 100644 --- a/impeller/fixtures/BUILD.gn +++ b/impeller/fixtures/BUILD.gn @@ -114,6 +114,27 @@ test_fixtures("file_fixtures") { ] } +impellerc("flutter_gpu_shaders") { + shaders = [ + # Temporarily build Flutter GPU test shaders as runtime stages. + "flutter_gpu_unlit.frag", + "flutter_gpu_unlit.vert", + ] + sl_file_extension = "iplr" + shader_target_flag = "--runtime-stage-metal" + iplr = true + iplr_bundle = "temporary" +} + +test_fixtures("flutter_gpu_fixtures") { + dart_main = "dart_tests.dart" + + fixtures = + filter_include(get_target_outputs(":flutter_gpu_shaders"), [ "*.iplr" ]) + + deps = [ ":flutter_gpu_shaders" ] +} + group("fixtures") { testonly = true diff --git a/impeller/fixtures/dart_tests.dart b/impeller/fixtures/dart_tests.dart index 2413c1b5546ce..80a4745e39ca6 100644 --- a/impeller/fixtures/dart_tests.dart +++ b/impeller/fixtures/dart_tests.dart @@ -159,3 +159,11 @@ void textureAsImageThrowsWhenNotShaderReadable() { assert(exception!.contains( 'Only shader readable Flutter GPU textures can be used as UI Images')); } + +@pragma('vm:entry-point') +void canCreateShaderLibrary() { + final gpu.ShaderLibrary? library = gpu.ShaderLibrary.fromAsset('playground'); + assert(library != null); + final gpu.Shader? shader = library!['UnlitVertex']; + assert(shader != null); +} diff --git a/impeller/fixtures/flutter_gpu_unlit.frag b/impeller/fixtures/flutter_gpu_unlit.frag new file mode 100644 index 0000000000000..fc61864108b1d --- /dev/null +++ b/impeller/fixtures/flutter_gpu_unlit.frag @@ -0,0 +1,10 @@ +// 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. + +in vec4 v_color; +out vec4 frag_color; + +void main() { + frag_color = v_color; +} diff --git a/impeller/fixtures/flutter_gpu_unlit.vert b/impeller/fixtures/flutter_gpu_unlit.vert new file mode 100644 index 0000000000000..6415b78044a74 --- /dev/null +++ b/impeller/fixtures/flutter_gpu_unlit.vert @@ -0,0 +1,12 @@ +#version 320 es + +layout(location = 0) uniform mat4 mvp; +layout(location = 1) uniform vec4 color; + +in vec2 position; +out vec4 v_color; + +void main() { + v_color = color; + gl_Position = mvp * vec4(position, 0.0, 1.0); +} diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn index a04ecd5e7ab0e..0613a36dd9c7e 100644 --- a/impeller/renderer/BUILD.gn +++ b/impeller/renderer/BUILD.gn @@ -143,15 +143,6 @@ impeller_component("renderer_unittests") { } } -test_fixtures("renderer_dart_fixtures") { - dart_main = "../fixtures/dart_tests.dart" - - fixtures = [ - "../fixtures/bay_bridge.jpg", - "../fixtures/boston.jpg", - ] -} - impeller_component("renderer_dart_unittests") { testonly = true @@ -159,8 +150,7 @@ impeller_component("renderer_dart_unittests") { deps = [ ":renderer", - ":renderer_dart_fixtures", - "../fixtures:shader_fixtures", + "../fixtures:flutter_gpu_fixtures", "../playground:playground_test", "//flutter/lib/gpu", "//flutter/runtime:runtime", diff --git a/impeller/renderer/renderer_dart_unittests.cc b/impeller/renderer/renderer_dart_unittests.cc index 89faca58540fe..9f7665ce31d0d 100644 --- a/impeller/renderer/renderer_dart_unittests.cc +++ b/impeller/renderer/renderer_dart_unittests.cc @@ -8,23 +8,18 @@ #include "flutter/common/settings.h" #include "flutter/common/task_runners.h" -#include "flutter/fml/backtrace.h" -#include "flutter/fml/command_line.h" #include "flutter/lib/gpu/context.h" -#include "flutter/lib/ui/ui_dart_state.h" +#include "flutter/lib/gpu/shader.h" +#include "flutter/lib/gpu/shader_library.h" #include "flutter/runtime/dart_isolate.h" #include "flutter/runtime/dart_vm_lifecycle.h" -#include "flutter/runtime/isolate_configuration.h" #include "flutter/testing/dart_fixture.h" #include "flutter/testing/dart_isolate_runner.h" -#include "flutter/testing/fixture_test.h" #include "flutter/testing/testing.h" -#include "impeller/fixtures/box_fade.frag.h" -#include "impeller/fixtures/box_fade.vert.h" +#include "fml/memory/ref_ptr.h" #include "impeller/playground/playground_test.h" -#include "impeller/renderer/pipeline_library.h" #include "impeller/renderer/render_pass.h" -#include "impeller/renderer/sampler_library.h" +#include "impeller/runtime_stage/runtime_stage.h" #include "gtest/gtest.h" #include "third_party/imgui/imgui.h" @@ -32,6 +27,29 @@ namespace impeller { namespace testing { +// This helper is for piggybacking on the RuntimeStage infrastructure for +// testing shaders/pipelines before the full shader bundle importer is finished. +static fml::RefPtr OpenRuntimeStageAsShader( + const std::string& fixture_name) { + auto fixture = flutter::testing::OpenFixtureAsMapping(fixture_name); + assert(fixture); + RuntimeStage stage(std::move(fixture)); + return flutter::gpu::Shader::Make( + stage.GetEntrypoint(), static_cast(stage.GetShaderStage()), + stage.GetCodeMapping(), stage.GetUniforms()); +} + +static void InstantiateTestShaderLibrary() { + flutter::gpu::ShaderLibrary::ShaderMap shaders; + shaders["UnlitVertex"] = + OpenRuntimeStageAsShader("flutter_gpu_unlit.vert.iplr"); + shaders["UnlitFragment"] = + OpenRuntimeStageAsShader("flutter_gpu_unlit.frag.iplr"); + auto library = + flutter::gpu::ShaderLibrary::MakeFromShaders(std::move(shaders)); + flutter::gpu::ShaderLibrary::SetOverride(library); +} + class RendererDartTest : public PlaygroundTest, public flutter::testing::DartFixture { public: @@ -52,6 +70,8 @@ class RendererDartTest : public PlaygroundTest, assert(GetContext() != nullptr); flutter::gpu::Context::SetOverrideContext(GetContext()); + InstantiateTestShaderLibrary(); + return isolate_.get(); } @@ -140,5 +160,7 @@ DART_TEST_CASE(textureOverwriteThrowsForWrongBufferSize); DART_TEST_CASE(textureAsImageReturnsAValidUIImageHandle); DART_TEST_CASE(textureAsImageThrowsWhenNotShaderReadable); +DART_TEST_CASE(canCreateShaderLibrary); + } // namespace testing } // namespace impeller diff --git a/impeller/runtime_stage/runtime_stage.cc b/impeller/runtime_stage/runtime_stage.cc index 919d374a3f053..786dc7a88fa24 100644 --- a/impeller/runtime_stage/runtime_stage.cc +++ b/impeller/runtime_stage/runtime_stage.cc @@ -96,11 +96,13 @@ RuntimeStage::RuntimeStage(std::shared_ptr payload) [payload = payload_](auto, auto) {} // ); - sksl_mapping_ = std::make_shared( - runtime_stage->sksl()->data(), // - runtime_stage->sksl()->size(), // - [payload = payload_](auto, auto) {} // - ); + if (runtime_stage->sksl()) { + sksl_mapping_ = std::make_shared( + runtime_stage->sksl()->data(), // + runtime_stage->sksl()->size(), // + [payload = payload_](auto, auto) {} // + ); + } is_valid_ = true; } diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni index 69bd645da1dfd..4d48704493975 100644 --- a/impeller/tools/impeller.gni +++ b/impeller/tools/impeller.gni @@ -282,6 +282,7 @@ template("impellerc") { ]) # Optional: invoker.iplr Causes --sl output to be in iplr format. + # Optional: invoker.iplr_bundle specifies a Flutter GPU shader bundle configuration. # Optional: invoker.defines specifies a list of valueless macro definitions. # Optional: invoker.intermediates_subdir specifies the subdirectory in which # to put intermediates. @@ -375,6 +376,9 @@ template("impellerc") { if (iplr) { args += [ "--iplr" ] } + if (defined(invoker.iplr_bundle)) { + args += [ "--iplr-bundle=${invoker.iplr_bundle}" ] + } outputs = [ sl_intermediate, diff --git a/lib/gpu/BUILD.gn b/lib/gpu/BUILD.gn index d24d75738458e..e91c0e4bd01e7 100644 --- a/lib/gpu/BUILD.gn +++ b/lib/gpu/BUILD.gn @@ -40,6 +40,10 @@ source_set("gpu") { "export.h", "host_buffer.cc", "host_buffer.h", + "shader.cc", + "shader.h", + "shader_library.cc", + "shader_library.h", "smoketest.cc", "smoketest.h", "texture.cc", diff --git a/lib/gpu/context.cc b/lib/gpu/context.cc index 25f663a9a4a10..e91e0d1b5a3bd 100644 --- a/lib/gpu/context.cc +++ b/lib/gpu/context.cc @@ -14,7 +14,7 @@ namespace flutter { namespace gpu { -IMPLEMENT_WRAPPERTYPEINFO(gpu, Context); +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, Context); std::shared_ptr Context::default_context_; diff --git a/lib/gpu/device_buffer.cc b/lib/gpu/device_buffer.cc index cbe07afb6b6d8..3dec0ad6ddec5 100644 --- a/lib/gpu/device_buffer.cc +++ b/lib/gpu/device_buffer.cc @@ -17,7 +17,7 @@ namespace flutter { namespace gpu { -IMPLEMENT_WRAPPERTYPEINFO(gpu, DeviceBuffer); +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, DeviceBuffer); DeviceBuffer::DeviceBuffer( std::shared_ptr device_buffer) diff --git a/lib/gpu/host_buffer.cc b/lib/gpu/host_buffer.cc index ad79d7aebe717..c92b4c873364b 100644 --- a/lib/gpu/host_buffer.cc +++ b/lib/gpu/host_buffer.cc @@ -11,7 +11,7 @@ namespace flutter { namespace gpu { -IMPLEMENT_WRAPPERTYPEINFO(gpu, HostBuffer); +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, HostBuffer); HostBuffer::HostBuffer() : host_buffer_(impeller::HostBuffer::Create()) {} diff --git a/lib/gpu/lib/gpu.dart b/lib/gpu/lib/gpu.dart index 0215900cb2b5c..d745768e66c9f 100644 --- a/lib/gpu/lib/gpu.dart +++ b/lib/gpu/lib/gpu.dart @@ -23,3 +23,5 @@ part 'src/formats.dart'; part 'src/context.dart'; part 'src/buffer.dart'; part 'src/texture.dart'; +part 'src/shader.dart'; +part 'src/shader_library.dart'; diff --git a/lib/gpu/lib/src/shader.dart b/lib/gpu/lib/src/shader.dart new file mode 100644 index 0000000000000..a0e8eff7e70a4 --- /dev/null +++ b/lib/gpu/lib/src/shader.dart @@ -0,0 +1,17 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +part of flutter_gpu; + +@pragma('vm:entry-point') +base class Shader extends NativeFieldWrapperClass1 { + // This class is created by the engine, and should not be instantiated + // or extended directly. + // + // [Shader] handles are instantiated when interacting with a [ShaderLibrary]. + @pragma('vm:entry-point') + Shader._(); +} diff --git a/lib/gpu/lib/src/shader_library.dart b/lib/gpu/lib/src/shader_library.dart new file mode 100644 index 0000000000000..551c20bc589ee --- /dev/null +++ b/lib/gpu/lib/src/shader_library.dart @@ -0,0 +1,38 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +part of flutter_gpu; + +base class ShaderLibrary extends NativeFieldWrapperClass1 { + static ShaderLibrary? fromAsset(String assetName) { + final lib = ShaderLibrary._(); + final error = lib._initializeWithAsset(assetName); + if (error != null) { + throw Exception("Failed to initialize ShaderLibrary: ${error}"); + } + return lib; + } + + ShaderLibrary._(); + + Shader? operator [](String shaderName) { + // This `flutter_gpu` library isn't always registered as part of the builtin + // DartClassLibrary, and so we can't instantiate the Dart classes on the + // engine side. + // Providing a new wrapper to [_getShader] for wrapping the native + // counterpart (if it hasn't been wrapped already) is a hack to work around + // this. + return _getShader(shaderName, Shader._()); + } + + @Native( + symbol: 'InternalFlutterGpu_ShaderLibrary_InitializeWithAsset') + external String? _initializeWithAsset(String assetName); + + @Native, Handle, Handle)>( + symbol: 'InternalFlutterGpu_ShaderLibrary_GetShader') + external Shader? _getShader(String shaderName, Shader shaderWrapper); +} diff --git a/lib/gpu/shader.cc b/lib/gpu/shader.cc new file mode 100644 index 0000000000000..100a182c7c1c7 --- /dev/null +++ b/lib/gpu/shader.cc @@ -0,0 +1,64 @@ +// 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 "flutter/lib/gpu/shader.h" + +#include + +#include "fml/make_copyable.h" +#include "impeller/renderer/shader_library.h" + +namespace flutter { +namespace gpu { + +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, Shader); + +Shader::Shader() = default; + +Shader::~Shader() = default; + +fml::RefPtr Shader::Make( + std::string entrypoint, + impeller::ShaderStage stage, + std::shared_ptr code_mapping, + std::vector uniforms) { + auto shader = fml::MakeRefCounted(); + shader->entrypoint_ = std::move(entrypoint); + shader->stage_ = stage; + shader->code_mapping_ = std::move(code_mapping); + shader->uniforms_ = std::move(uniforms); + return shader; +} + +bool Shader::IsRegistered(Context& context) { + auto& lib = *context.GetContext()->GetShaderLibrary(); + return lib.GetFunction(entrypoint_, stage_) != nullptr; +} + +bool Shader::RegisterSync(Context& context) { + if (IsRegistered(context)) { + return true; // Already registered. + } + + auto& lib = *context.GetContext()->GetShaderLibrary(); + + std::promise promise; + auto future = promise.get_future(); + lib.RegisterFunction( + entrypoint_, stage_, code_mapping_, + fml::MakeCopyable([promise = std::move(promise)](bool result) mutable { + promise.set_value(result); + })); + if (!future.get()) { + return false; // Registration failed. + } + return true; +} + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// diff --git a/lib/gpu/shader.h b/lib/gpu/shader.h new file mode 100644 index 0000000000000..418083ba6c9c1 --- /dev/null +++ b/lib/gpu/shader.h @@ -0,0 +1,64 @@ +// 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/lib/gpu/context.h" +#include "flutter/lib/gpu/export.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "fml/memory/ref_ptr.h" +#include "impeller/core/formats.h" +#include "impeller/core/runtime_types.h" +#include "impeller/core/shader_types.h" +#include "impeller/renderer/shader_function.h" +#include "third_party/tonic/typed_data/dart_byte_data.h" + +namespace flutter { +namespace gpu { + +/// An immutable collection of shaders loaded from a shader bundle asset. +class Shader : public RefCountedDartWrappable { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(Shader); + + public: + static fml::RefPtr Make( + std::string entrypoint, + impeller::ShaderStage stage, + std::shared_ptr code_mapping, + std::vector uniforms); + + bool IsRegistered(Context& context); + + bool RegisterSync(Context& context); + + ~Shader() override; + + private: + Shader(); + + std::string entrypoint_; + impeller::ShaderStage stage_; + std::shared_ptr code_mapping_; + std::vector uniforms_; + + FML_DISALLOW_COPY_AND_ASSIGN(Shader); +}; + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +extern "C" { + +// + +} // extern "C" diff --git a/lib/gpu/shader_library.cc b/lib/gpu/shader_library.cc new file mode 100644 index 0000000000000..1dcc412fc6447 --- /dev/null +++ b/lib/gpu/shader_library.cc @@ -0,0 +1,98 @@ +// 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 "flutter/lib/gpu/shader_library.h" + +#include + +#include "dart_api.h" +#include "flutter/lib/gpu/shader.h" +#include "fml/memory/ref_ptr.h" +#include "tonic/converter/dart_converter.h" + +namespace flutter { +namespace gpu { + +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, ShaderLibrary); + +fml::RefPtr ShaderLibrary::override_shader_library_; + +fml::RefPtr ShaderLibrary::MakeFromAsset( + const std::string& name, + std::string& out_error) { + if (override_shader_library_) { + return override_shader_library_; + } + // TODO(bdero): Load the ShaderLibrary asset. + // auto res = fml::MakeRefCounted(); + out_error = "Shader bundle asset unimplemented"; + return nullptr; +} + +fml::RefPtr ShaderLibrary::MakeFromShaders(ShaderMap shaders) { + auto res = + fml::MakeRefCounted(std::move(shaders)); + return res; +} + +void ShaderLibrary::SetOverride( + fml::RefPtr override_shader_library) { + override_shader_library_ = std::move(override_shader_library); +} + +fml::RefPtr ShaderLibrary::GetShader(const std::string& shader_name, + Dart_Handle shader_wrapper) const { + auto it = shaders_.find(shader_name); + if (it == shaders_.end()) { + return nullptr; // No matching shaders. + } + auto shader = it->second; + + if (shader->dart_wrapper() == nullptr) { + shader->AssociateWithDartWrapper(shader_wrapper); + } + return shader; +} + +ShaderLibrary::ShaderLibrary(ShaderMap shaders) + : shaders_(std::move(shaders)) {} + +ShaderLibrary::~ShaderLibrary() = default; + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +Dart_Handle InternalFlutterGpu_ShaderLibrary_InitializeWithAsset( + Dart_Handle wrapper, + Dart_Handle asset_name) { + if (!Dart_IsString(asset_name)) { + return tonic::ToDart("Asset name must be a string"); + } + + std::string error; + auto res = flutter::gpu::ShaderLibrary::MakeFromAsset( + tonic::StdStringFromDart(asset_name), error); + if (!res) { + return tonic::ToDart(error); + } + res->AssociateWithDartWrapper(wrapper); + return Dart_Null(); +} + +Dart_Handle InternalFlutterGpu_ShaderLibrary_GetShader( + flutter::gpu::ShaderLibrary* wrapper, + Dart_Handle shader_name, + Dart_Handle shader_wrapper) { + FML_DCHECK(Dart_IsString(shader_name)); + auto shader = + wrapper->GetShader(tonic::StdStringFromDart(shader_name), shader_wrapper); + if (!shader) { + return Dart_Null(); + } + return tonic::ToDart(shader.get()); +} diff --git a/lib/gpu/shader_library.h b/lib/gpu/shader_library.h new file mode 100644 index 0000000000000..4a481cd469d94 --- /dev/null +++ b/lib/gpu/shader_library.h @@ -0,0 +1,73 @@ +// 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/lib/gpu/export.h" +#include "flutter/lib/gpu/shader.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "fml/memory/ref_ptr.h" +#include "impeller/renderer/shader_function.h" + +namespace flutter { +namespace gpu { + +/// An immutable collection of shaders loaded from a shader bundle asset. +class ShaderLibrary : public RefCountedDartWrappable { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(ShaderLibrary); + + public: + using ShaderMap = std::unordered_map>; + + static fml::RefPtr MakeFromAsset(const std::string& name, + std::string& out_error); + + static fml::RefPtr MakeFromShaders(ShaderMap shaders); + + /// Sets a return override for `MakeFromAsset` for testing purposes. + static void SetOverride(fml::RefPtr override_shader_library); + + fml::RefPtr GetShader(const std::string& shader_name, + Dart_Handle shader_wrapper) const; + + ~ShaderLibrary() override; + + private: + /// A global override used to inject a ShaderLibrary when running with the + /// Impeller playground. When set, `MakeFromAsset` will always just return + /// this library. + static fml::RefPtr override_shader_library_; + + ShaderMap shaders_; + + explicit ShaderLibrary(ShaderMap shaders); + + FML_DISALLOW_COPY_AND_ASSIGN(ShaderLibrary); +}; + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +extern "C" { + +FLUTTER_GPU_EXPORT +extern Dart_Handle InternalFlutterGpu_ShaderLibrary_InitializeWithAsset( + Dart_Handle wrapper, + Dart_Handle asset_name); + +FLUTTER_GPU_EXPORT +extern Dart_Handle InternalFlutterGpu_ShaderLibrary_GetShader( + flutter::gpu::ShaderLibrary* wrapper, + Dart_Handle shader_name, + Dart_Handle shader_wrapper); + +} // extern "C" diff --git a/lib/gpu/smoketest.cc b/lib/gpu/smoketest.cc index 54411d7397921..e7524cd10efa5 100644 --- a/lib/gpu/smoketest.cc +++ b/lib/gpu/smoketest.cc @@ -16,7 +16,7 @@ namespace flutter { // TODO(131346): Remove this once we migrate the Dart GPU API into this space. -IMPLEMENT_WRAPPERTYPEINFO(gpu, FlutterGpuTestClass); +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, FlutterGpuTestClass); // TODO(131346): Remove this once we migrate the Dart GPU API into this space. FlutterGpuTestClass::~FlutterGpuTestClass() = default; diff --git a/lib/gpu/texture.cc b/lib/gpu/texture.cc index 648af7643d6d6..eb468f423fe62 100644 --- a/lib/gpu/texture.cc +++ b/lib/gpu/texture.cc @@ -15,7 +15,7 @@ namespace flutter { namespace gpu { -IMPLEMENT_WRAPPERTYPEINFO(gpu, Texture); +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, Texture); Texture::Texture(std::shared_ptr texture) : texture_(std::move(texture)) {} From 7e222b57fe9f3cac3b078141e209a619465def94 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 21 Nov 2023 02:04:29 -0800 Subject: [PATCH 02/11] [Flutter GPU] Add CommandBuffer and RenderPass. --- impeller/fixtures/dart_tests.dart | 11 ++ impeller/renderer/renderer_dart_unittests.cc | 2 + lib/gpu/BUILD.gn | 4 + lib/gpu/command_buffer.cc | 45 ++++++++ lib/gpu/command_buffer.h | 49 +++++++++ lib/gpu/lib/gpu.dart | 6 +- lib/gpu/lib/src/command_buffer.dart | 25 +++++ lib/gpu/lib/src/context.dart | 5 + lib/gpu/lib/src/formats.dart | 37 +++++++ lib/gpu/lib/src/render_pass.dart | 90 ++++++++++++++++ lib/gpu/render_pass.cc | 104 +++++++++++++++++++ lib/gpu/render_pass.h | 77 ++++++++++++++ lib/gpu/texture.cc | 4 + lib/gpu/texture.h | 2 + 14 files changed, 459 insertions(+), 2 deletions(-) create mode 100644 lib/gpu/command_buffer.cc create mode 100644 lib/gpu/command_buffer.h create mode 100644 lib/gpu/lib/src/command_buffer.dart create mode 100644 lib/gpu/lib/src/render_pass.dart create mode 100644 lib/gpu/render_pass.cc create mode 100644 lib/gpu/render_pass.h diff --git a/impeller/fixtures/dart_tests.dart b/impeller/fixtures/dart_tests.dart index 80a4745e39ca6..4449ae3e9c465 100644 --- a/impeller/fixtures/dart_tests.dart +++ b/impeller/fixtures/dart_tests.dart @@ -167,3 +167,14 @@ void canCreateShaderLibrary() { final gpu.Shader? shader = library!['UnlitVertex']; assert(shader != null); } + +@pragma('vm:entry-point') +void canCreateRenderPass() { + final gpu.Texture? renderTexture = + gpu.gpuContext.createTexture(gpu.StorageMode.devicePrivate, 100, 100); + assert(renderTexture != null); + + final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); + final gpu.RenderPass renderPass = commandBuffer.createRenderPass( + colorAttachment: gpu.ColorAttachment(texture: renderTexture!)); +} diff --git a/impeller/renderer/renderer_dart_unittests.cc b/impeller/renderer/renderer_dart_unittests.cc index 9f7665ce31d0d..67b37edb0401d 100644 --- a/impeller/renderer/renderer_dart_unittests.cc +++ b/impeller/renderer/renderer_dart_unittests.cc @@ -162,5 +162,7 @@ DART_TEST_CASE(textureAsImageThrowsWhenNotShaderReadable); DART_TEST_CASE(canCreateShaderLibrary); +DART_TEST_CASE(canCreateRenderPass); + } // namespace testing } // namespace impeller diff --git a/lib/gpu/BUILD.gn b/lib/gpu/BUILD.gn index e91c0e4bd01e7..5d5478b0e5d82 100644 --- a/lib/gpu/BUILD.gn +++ b/lib/gpu/BUILD.gn @@ -32,6 +32,8 @@ source_set("gpu") { if (!is_fuchsia) { sources = [ + "command_buffer.cc", + "command_buffer.h", "context.cc", "context.h", "device_buffer.cc", @@ -40,6 +42,8 @@ source_set("gpu") { "export.h", "host_buffer.cc", "host_buffer.h", + "render_pass.cc", + "render_pass.h", "shader.cc", "shader.h", "shader_library.cc", diff --git a/lib/gpu/command_buffer.cc b/lib/gpu/command_buffer.cc new file mode 100644 index 0000000000000..44a6707cbc9f0 --- /dev/null +++ b/lib/gpu/command_buffer.cc @@ -0,0 +1,45 @@ +// 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 "flutter/lib/gpu/command_buffer.h" + +#include "flutter/lib/ui/painting/image.h" +#include "fml/mapping.h" +#include "impeller/core/allocator.h" +#include "impeller/core/formats.h" +#include "impeller/display_list/dl_image_impeller.h" +#include "impeller/renderer/command_buffer.h" +#include "third_party/tonic/typed_data/dart_byte_data.h" + +namespace flutter { +namespace gpu { + +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, CommandBuffer); + +CommandBuffer::CommandBuffer( + std::shared_ptr command_buffer) + : command_buffer_(std::move(command_buffer)) {} + +std::shared_ptr CommandBuffer::GetCommandBuffer() { + return command_buffer_; +} + +CommandBuffer::~CommandBuffer() = default; + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +bool InternalFlutterGpu_CommandBuffer_Initialize( + Dart_Handle wrapper, + flutter::gpu::Context* contextWrapper) { + auto res = fml::MakeRefCounted( + contextWrapper->GetContext()->CreateCommandBuffer()); + res->AssociateWithDartWrapper(wrapper); + + return true; +} diff --git a/lib/gpu/command_buffer.h b/lib/gpu/command_buffer.h new file mode 100644 index 0000000000000..40d88d40ffb85 --- /dev/null +++ b/lib/gpu/command_buffer.h @@ -0,0 +1,49 @@ +// 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/lib/gpu/context.h" +#include "flutter/lib/gpu/export.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "impeller/core/formats.h" +#include "impeller/renderer/command_buffer.h" +#include "third_party/tonic/typed_data/dart_byte_data.h" + +namespace flutter { +namespace gpu { + +class CommandBuffer : public RefCountedDartWrappable { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(CommandBuffer); + + public: + explicit CommandBuffer( + std::shared_ptr command_buffer); + + std::shared_ptr GetCommandBuffer(); + + ~CommandBuffer() override; + + private: + std::shared_ptr command_buffer_; + + FML_DISALLOW_COPY_AND_ASSIGN(CommandBuffer); +}; + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +extern "C" { + +FLUTTER_GPU_EXPORT +extern bool InternalFlutterGpu_CommandBuffer_Initialize( + Dart_Handle wrapper, + flutter::gpu::Context* contextWrapper); + +} // extern "C" diff --git a/lib/gpu/lib/gpu.dart b/lib/gpu/lib/gpu.dart index d745768e66c9f..34d1fdfffe8d7 100644 --- a/lib/gpu/lib/gpu.dart +++ b/lib/gpu/lib/gpu.dart @@ -19,9 +19,11 @@ import 'dart:ui' as ui; export 'src/smoketest.dart'; -part 'src/formats.dart'; -part 'src/context.dart'; part 'src/buffer.dart'; +part 'src/command_buffer.dart'; +part 'src/context.dart'; +part 'src/formats.dart'; part 'src/texture.dart'; +part 'src/render_pass.dart'; part 'src/shader.dart'; part 'src/shader_library.dart'; diff --git a/lib/gpu/lib/src/command_buffer.dart b/lib/gpu/lib/src/command_buffer.dart new file mode 100644 index 0000000000000..3d5dc31544b79 --- /dev/null +++ b/lib/gpu/lib/src/command_buffer.dart @@ -0,0 +1,25 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +part of flutter_gpu; + +base class CommandBuffer extends NativeFieldWrapperClass1 { + /// Creates a new CommandBuffer. + CommandBuffer._(GpuContext gpuContext) { + _initialize(gpuContext); + } + + RenderPass createRenderPass( + {required ColorAttachment colorAttachment, + StencilAttachment? stencilAttachment = null}) { + return RenderPass._(this, colorAttachment, stencilAttachment); + } + + /// Wrap with native counterpart. + @Native)>( + symbol: 'InternalFlutterGpu_CommandBuffer_Initialize') + external bool _initialize(GpuContext gpuContext); +} diff --git a/lib/gpu/lib/src/context.dart b/lib/gpu/lib/src/context.dart index 3963211a4ebc5..01d5a169e6647 100644 --- a/lib/gpu/lib/src/context.dart +++ b/lib/gpu/lib/src/context.dart @@ -94,6 +94,11 @@ base class GpuContext extends NativeFieldWrapperClass1 { return result.isValid ? result : null; } + /// Create a new command buffer that can be used to submit GPU commands. + CommandBuffer createCommandBuffer() { + return CommandBuffer._(this); + } + /// Associates the default Impeller context with this Context. @Native( symbol: 'InternalFlutterGpu_Context_InitializeDefault') diff --git a/lib/gpu/lib/src/formats.dart b/lib/gpu/lib/src/formats.dart index 50256ecdc0bd5..e7338bfc30c78 100644 --- a/lib/gpu/lib/src/formats.dart +++ b/lib/gpu/lib/src/formats.dart @@ -59,3 +59,40 @@ enum TextureCoordinateSystem { /// (0, 0) is the top-left of the image with +Y going down. renderToTexture, } + +enum BlendFactor { + zero, + one, + sourceColor, + oneMinusSourceColor, + sourceAlpha, + oneMinusSourceAlpha, + destinationColor, + oneMinusDestinationColor, + destinationAlpha, + oneMinusDestinationAlpha, + sourceAlphaSaturated, + blendColor, + oneMinusBlendColor, + blendAlpha, + oneMinusBlendAlpha, +} + +enum BlendOperation { + add, + subtract, + reverseSubtract, +} + +enum LoadAction { + dontCare, + load, + clear, +} + +enum StoreAction { + dontCare, + store, + multisampleResolve, + storeAndMultisampleResolve, +} diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart new file mode 100644 index 0000000000000..2b8318de41df1 --- /dev/null +++ b/lib/gpu/lib/src/render_pass.dart @@ -0,0 +1,90 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +part of flutter_gpu; + +base class ColorAttachment { + ColorAttachment( + {this.loadAction = LoadAction.clear, + this.storeAction = StoreAction.store, + this.clearColor = const ui.Color(0), + required this.texture, + this.resolveTexture = null}); + + LoadAction loadAction; + StoreAction storeAction; + ui.Color clearColor; + Texture texture; + Texture? resolveTexture; +} + +base class StencilAttachment { + StencilAttachment( + {this.loadAction = LoadAction.clear, + this.storeAction = StoreAction.dontCare, + this.clearStencil = 0, + required this.texture}); + + LoadAction loadAction; + StoreAction storeAction; + int clearStencil; + Texture texture; +} + +/// A descriptor for RenderPass creation. Defines the output targets for raster +/// pipelines. +base class RenderTarget {} + +base class RenderPass extends NativeFieldWrapperClass1 { + /// Creates a new RenderPass. + RenderPass._(CommandBuffer commandBuffer, ColorAttachment colorAttachment, + StencilAttachment? stencilAttachment) { + _initialize(commandBuffer); + String? error; + error = _setColorAttachment( + colorAttachment.loadAction.index, + colorAttachment.storeAction.index, + colorAttachment.clearColor.value, + colorAttachment.texture, + colorAttachment.resolveTexture); + if (error != null) { + throw Exception(error); + } + if (stencilAttachment != null) { + error = _setStencilAttachment( + stencilAttachment.loadAction.index, + stencilAttachment.storeAction.index, + stencilAttachment.clearStencil, + stencilAttachment.texture); + if (error != null) { + throw Exception(error); + } + } + error = _begin(); + if (error != null) { + throw Exception(error); + } + } + + /// Wrap with native counterpart. + @Native)>( + symbol: 'InternalFlutterGpu_RenderPass_Initialize') + external void _initialize(CommandBuffer commandBuffer); + + @Native, Int, Int, Int, Pointer, Handle)>( + symbol: 'InternalFlutterGpu_RenderPass_SetColorAttachment') + external String? _setColorAttachment(int loadAction, int storeAction, + int clearColor, Texture texture, Texture? resolveTexture); + + @Native, Int, Int, Int, Pointer)>( + symbol: 'InternalFlutterGpu_RenderPass_SetStencilAttachment') + external String? _setStencilAttachment( + int loadAction, int storeAction, int clearStencil, Texture texture); + + @Native)>( + symbol: 'InternalFlutterGpu_RenderPass_Begin') + external String? _begin(); +} diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc new file mode 100644 index 0000000000000..f97ad10196a63 --- /dev/null +++ b/lib/gpu/render_pass.cc @@ -0,0 +1,104 @@ +// 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 "flutter/lib/gpu/render_pass.h" + +#include "dart_api.h" +#include "impeller/core/formats.h" +#include "impeller/geometry/color.h" +#include "tonic/converter/dart_converter.h" + +namespace flutter { +namespace gpu { + +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, RenderPass); + +RenderPass::RenderPass(std::weak_ptr command_buffer) + : command_buffer_(std::move(command_buffer)) {} + +impeller::Command& RenderPass::GetCommand() { + return command_; +} + +impeller::RenderTarget& RenderPass::GetRenderTarget() { + return render_target_; +} + +bool RenderPass::Begin() { + auto buffer = command_buffer_.lock(); + if (!buffer) { + return false; + } + render_pass_ = buffer->CreateRenderPass(render_target_); + return !!render_pass_; +} + +RenderPass::~RenderPass() = default; + +} // 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 +/// + +void InternalFlutterGpu_RenderPass_Initialize( + Dart_Handle wrapper, + flutter::gpu::CommandBuffer* command_buffer_wrapper) { + auto res = fml::MakeRefCounted( + command_buffer_wrapper->GetCommandBuffer()); + res->AssociateWithDartWrapper(wrapper); +} + +Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( + flutter::gpu::RenderPass* wrapper, + int load_action, + int store_action, + int clear_color, + flutter::gpu::Texture* texture, + Dart_Handle resolve_texture_wrapper) { + impeller::ColorAttachment desc; + desc.load_action = static_cast(load_action); + desc.store_action = static_cast(store_action); + desc.clear_color = ToImpellerColor(static_cast(clear_color)); + desc.texture = texture->GetTexture(); + if (!Dart_IsNull(resolve_texture_wrapper)) { + flutter::gpu::Texture* resolve_texture = + tonic::DartConverter::FromDart( + resolve_texture_wrapper); + desc.resolve_texture = resolve_texture->GetTexture(); + } + wrapper->GetRenderTarget().SetColorAttachment(desc, 0); + return Dart_Null(); +} + +Dart_Handle InternalFlutterGpu_RenderPass_SetStencilAttachment( + flutter::gpu::RenderPass* wrapper, + int load_action, + int store_action, + int clear_stencil, + flutter::gpu::Texture* texture) { + impeller::StencilAttachment desc; + desc.load_action = static_cast(load_action); + desc.store_action = static_cast(store_action); + desc.clear_stencil = clear_stencil; + desc.texture = texture->GetTexture(); + wrapper->GetRenderTarget().SetStencilAttachment(desc); + return Dart_Null(); +} + +Dart_Handle InternalFlutterGpu_RenderPass_Begin( + flutter::gpu::RenderPass* wrapper) { + if (!wrapper->Begin()) { + return tonic::ToDart("Failed to begin RenderPass"); + } + return Dart_Null(); +} diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h new file mode 100644 index 0000000000000..81ebfebaec22e --- /dev/null +++ b/lib/gpu/render_pass.h @@ -0,0 +1,77 @@ +// 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/lib/gpu/command_buffer.h" +#include "flutter/lib/gpu/export.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "impeller/renderer/command.h" +#include "impeller/renderer/render_pass.h" +#include "impeller/renderer/render_target.h" +#include "lib/gpu/texture.h" + +namespace flutter { +namespace gpu { + +class RenderPass : public RefCountedDartWrappable { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(RenderPass); + + public: + explicit RenderPass(std::weak_ptr command_buffer); + + impeller::Command& GetCommand(); + impeller::RenderTarget& GetRenderTarget(); + + bool Begin(); + + ~RenderPass() override; + + private: + std::weak_ptr command_buffer_; + impeller::RenderTarget render_target_; + impeller::Command command_; + std::shared_ptr render_pass_; + + FML_DISALLOW_COPY_AND_ASSIGN(RenderPass); +}; + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +extern "C" { + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_Initialize( + Dart_Handle wrapper, + flutter::gpu::CommandBuffer* command_buffer_wrapper); + +FLUTTER_GPU_EXPORT +extern Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( + flutter::gpu::RenderPass* wrapper, + int load_action, + int store_action, + int clear_color, + flutter::gpu::Texture* texture, + Dart_Handle resolve_texture_wrapper); + +FLUTTER_GPU_EXPORT +extern Dart_Handle InternalFlutterGpu_RenderPass_SetStencilAttachment( + flutter::gpu::RenderPass* wrapper, + int load_action, + int store_action, + int clear_stencil, + flutter::gpu::Texture* texture); + +FLUTTER_GPU_EXPORT +extern Dart_Handle InternalFlutterGpu_RenderPass_Begin( + flutter::gpu::RenderPass* wrapper); + +} // extern "C" diff --git a/lib/gpu/texture.cc b/lib/gpu/texture.cc index eb468f423fe62..b9e20e233d2dc 100644 --- a/lib/gpu/texture.cc +++ b/lib/gpu/texture.cc @@ -22,6 +22,10 @@ Texture::Texture(std::shared_ptr texture) Texture::~Texture() = default; +std::shared_ptr Texture::GetTexture() { + return texture_; +} + void Texture::SetCoordinateSystem( impeller::TextureCoordinateSystem coordinate_system) { texture_->SetCoordinateSystem(coordinate_system); diff --git a/lib/gpu/texture.h b/lib/gpu/texture.h index f6329f936c5bb..b6105fae81b04 100644 --- a/lib/gpu/texture.h +++ b/lib/gpu/texture.h @@ -22,6 +22,8 @@ class Texture : public RefCountedDartWrappable { ~Texture() override; + std::shared_ptr GetTexture(); + void SetCoordinateSystem(impeller::TextureCoordinateSystem coordinate_system); bool Overwrite(const tonic::DartByteData& source_bytes); From 3db67ef6dfa96a9268bdb004b53331897800f3c1 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 21 Nov 2023 03:47:21 -0800 Subject: [PATCH 03/11] [Flutter GPU] Add CommandBuffer submission and completion callback --- impeller/fixtures/dart_tests.dart | 4 +- impeller/renderer/renderer_dart_unittests.cc | 2 +- lib/gpu/command_buffer.cc | 83 ++++++++++++++++++-- lib/gpu/command_buffer.h | 14 +++- lib/gpu/lib/src/command_buffer.dart | 13 +++ lib/gpu/lib/src/render_pass.dart | 14 ++-- lib/gpu/render_pass.cc | 26 +++--- lib/gpu/render_pass.h | 12 ++- 8 files changed, 130 insertions(+), 38 deletions(-) diff --git a/impeller/fixtures/dart_tests.dart b/impeller/fixtures/dart_tests.dart index 4449ae3e9c465..f532aa9cb67f6 100644 --- a/impeller/fixtures/dart_tests.dart +++ b/impeller/fixtures/dart_tests.dart @@ -169,7 +169,7 @@ void canCreateShaderLibrary() { } @pragma('vm:entry-point') -void canCreateRenderPass() { +void canCreateRenderPassAndSubmit() { final gpu.Texture? renderTexture = gpu.gpuContext.createTexture(gpu.StorageMode.devicePrivate, 100, 100); assert(renderTexture != null); @@ -177,4 +177,6 @@ void canCreateRenderPass() { final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); final gpu.RenderPass renderPass = commandBuffer.createRenderPass( colorAttachment: gpu.ColorAttachment(texture: renderTexture!)); + + commandBuffer.submit(); } diff --git a/impeller/renderer/renderer_dart_unittests.cc b/impeller/renderer/renderer_dart_unittests.cc index 67b37edb0401d..26c35053ce7ec 100644 --- a/impeller/renderer/renderer_dart_unittests.cc +++ b/impeller/renderer/renderer_dart_unittests.cc @@ -162,7 +162,7 @@ DART_TEST_CASE(textureAsImageThrowsWhenNotShaderReadable); DART_TEST_CASE(canCreateShaderLibrary); -DART_TEST_CASE(canCreateRenderPass); +DART_TEST_CASE(canCreateRenderPassAndSubmit); } // namespace testing } // namespace impeller diff --git a/lib/gpu/command_buffer.cc b/lib/gpu/command_buffer.cc index 44a6707cbc9f0..f0dd7e0234092 100644 --- a/lib/gpu/command_buffer.cc +++ b/lib/gpu/command_buffer.cc @@ -4,13 +4,12 @@ #include "flutter/lib/gpu/command_buffer.h" -#include "flutter/lib/ui/painting/image.h" -#include "fml/mapping.h" -#include "impeller/core/allocator.h" -#include "impeller/core/formats.h" -#include "impeller/display_list/dl_image_impeller.h" +#include "dart_api.h" +#include "fml/make_copyable.h" #include "impeller/renderer/command_buffer.h" -#include "third_party/tonic/typed_data/dart_byte_data.h" +#include "impeller/renderer/render_pass.h" +#include "lib/ui/ui_dart_state.h" +#include "tonic/converter/dart_converter.h" namespace flutter { namespace gpu { @@ -21,11 +20,31 @@ CommandBuffer::CommandBuffer( std::shared_ptr command_buffer) : command_buffer_(std::move(command_buffer)) {} +CommandBuffer::~CommandBuffer() = default; + std::shared_ptr CommandBuffer::GetCommandBuffer() { return command_buffer_; } -CommandBuffer::~CommandBuffer() = default; +void CommandBuffer::AddRenderPass( + std::shared_ptr render_pass) { + encodables_.push_back(std::move(render_pass)); +} + +bool CommandBuffer::Submit() { + for (auto& encodable : encodables_) { + encodable->EncodeCommands(); + } + return command_buffer_->SubmitCommands(); +} + +bool CommandBuffer::Submit( + const impeller::CommandBuffer::CompletionCallback& completion_callback) { + for (auto& encodable : encodables_) { + encodable->EncodeCommands(); + } + return command_buffer_->SubmitCommands(completion_callback); +} } // namespace gpu } // namespace flutter @@ -43,3 +62,53 @@ bool InternalFlutterGpu_CommandBuffer_Initialize( return true; } + +Dart_Handle InternalFlutterGpu_CommandBuffer_Submit( + flutter::gpu::CommandBuffer* wrapper, + Dart_Handle completion_callback) { + if (Dart_IsNull(completion_callback)) { + bool success = wrapper->Submit(); + if (!success) { + return tonic::ToDart("Failed to submit CommandBuffer"); + } + return Dart_Null(); + } + + if (!Dart_IsClosure(completion_callback)) { + return tonic::ToDart("Completion callback must be a function"); + } + + auto dart_state = flutter::UIDartState::Current(); + auto& task_runners = dart_state->GetTaskRunners(); + + auto persistent_completion_callback = + std::make_unique(dart_state, + completion_callback); + + bool success = wrapper->Submit(fml::MakeCopyable( + [callback = std::move(persistent_completion_callback), + task_runners](impeller::CommandBuffer::Status status) mutable { + bool success = status != impeller::CommandBuffer::Status::kError; + + auto ui_completion_task = fml::MakeCopyable( + [callback = std::move(callback), success]() mutable { + auto dart_state = callback->dart_state().lock(); + if (!dart_state) { + // The root isolate could have died in the meantime. + return; + } + tonic::DartState::Scope scope(dart_state); + + tonic::DartInvoke(callback->Get(), {tonic::ToDart(success)}); + + // callback is associated with the Dart isolate and must be + // deleted on the UI thread. + callback.reset(); + }); + task_runners.GetUITaskRunner()->PostTask(ui_completion_task); + })); + if (!success) { + return tonic::ToDart("Failed to submit CommandBuffer"); + } + return Dart_Null(); +} diff --git a/lib/gpu/command_buffer.h b/lib/gpu/command_buffer.h index 40d88d40ffb85..505471045bdf0 100644 --- a/lib/gpu/command_buffer.h +++ b/lib/gpu/command_buffer.h @@ -7,9 +7,7 @@ #include "flutter/lib/gpu/context.h" #include "flutter/lib/gpu/export.h" #include "flutter/lib/ui/dart_wrapper.h" -#include "impeller/core/formats.h" #include "impeller/renderer/command_buffer.h" -#include "third_party/tonic/typed_data/dart_byte_data.h" namespace flutter { namespace gpu { @@ -24,10 +22,17 @@ class CommandBuffer : public RefCountedDartWrappable { std::shared_ptr GetCommandBuffer(); + void AddRenderPass(std::shared_ptr render_pass); + + bool Submit(); + bool Submit( + const impeller::CommandBuffer::CompletionCallback& completion_callback); + ~CommandBuffer() override; private: std::shared_ptr command_buffer_; + std::vector> encodables_; FML_DISALLOW_COPY_AND_ASSIGN(CommandBuffer); }; @@ -46,4 +51,9 @@ extern bool InternalFlutterGpu_CommandBuffer_Initialize( Dart_Handle wrapper, flutter::gpu::Context* contextWrapper); +FLUTTER_GPU_EXPORT +extern Dart_Handle InternalFlutterGpu_CommandBuffer_Submit( + flutter::gpu::CommandBuffer* wrapper, + Dart_Handle completion_callback); + } // extern "C" diff --git a/lib/gpu/lib/src/command_buffer.dart b/lib/gpu/lib/src/command_buffer.dart index 3d5dc31544b79..06ff0d985bea6 100644 --- a/lib/gpu/lib/src/command_buffer.dart +++ b/lib/gpu/lib/src/command_buffer.dart @@ -6,6 +6,8 @@ part of flutter_gpu; +typedef CompletionCallback = void Function(bool success); + base class CommandBuffer extends NativeFieldWrapperClass1 { /// Creates a new CommandBuffer. CommandBuffer._(GpuContext gpuContext) { @@ -18,8 +20,19 @@ base class CommandBuffer extends NativeFieldWrapperClass1 { return RenderPass._(this, colorAttachment, stencilAttachment); } + void submit({CompletionCallback? completionCallback}) { + String? error = _submit(completionCallback); + if (error != null) { + throw Exception(error); + } + } + /// Wrap with native counterpart. @Native)>( symbol: 'InternalFlutterGpu_CommandBuffer_Initialize') external bool _initialize(GpuContext gpuContext); + + @Native, Handle)>( + symbol: 'InternalFlutterGpu_CommandBuffer_Submit') + external String? _submit(CompletionCallback? completionCallback); } diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart index 2b8318de41df1..db85d75af0502 100644 --- a/lib/gpu/lib/src/render_pass.dart +++ b/lib/gpu/lib/src/render_pass.dart @@ -42,7 +42,7 @@ base class RenderPass extends NativeFieldWrapperClass1 { /// Creates a new RenderPass. RenderPass._(CommandBuffer commandBuffer, ColorAttachment colorAttachment, StencilAttachment? stencilAttachment) { - _initialize(commandBuffer); + _initialize(); String? error; error = _setColorAttachment( colorAttachment.loadAction.index, @@ -63,16 +63,18 @@ base class RenderPass extends NativeFieldWrapperClass1 { throw Exception(error); } } - error = _begin(); + error = _begin(commandBuffer); if (error != null) { throw Exception(error); } } + + /// Wrap with native counterpart. - @Native)>( + @Native( symbol: 'InternalFlutterGpu_RenderPass_Initialize') - external void _initialize(CommandBuffer commandBuffer); + external void _initialize(); @Native, Int, Int, Int, Pointer, Handle)>( symbol: 'InternalFlutterGpu_RenderPass_SetColorAttachment') @@ -84,7 +86,7 @@ base class RenderPass extends NativeFieldWrapperClass1 { external String? _setStencilAttachment( int loadAction, int storeAction, int clearStencil, Texture texture); - @Native)>( + @Native, Pointer)>( symbol: 'InternalFlutterGpu_RenderPass_Begin') - external String? _begin(); + external String? _begin(CommandBuffer commandBuffer); } diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index f97ad10196a63..d1dd5db4bf9bf 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -14,8 +14,7 @@ namespace gpu { IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, RenderPass); -RenderPass::RenderPass(std::weak_ptr command_buffer) - : command_buffer_(std::move(command_buffer)) {} +RenderPass::RenderPass() = default; impeller::Command& RenderPass::GetCommand() { return command_; @@ -25,13 +24,14 @@ impeller::RenderTarget& RenderPass::GetRenderTarget() { return render_target_; } -bool RenderPass::Begin() { - auto buffer = command_buffer_.lock(); - if (!buffer) { +bool RenderPass::Begin(flutter::gpu::CommandBuffer& command_buffer) { + render_pass_ = + command_buffer.GetCommandBuffer()->CreateRenderPass(render_target_); + if (!render_pass_) { return false; } - render_pass_ = buffer->CreateRenderPass(render_target_); - return !!render_pass_; + command_buffer.AddRenderPass(render_pass_); + return true; } RenderPass::~RenderPass() = default; @@ -50,11 +50,8 @@ static impeller::Color ToImpellerColor(uint32_t argb) { /// Exports /// -void InternalFlutterGpu_RenderPass_Initialize( - Dart_Handle wrapper, - flutter::gpu::CommandBuffer* command_buffer_wrapper) { - auto res = fml::MakeRefCounted( - command_buffer_wrapper->GetCommandBuffer()); +void InternalFlutterGpu_RenderPass_Initialize(Dart_Handle wrapper) { + auto res = fml::MakeRefCounted(); res->AssociateWithDartWrapper(wrapper); } @@ -96,8 +93,9 @@ Dart_Handle InternalFlutterGpu_RenderPass_SetStencilAttachment( } Dart_Handle InternalFlutterGpu_RenderPass_Begin( - flutter::gpu::RenderPass* wrapper) { - if (!wrapper->Begin()) { + flutter::gpu::RenderPass* wrapper, + flutter::gpu::CommandBuffer* command_buffer) { + if (!wrapper->Begin(*command_buffer)) { return tonic::ToDart("Failed to begin RenderPass"); } return Dart_Null(); diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h index 81ebfebaec22e..5acb70f72e7c8 100644 --- a/lib/gpu/render_pass.h +++ b/lib/gpu/render_pass.h @@ -21,17 +21,16 @@ class RenderPass : public RefCountedDartWrappable { FML_FRIEND_MAKE_REF_COUNTED(RenderPass); public: - explicit RenderPass(std::weak_ptr command_buffer); + RenderPass(); impeller::Command& GetCommand(); impeller::RenderTarget& GetRenderTarget(); - bool Begin(); + bool Begin(flutter::gpu::CommandBuffer& command_buffer); ~RenderPass() override; private: - std::weak_ptr command_buffer_; impeller::RenderTarget render_target_; impeller::Command command_; std::shared_ptr render_pass_; @@ -49,9 +48,7 @@ class RenderPass : public RefCountedDartWrappable { extern "C" { FLUTTER_GPU_EXPORT -extern void InternalFlutterGpu_RenderPass_Initialize( - Dart_Handle wrapper, - flutter::gpu::CommandBuffer* command_buffer_wrapper); +extern void InternalFlutterGpu_RenderPass_Initialize(Dart_Handle wrapper); FLUTTER_GPU_EXPORT extern Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( @@ -72,6 +69,7 @@ extern Dart_Handle InternalFlutterGpu_RenderPass_SetStencilAttachment( FLUTTER_GPU_EXPORT extern Dart_Handle InternalFlutterGpu_RenderPass_Begin( - flutter::gpu::RenderPass* wrapper); + flutter::gpu::RenderPass* wrapper, + flutter::gpu::CommandBuffer* command_buffer); } // extern "C" From 39a9dedc613da34385ec0a38e3ad0d230b84fab0 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 21 Nov 2023 12:59:09 -0800 Subject: [PATCH 04/11] [Flutter GPU] Start of pipelines. --- .../entity/contents/runtime_effect_contents.h | 1 - impeller/renderer/render_pass.h | 4 +- lib/gpu/lib/gpu.dart | 1 + lib/gpu/lib/src/context.dart | 5 ++ lib/gpu/lib/src/render_pass.dart | 2 - lib/gpu/lib/src/render_pipeline.dart | 24 ++++++++ lib/gpu/render_pass.cc | 4 ++ lib/gpu/render_pass.h | 3 + lib/gpu/render_pipeline.cc | 55 ++++++++++++++++++ lib/gpu/render_pipeline.h | 58 +++++++++++++++++++ lib/gpu/shader.h | 5 -- 11 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 lib/gpu/lib/src/render_pipeline.dart create mode 100644 lib/gpu/render_pipeline.cc create mode 100644 lib/gpu/render_pipeline.h diff --git a/impeller/entity/contents/runtime_effect_contents.h b/impeller/entity/contents/runtime_effect_contents.h index 61cb4267e9bd2..ada5f582654bf 100644 --- a/impeller/entity/contents/runtime_effect_contents.h +++ b/impeller/entity/contents/runtime_effect_contents.h @@ -4,7 +4,6 @@ #pragma once -#include #include #include diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index 658eb07163636..512c152d6e0bf 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -29,6 +29,8 @@ class RenderPass { public: virtual ~RenderPass(); + const std::weak_ptr& GetContext() const; + const RenderTarget& GetRenderTarget() const; ISize GetRenderTargetSize() const; @@ -101,8 +103,6 @@ class RenderPass { RenderPass(std::weak_ptr context, const RenderTarget& target); - const std::weak_ptr& GetContext() const; - virtual void OnSetLabel(std::string label) = 0; virtual bool OnEncodeCommands(const Context& context) const = 0; diff --git a/lib/gpu/lib/gpu.dart b/lib/gpu/lib/gpu.dart index 34d1fdfffe8d7..8603811c3fd8b 100644 --- a/lib/gpu/lib/gpu.dart +++ b/lib/gpu/lib/gpu.dart @@ -25,5 +25,6 @@ part 'src/context.dart'; part 'src/formats.dart'; part 'src/texture.dart'; part 'src/render_pass.dart'; +part 'src/render_pipeline.dart'; part 'src/shader.dart'; part 'src/shader_library.dart'; diff --git a/lib/gpu/lib/src/context.dart b/lib/gpu/lib/src/context.dart index 01d5a169e6647..0905acac5a02c 100644 --- a/lib/gpu/lib/src/context.dart +++ b/lib/gpu/lib/src/context.dart @@ -99,6 +99,11 @@ base class GpuContext extends NativeFieldWrapperClass1 { return CommandBuffer._(this); } + RenderPipeline createRenderPipeline( + Shader vertexShader, Shader fragmentShader) { + return RenderPipeline._(this, vertexShader, fragmentShader); + } + /// Associates the default Impeller context with this Context. @Native( symbol: 'InternalFlutterGpu_Context_InitializeDefault') diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart index db85d75af0502..4c8120be5f456 100644 --- a/lib/gpu/lib/src/render_pass.dart +++ b/lib/gpu/lib/src/render_pass.dart @@ -69,8 +69,6 @@ base class RenderPass extends NativeFieldWrapperClass1 { } } - - /// Wrap with native counterpart. @Native( symbol: 'InternalFlutterGpu_RenderPass_Initialize') diff --git a/lib/gpu/lib/src/render_pipeline.dart b/lib/gpu/lib/src/render_pipeline.dart new file mode 100644 index 0000000000000..42e1caaaef746 --- /dev/null +++ b/lib/gpu/lib/src/render_pipeline.dart @@ -0,0 +1,24 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +part of flutter_gpu; + +base class RenderPipeline extends NativeFieldWrapperClass1 { + /// Creates a new RenderPipeline. + RenderPipeline._( + GpuContext gpuContext, Shader vertexShader, Shader fragmentShader) { + String? error = _initialize(gpuContext, vertexShader, fragmentShader); + if (error != null) { + throw Exception(error); + } + } + + /// Wrap with native counterpart. + @Native, Pointer, Pointer)>( + symbol: 'InternalFlutterGpu_RenderPipeline_Initialize') + external String? _initialize( + GpuContext gpuContext, Shader vertexShader, Shader fragmentShader); +} diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index d1dd5db4bf9bf..118001ff8a0fd 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -16,6 +16,10 @@ IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, RenderPass); RenderPass::RenderPass() = default; +const std::weak_ptr& RenderPass::GetContext() const { + return render_pass_->GetContext(); +} + impeller::Command& RenderPass::GetCommand() { return command_; } diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h index 5acb70f72e7c8..9619c2982ba4b 100644 --- a/lib/gpu/render_pass.h +++ b/lib/gpu/render_pass.h @@ -23,7 +23,10 @@ class RenderPass : public RefCountedDartWrappable { public: RenderPass(); + const std::weak_ptr& GetContext() const; + impeller::Command& GetCommand(); + impeller::RenderTarget& GetRenderTarget(); bool Begin(flutter::gpu::CommandBuffer& command_buffer); diff --git a/lib/gpu/render_pipeline.cc b/lib/gpu/render_pipeline.cc new file mode 100644 index 0000000000000..9f0490905a9a1 --- /dev/null +++ b/lib/gpu/render_pipeline.cc @@ -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. + +#include "flutter/lib/gpu/render_pipeline.h" + +#include "flutter/lib/gpu/shader.h" +#include "flutter/lib/ui/painting/image.h" +#include "fml/mapping.h" +#include "impeller/core/allocator.h" +#include "impeller/core/formats.h" +#include "impeller/display_list/dl_image_impeller.h" +#include "third_party/tonic/typed_data/dart_byte_data.h" + +namespace flutter { +namespace gpu { + +IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, RenderPipeline); + +RenderPipeline::RenderPipeline( + fml::RefPtr vertex_shader, + fml::RefPtr fragment_shader) + : vertex_shader_(std::move(vertex_shader)), + fragment_shader_(std::move(fragment_shader)) {} + +RenderPipeline::~RenderPipeline() = default; + +std::shared_ptr> +RenderPipeline::GetOrCreatePipeline(const RenderPass& render_pass) { + return nullptr; +} + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +Dart_Handle InternalFlutterGpu_RenderPipeline_Initialize( + Dart_Handle wrapper, + flutter::gpu::Context* gpu_context, + flutter::gpu::Shader* vertex_shader, + flutter::gpu::Shader* fragment_shader) { + // Lazily register the shaders synchronously if they haven't been already. + vertex_shader->RegisterSync(*gpu_context); + fragment_shader->RegisterSync(*gpu_context); + + auto res = fml::MakeRefCounted( + fml::RefPtr(vertex_shader), // + fml::RefPtr(fragment_shader)); + res->AssociateWithDartWrapper(wrapper); + + return Dart_Null(); +} diff --git a/lib/gpu/render_pipeline.h b/lib/gpu/render_pipeline.h new file mode 100644 index 0000000000000..c4e72f6d3ad44 --- /dev/null +++ b/lib/gpu/render_pipeline.h @@ -0,0 +1,58 @@ +// 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/lib/gpu/context.h" +#include "flutter/lib/gpu/export.h" +#include "flutter/lib/gpu/render_pass.h" +#include "flutter/lib/gpu/shader.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "impeller/renderer/pipeline.h" +#include "impeller/renderer/pipeline_descriptor.h" + +namespace flutter { +namespace gpu { + +class RenderPipeline : public RefCountedDartWrappable { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(RenderPipeline); + + public: + RenderPipeline(fml::RefPtr vertex_shader, + fml::RefPtr fragment_shader); + + ~RenderPipeline() override; + + /// Lookup an Impeller pipeline by building a descriptor based on the current + /// command state of the given Flutter GPU RenderPass. + std::shared_ptr> + GetOrCreatePipeline(const RenderPass& render_pass); + + private: + fml::RefPtr vertex_shader_; + fml::RefPtr fragment_shader_; + + FML_DISALLOW_COPY_AND_ASSIGN(RenderPipeline); +}; + +} // namespace gpu +} // namespace flutter + +//---------------------------------------------------------------------------- +/// Exports +/// + +extern "C" { + +FLUTTER_GPU_EXPORT +extern Dart_Handle InternalFlutterGpu_RenderPipeline_Initialize( + Dart_Handle wrapper, + flutter::gpu::Context* gpu_context, + flutter::gpu::Shader* vertex_shader, + flutter::gpu::Shader* fragment_shader); + +} // extern "C" diff --git a/lib/gpu/shader.h b/lib/gpu/shader.h index 418083ba6c9c1..7f7fee58206b6 100644 --- a/lib/gpu/shader.h +++ b/lib/gpu/shader.h @@ -6,17 +6,12 @@ #include #include -#include #include "flutter/lib/gpu/context.h" -#include "flutter/lib/gpu/export.h" #include "flutter/lib/ui/dart_wrapper.h" #include "fml/memory/ref_ptr.h" -#include "impeller/core/formats.h" #include "impeller/core/runtime_types.h" #include "impeller/core/shader_types.h" -#include "impeller/renderer/shader_function.h" -#include "third_party/tonic/typed_data/dart_byte_data.h" namespace flutter { namespace gpu { From 964dba85c962af0e0137de1fdf7e5074a58db915 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 22 Nov 2023 06:05:50 -0800 Subject: [PATCH 05/11] [Flutter GPU] Command encoding. --- impeller/fixtures/dart_tests.dart | 42 ++++- impeller/fixtures/flutter_gpu_unlit.vert | 4 + impeller/renderer/BUILD.gn | 1 + impeller/renderer/renderer_dart_unittests.cc | 26 ++- lib/gpu/BUILD.gn | 4 + lib/gpu/device_buffer.cc | 4 + lib/gpu/device_buffer.h | 2 + lib/gpu/fixtures.cc | 124 +++++++++++++ lib/gpu/fixtures.h | 42 +++++ lib/gpu/host_buffer.cc | 4 + lib/gpu/host_buffer.h | 2 + lib/gpu/lib/src/formats.dart | 9 + lib/gpu/lib/src/render_pass.dart | 80 +++++++++ lib/gpu/lib/src/render_pipeline.dart | 7 +- lib/gpu/lib/src/shader.dart | 28 ++- lib/gpu/render_pass.cc | 173 ++++++++++++++++++- lib/gpu/render_pass.h | 81 ++++++++- lib/gpu/render_pipeline.cc | 19 +- lib/gpu/render_pipeline.h | 10 +- lib/gpu/shader.cc | 42 ++++- lib/gpu/shader.h | 26 ++- lib/gpu/shader_library.cc | 48 ++++- lib/gpu/shader_library.h | 1 - 23 files changed, 735 insertions(+), 44 deletions(-) create mode 100644 lib/gpu/fixtures.cc create mode 100644 lib/gpu/fixtures.h diff --git a/impeller/fixtures/dart_tests.dart b/impeller/fixtures/dart_tests.dart index f532aa9cb67f6..8ec5229b37df9 100644 --- a/impeller/fixtures/dart_tests.dart +++ b/impeller/fixtures/dart_tests.dart @@ -168,6 +168,20 @@ void canCreateShaderLibrary() { assert(shader != null); } +gpu.RenderPipeline createUnlitRenderPipeline() { + final gpu.ShaderLibrary? library = gpu.ShaderLibrary.fromAsset('playground'); + assert(library != null); + final gpu.Shader? vertex = library!['UnlitVertex']; + assert(vertex != null); + final gpu.Shader? fragment = library['UnlitFragment']; + assert(fragment != null); + return gpu.gpuContext.createRenderPipeline(vertex!, fragment!); +} + +ByteData float32(List values) { + return Float32List.fromList(values).buffer.asByteData(); +} + @pragma('vm:entry-point') void canCreateRenderPassAndSubmit() { final gpu.Texture? renderTexture = @@ -175,8 +189,34 @@ void canCreateRenderPassAndSubmit() { assert(renderTexture != null); final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); - final gpu.RenderPass renderPass = commandBuffer.createRenderPass( + final gpu.RenderPass encoder = commandBuffer.createRenderPass( colorAttachment: gpu.ColorAttachment(texture: renderTexture!)); + final gpu.RenderPipeline pipeline = createUnlitRenderPipeline(); + encoder.bindPipeline(pipeline); + + final gpu.HostBuffer transients = gpu.HostBuffer(); + final gpu.BufferView vertices = transients.emplace(float32([ + -0.5, -0.5, // + 0.5, 0.5, // + 0.5, -0.5, // + ])); + final gpu.BufferView color = + transients.emplace(float32([0, 1, 0, 1])); // rgba + final gpu.BufferView mvp = transients.emplace(float32([ + 1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1, // + ])); + encoder.bindVertexBuffer(vertices, 3); + + final gpu.UniformSlot? colorSlot = + pipeline.vertexShader.getUniformSlot('color'); + final gpu.UniformSlot? mvpSlot = pipeline.vertexShader.getUniformSlot('mvp'); + encoder.bindUniform(mvpSlot!, mvp); + encoder.bindUniform(colorSlot!, color); + encoder.draw(); + commandBuffer.submit(); } diff --git a/impeller/fixtures/flutter_gpu_unlit.vert b/impeller/fixtures/flutter_gpu_unlit.vert index 6415b78044a74..1de82a3294fb7 100644 --- a/impeller/fixtures/flutter_gpu_unlit.vert +++ b/impeller/fixtures/flutter_gpu_unlit.vert @@ -1,3 +1,7 @@ +// 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. + #version 320 es layout(location = 0) uniform mat4 mvp; diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn index 0613a36dd9c7e..8d6a2061f9e59 100644 --- a/impeller/renderer/BUILD.gn +++ b/impeller/renderer/BUILD.gn @@ -151,6 +151,7 @@ impeller_component("renderer_dart_unittests") { deps = [ ":renderer", "../fixtures:flutter_gpu_fixtures", + "../fixtures:flutter_gpu_shaders", "../playground:playground_test", "//flutter/lib/gpu", "//flutter/runtime:runtime", diff --git a/impeller/renderer/renderer_dart_unittests.cc b/impeller/renderer/renderer_dart_unittests.cc index 26c35053ce7ec..0cc76080e82c1 100644 --- a/impeller/renderer/renderer_dart_unittests.cc +++ b/impeller/renderer/renderer_dart_unittests.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "impeller/core/shader_types.h" +#include "impeller/renderer/vertex_descriptor.h" #define FML_USED_ON_EMBEDDER #include @@ -17,6 +19,7 @@ #include "flutter/testing/dart_isolate_runner.h" #include "flutter/testing/testing.h" #include "fml/memory/ref_ptr.h" +#include "impeller/fixtures/flutter_gpu_unlit.vert.h" #include "impeller/playground/playground_test.h" #include "impeller/renderer/render_pass.h" #include "impeller/runtime_stage/runtime_stage.h" @@ -30,21 +33,32 @@ namespace testing { // This helper is for piggybacking on the RuntimeStage infrastructure for // testing shaders/pipelines before the full shader bundle importer is finished. static fml::RefPtr OpenRuntimeStageAsShader( - const std::string& fixture_name) { + const std::string& fixture_name, + std::shared_ptr vertex_desc) { auto fixture = flutter::testing::OpenFixtureAsMapping(fixture_name); assert(fixture); RuntimeStage stage(std::move(fixture)); return flutter::gpu::Shader::Make( - stage.GetEntrypoint(), static_cast(stage.GetShaderStage()), - stage.GetCodeMapping(), stage.GetUniforms()); + stage.GetEntrypoint(), ToShaderStage(stage.GetShaderStage()), + stage.GetCodeMapping(), stage.GetUniforms(), std::move(vertex_desc)); } static void InstantiateTestShaderLibrary() { flutter::gpu::ShaderLibrary::ShaderMap shaders; - shaders["UnlitVertex"] = - OpenRuntimeStageAsShader("flutter_gpu_unlit.vert.iplr"); + auto vertex_desc = std::make_shared(); + vertex_desc->SetStageInputs( + // TODO(bdero): The stage inputs need to be packed into the flatbuffer. + FlutterGpuUnlitVertexShader::kAllShaderStageInputs, + // TODO(bdero): Make the vertex attribute layout fully configurable. + // When encoding commands, allow for specifying a stride, + // type, and vertex buffer slot for each attribute. + // Provide a way to lookup vertex attribute slot locations by + // name from the shader. + FlutterGpuUnlitVertexShader::kInterleavedBufferLayout); + shaders["UnlitVertex"] = OpenRuntimeStageAsShader( + "flutter_gpu_unlit.vert.iplr", std::move(vertex_desc)); shaders["UnlitFragment"] = - OpenRuntimeStageAsShader("flutter_gpu_unlit.frag.iplr"); + OpenRuntimeStageAsShader("flutter_gpu_unlit.frag.iplr", nullptr); auto library = flutter::gpu::ShaderLibrary::MakeFromShaders(std::move(shaders)); flutter::gpu::ShaderLibrary::SetOverride(library); diff --git a/lib/gpu/BUILD.gn b/lib/gpu/BUILD.gn index 5d5478b0e5d82..b9c48610754ea 100644 --- a/lib/gpu/BUILD.gn +++ b/lib/gpu/BUILD.gn @@ -40,10 +40,14 @@ source_set("gpu") { "device_buffer.h", "export.cc", "export.h", + "fixtures.cc", + "fixtures.h", "host_buffer.cc", "host_buffer.h", "render_pass.cc", "render_pass.h", + "render_pipeline.cc", + "render_pipeline.h", "shader.cc", "shader.h", "shader_library.cc", diff --git a/lib/gpu/device_buffer.cc b/lib/gpu/device_buffer.cc index 3dec0ad6ddec5..55a12830731de 100644 --- a/lib/gpu/device_buffer.cc +++ b/lib/gpu/device_buffer.cc @@ -25,6 +25,10 @@ DeviceBuffer::DeviceBuffer( DeviceBuffer::~DeviceBuffer() = default; +std::shared_ptr DeviceBuffer::GetBuffer() { + return device_buffer_; +} + bool DeviceBuffer::Overwrite(const tonic::DartByteData& source_bytes, size_t destination_offset_in_bytes) { if (!device_buffer_->CopyHostBuffer( diff --git a/lib/gpu/device_buffer.h b/lib/gpu/device_buffer.h index df2f73ed82646..44f7ac0c11bef 100644 --- a/lib/gpu/device_buffer.h +++ b/lib/gpu/device_buffer.h @@ -22,6 +22,8 @@ class DeviceBuffer : public RefCountedDartWrappable { ~DeviceBuffer() override; + std::shared_ptr GetBuffer(); + bool Overwrite(const tonic::DartByteData& source_bytes, size_t destination_offset_in_bytes); diff --git a/lib/gpu/fixtures.cc b/lib/gpu/fixtures.cc new file mode 100644 index 0000000000000..b03a2f2e9259b --- /dev/null +++ b/lib/gpu/fixtures.cc @@ -0,0 +1,124 @@ +#include "flutter/lib/gpu/fixtures.h" + +unsigned char kFlutterGPUUnlitVertIPLR[] = { + 0x18, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4c, 0x52, 0x00, 0x00, 0x0e, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0x23, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f, + 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, + 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a, 0x75, 0x73, 0x69, 0x6e, + 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, + 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, + 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x76, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x75, 0x74, + 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x5b, 0x5b, + 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x5d, + 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x34, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x5b, 0x5b, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, + 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x76, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x0a, + 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, + 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5b, 0x5b, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x30, 0x29, + 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x74, + 0x65, 0x78, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, + 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x76, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x75, 0x74, + 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, + 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x66, 0x6c, 0x75, 0x74, 0x74, + 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, + 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, + 0x5f, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73, 0x74, 0x61, + 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, + 0x26, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x5b, 0x5b, 0x62, 0x75, + 0x66, 0x66, 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x78, 0x34, 0x26, 0x20, 0x6d, 0x76, 0x70, 0x20, 0x5b, 0x5b, + 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, 0x31, 0x29, 0x5d, 0x5d, 0x29, + 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, + 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, + 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, + 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b, + 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x76, + 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, + 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x3d, 0x20, 0x6d, 0x76, 0x70, 0x20, 0x2a, 0x20, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x28, 0x69, 0x6e, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, + 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x2c, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x14, 0x00, + 0x1c, 0x00, 0x24, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x14, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x6d, 0x76, 0x70, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x75, 0x74, + 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, + 0x74, 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, + 0x6e, 0x00, 0x00, 0x00}; + +unsigned char kFlutterGPUUnlitFragIPLR[] = { + 0x18, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4c, 0x52, 0x00, 0x00, 0x0e, 0x00, + 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe8, 0x01, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xda, 0x01, 0x00, 0x00, 0x23, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f, + 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, + 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a, 0x75, 0x73, 0x69, 0x6e, + 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, + 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, + 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, + 0x75, 0x74, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x34, 0x20, 0x66, 0x72, 0x61, 0x67, 0x5f, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x20, 0x5b, 0x5b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x30, + 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, + 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x66, 0x72, + 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, + 0x69, 0x6e, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, + 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, + 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x66, 0x72, 0x61, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, + 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, + 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, + 0x6e, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, + 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, + 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, + 0x6e, 0x28, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, + 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, + 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f, + 0x69, 0x6e, 0x5d, 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, + 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x75, 0x74, 0x20, + 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x66, 0x72, 0x61, 0x67, 0x5f, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x2e, 0x76, 0x5f, + 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, + 0x0a, 0x0a, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x75, 0x74, + 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, + 0x74, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, + 0x61, 0x69, 0x6e, 0x00}; diff --git a/lib/gpu/fixtures.h b/lib/gpu/fixtures.h new file mode 100644 index 0000000000000..13926f2c9b928 --- /dev/null +++ b/lib/gpu/fixtures.h @@ -0,0 +1,42 @@ +// 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/core/shader_types.h" + +struct FlutterGPUUnlitVertexShader { + struct PerVertexData { + impeller::Point position; // (offset 0, size 8) + }; // struct PerVertexData (size 8) + + static constexpr auto kInputPosition = impeller::ShaderStageIOSlot{ + // position + "position", // name + 0u, // attribute location + 0u, // attribute set + 0u, // attribute binding + impeller::ShaderType::kFloat, // type + 32u, // bit width of type + 2u, // vec size + 1u, // number of columns + 0u, // offset for interleaved layout + }; + + static constexpr std::array + kAllShaderStageInputs = { + &kInputPosition, // position + }; + + static constexpr auto kInterleavedLayout = impeller::ShaderStageBufferLayout{ + sizeof(PerVertexData), // stride for interleaved layout + 0u, // attribute binding + }; + static constexpr std::array + kInterleavedBufferLayout = {&kInterleavedLayout}; +}; + +constexpr unsigned int kFlutterGPUUnlitVertIPLRLength = 856; +extern unsigned char kFlutterGPUUnlitVertIPLR[]; + +constexpr unsigned int kFlutterGPUUnlitFragIPLRLength = 556; +extern unsigned char kFlutterGPUUnlitFragIPLR[]; diff --git a/lib/gpu/host_buffer.cc b/lib/gpu/host_buffer.cc index c92b4c873364b..b7edccf5318d6 100644 --- a/lib/gpu/host_buffer.cc +++ b/lib/gpu/host_buffer.cc @@ -17,6 +17,10 @@ HostBuffer::HostBuffer() : host_buffer_(impeller::HostBuffer::Create()) {} HostBuffer::~HostBuffer() = default; +std::shared_ptr HostBuffer::GetBuffer() { + return host_buffer_; +} + size_t HostBuffer::EmplaceBytes(const tonic::DartByteData& byte_data) { auto view = host_buffer_->Emplace(byte_data.data(), byte_data.length_in_bytes(), diff --git a/lib/gpu/host_buffer.h b/lib/gpu/host_buffer.h index 0662c1f9fab9d..b386bc962c23b 100644 --- a/lib/gpu/host_buffer.h +++ b/lib/gpu/host_buffer.h @@ -21,6 +21,8 @@ class HostBuffer : public RefCountedDartWrappable { ~HostBuffer() override; + std::shared_ptr GetBuffer(); + size_t EmplaceBytes(const tonic::DartByteData& byte_data); private: diff --git a/lib/gpu/lib/src/formats.dart b/lib/gpu/lib/src/formats.dart index e7338bfc30c78..56350fc63c522 100644 --- a/lib/gpu/lib/src/formats.dart +++ b/lib/gpu/lib/src/formats.dart @@ -96,3 +96,12 @@ enum StoreAction { multisampleResolve, storeAndMultisampleResolve, } + +enum ShaderStage { + unknown, + vertex, + fragment, + tessellationControl, + tessellationEvaluation, + compute, +} diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart index 4c8120be5f456..62bb90fb0f5cc 100644 --- a/lib/gpu/lib/src/render_pass.dart +++ b/lib/gpu/lib/src/render_pass.dart @@ -69,6 +69,58 @@ base class RenderPass extends NativeFieldWrapperClass1 { } } + void bindPipeline(RenderPipeline pipeline) { + _bindPipeline(pipeline); + } + + void bindVertexBuffer(BufferView bufferView, int vertexCount) { + switch (bufferView.buffer.runtimeType) { + case DeviceBuffer: + _bindVertexBufferDevice(bufferView.buffer as DeviceBuffer, + bufferView.offsetInBytes, bufferView.lengthInBytes, vertexCount); + break; + case HostBuffer: + _bindVertexBufferHost(bufferView.buffer as HostBuffer, + bufferView.offsetInBytes, bufferView.lengthInBytes, vertexCount); + break; + default: + throw Exception("Invalid buffer type"); + } + } + + void bindUniform(UniformSlot slot, BufferView bufferView) { + bool success; + switch (bufferView.buffer.runtimeType) { + case DeviceBuffer: + success = _bindUniformDevice( + slot.shaderStage.index, + slot.slotId, + bufferView.buffer as DeviceBuffer, + bufferView.offsetInBytes, + bufferView.lengthInBytes); + break; + case HostBuffer: + success = _bindUniformHost( + slot.shaderStage.index, + slot.slotId, + bufferView.buffer as HostBuffer, + bufferView.offsetInBytes, + bufferView.lengthInBytes); + break; + default: + throw Exception("Invalid buffer type"); + } + if (!success) { + throw Exception("Failed to bind uniform slot"); + } + } + + void draw() { + if (!_draw()) { + throw Exception("Failed to append draw"); + } + } + /// Wrap with native counterpart. @Native( symbol: 'InternalFlutterGpu_RenderPass_Initialize') @@ -87,4 +139,32 @@ base class RenderPass extends NativeFieldWrapperClass1 { @Native, Pointer)>( symbol: 'InternalFlutterGpu_RenderPass_Begin') external String? _begin(CommandBuffer commandBuffer); + + @Native, Pointer)>( + symbol: 'InternalFlutterGpu_RenderPass_BindPipeline') + external void _bindPipeline(RenderPipeline pipeline); + + @Native, Pointer, Int, Int, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_BindVertexBufferDevice') + external void _bindVertexBufferDevice(DeviceBuffer buffer, int offsetInBytes, + int lengthInBytes, int vertexCount); + + @Native, Pointer, Int, Int, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_BindVertexBufferHost') + external void _bindVertexBufferHost( + HostBuffer buffer, int offsetInBytes, int lengthInBytes, int vertexCount); + + @Native, Int, Int, Pointer, Int, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_BindUniformDevice') + external bool _bindUniformDevice(int stage, int slotId, DeviceBuffer buffer, + int offsetInBytes, int lengthInBytes); + + @Native, Int, Int, Pointer, Int, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_BindUniformHost') + external bool _bindUniformHost(int stage, int slotId, HostBuffer buffer, + int offsetInBytes, int lengthInBytes); + + @Native)>( + symbol: 'InternalFlutterGpu_RenderPass_Draw') + external bool _draw(); } diff --git a/lib/gpu/lib/src/render_pipeline.dart b/lib/gpu/lib/src/render_pipeline.dart index 42e1caaaef746..a8d110e29a2fd 100644 --- a/lib/gpu/lib/src/render_pipeline.dart +++ b/lib/gpu/lib/src/render_pipeline.dart @@ -9,13 +9,18 @@ part of flutter_gpu; base class RenderPipeline extends NativeFieldWrapperClass1 { /// Creates a new RenderPipeline. RenderPipeline._( - GpuContext gpuContext, Shader vertexShader, Shader fragmentShader) { + GpuContext gpuContext, Shader vertexShader, Shader fragmentShader) + : vertexShader = vertexShader, + fragmentShader = fragmentShader { String? error = _initialize(gpuContext, vertexShader, fragmentShader); if (error != null) { throw Exception(error); } } + final Shader vertexShader; + final Shader fragmentShader; + /// Wrap with native counterpart. @Native, Pointer, Pointer)>( symbol: 'InternalFlutterGpu_RenderPipeline_Initialize') diff --git a/lib/gpu/lib/src/shader.dart b/lib/gpu/lib/src/shader.dart index a0e8eff7e70a4..f5f06bbe87145 100644 --- a/lib/gpu/lib/src/shader.dart +++ b/lib/gpu/lib/src/shader.dart @@ -6,12 +6,30 @@ part of flutter_gpu; -@pragma('vm:entry-point') +base class UniformSlot { + UniformSlot(this.slotId, this.shaderStage); + + int slotId; + ShaderStage shaderStage; +} + base class Shader extends NativeFieldWrapperClass1 { - // This class is created by the engine, and should not be instantiated - // or extended directly. - // // [Shader] handles are instantiated when interacting with a [ShaderLibrary]. - @pragma('vm:entry-point') Shader._(); + + UniformSlot? getUniformSlot(String name) { + int slot = _getUniformSlot(name); + if (slot < 0) { + return null; + } + return UniformSlot(slot, ShaderStage.values[_getShaderStage()]); + } + + @Native)>( + symbol: 'InternalFlutterGpu_Shader_GetShaderStage') + external int _getShaderStage(); + + @Native, Handle)>( + symbol: 'InternalFlutterGpu_Shader_GetUniformSlot') + external int _getUniformSlot(String name); } diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index 118001ff8a0fd..9927b6cb940c4 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -5,8 +5,14 @@ #include "flutter/lib/gpu/render_pass.h" #include "dart_api.h" +#include "fml/memory/ref_ptr.h" +#include "impeller/core/buffer_view.h" #include "impeller/core/formats.h" +#include "impeller/core/shader_types.h" +#include "impeller/core/vertex_buffer.h" #include "impeller/geometry/color.h" +#include "impeller/renderer/pipeline_library.h" +#include "lib/gpu/render_pipeline.h" #include "tonic/converter/dart_converter.h" namespace flutter { @@ -14,7 +20,11 @@ namespace gpu { IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, RenderPass); -RenderPass::RenderPass() = default; +RenderPass::RenderPass() + : vertex_buffer_( + impeller::VertexBuffer{.index_type = impeller::IndexType::kNone}){}; + +RenderPass::~RenderPass() = default; const std::weak_ptr& RenderPass::GetContext() const { return render_pass_->GetContext(); @@ -24,10 +34,22 @@ impeller::Command& RenderPass::GetCommand() { return command_; } +const impeller::Command& RenderPass::GetCommand() const { + return command_; +} + impeller::RenderTarget& RenderPass::GetRenderTarget() { return render_target_; } +const impeller::RenderTarget& RenderPass::GetRenderTarget() const { + return render_target_; +} + +impeller::VertexBuffer& RenderPass::GetVertexBuffer() { + return vertex_buffer_; +} + bool RenderPass::Begin(flutter::gpu::CommandBuffer& command_buffer) { render_pass_ = command_buffer.GetCommandBuffer()->CreateRenderPass(render_target_); @@ -38,7 +60,62 @@ bool RenderPass::Begin(flutter::gpu::CommandBuffer& command_buffer) { return true; } -RenderPass::~RenderPass() = default; +void RenderPass::SetPipeline(fml::RefPtr pipeline) { + render_pipeline_ = std::move(pipeline); +} + +std::shared_ptr> +RenderPass::GetOrCreatePipeline() { + // Infer the pipeline layout based on the shape of the RenderTarget. + auto pipeline_desc = pipeline_descriptor_; + { + FML_DCHECK(render_target_.HasColorAttachment(0)) + << "The render target has no color attachment. This should never " + "happen."; + const auto& color = render_target_.GetColorAttachments().find(0)->second; + color_desc_.format = render_target_.GetRenderTargetPixelFormat(); + pipeline_desc.SetColorAttachmentDescriptor(0, color_desc_); + } + + if (auto stencil = render_target_.GetStencilAttachment()) { + pipeline_desc.SetStencilPixelFormat( + stencil->texture->GetTextureDescriptor().format); + pipeline_desc.SetStencilAttachmentDescriptors(stencil_front_desc_, + stencil_back_desc_); + } else { + pipeline_desc.ClearStencilAttachments(); + } + + if (auto depth = render_target_.GetDepthAttachment()) { + pipeline_desc.SetDepthStencilAttachmentDescriptor(depth_desc_); + } else { + pipeline_desc.ClearDepthAttachment(); + } + + auto& context = *GetContext().lock(); + + render_pipeline_->BindToPipelineDescriptor(*context.GetShaderLibrary(), + pipeline_desc); + + auto pipeline = + context.GetPipelineLibrary()->GetPipeline(pipeline_desc).Get(); + FML_DCHECK(pipeline) << "Couldn't resolve render pipeline"; + return pipeline; +} + +impeller::Command RenderPass::ProvisionRasterCommand() { + impeller::Command result = command_; + + result.pipeline = GetOrCreatePipeline(); + result.BindVertices(vertex_buffer_); + + return result; +} + +bool RenderPass::Draw() { + impeller::Command result = ProvisionRasterCommand(); + return render_pass_->AddCommand(std::move(result)); +} } // namespace gpu } // namespace flutter @@ -104,3 +181,95 @@ Dart_Handle InternalFlutterGpu_RenderPass_Begin( } return Dart_Null(); } + +void InternalFlutterGpu_RenderPass_BindPipeline( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::RenderPipeline* pipeline) { + auto ref = fml::RefPtr(pipeline); + wrapper->SetPipeline(std::move(ref)); +} + +template +static void BindVertexBuffer(flutter::gpu::RenderPass* wrapper, + TBuffer* buffer, + int offset_in_bytes, + int length_in_bytes, + int vertex_count) { + auto& vertex_buffer = wrapper->GetVertexBuffer(); + vertex_buffer.vertex_buffer = impeller::BufferView{ + .buffer = buffer->GetBuffer(), + .range = impeller::Range(offset_in_bytes, length_in_bytes), + }; + vertex_buffer.vertex_count = vertex_count; +} + +void InternalFlutterGpu_RenderPass_BindVertexBufferDevice( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::DeviceBuffer* device_buffer, + int offset_in_bytes, + int length_in_bytes, + int vertex_count) { + BindVertexBuffer(wrapper, device_buffer, offset_in_bytes, length_in_bytes, + vertex_count); +} + +void InternalFlutterGpu_RenderPass_BindVertexBufferHost( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::HostBuffer* host_buffer, + int offset_in_bytes, + int length_in_bytes, + int vertex_count) { + BindVertexBuffer(wrapper, host_buffer, offset_in_bytes, length_in_bytes, + vertex_count); +} + +template +static bool BindUniform(flutter::gpu::RenderPass* wrapper, + int stage, + int slot_id, + TBuffer* buffer, + int offset_in_bytes, + int length_in_bytes) { + // TODO(113715): Populate this metadata once GLES is able to handle + // non-struct uniform names. + std::shared_ptr metadata = + std::make_shared(); + + auto& command = wrapper->GetCommand(); + impeller::ShaderUniformSlot slot; + // Don't populate the slot name... we don't have it here and Impeller doesn't + // even use it for anything. + slot.ext_res_0 = slot_id; + return command.BindResource( + static_cast(stage), slot, metadata, + impeller::BufferView{ + .buffer = buffer->GetBuffer(), + .range = impeller::Range(offset_in_bytes, length_in_bytes), + }); +} + +bool InternalFlutterGpu_RenderPass_BindUniformDevice( + flutter::gpu::RenderPass* wrapper, + int stage, + int slot_id, + flutter::gpu::DeviceBuffer* device_buffer, + int offset_in_bytes, + int length_in_bytes) { + return BindUniform(wrapper, stage, slot_id, device_buffer, offset_in_bytes, + length_in_bytes); +} + +bool InternalFlutterGpu_RenderPass_BindUniformHost( + flutter::gpu::RenderPass* wrapper, + int stage, + int slot_id, + flutter::gpu::HostBuffer* host_buffer, + int offset_in_bytes, + int length_in_bytes) { + return BindUniform(wrapper, stage, slot_id, host_buffer, offset_in_bytes, + length_in_bytes); +} + +bool InternalFlutterGpu_RenderPass_Draw(flutter::gpu::RenderPass* wrapper) { + return wrapper->Draw(); +} diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h index 9619c2982ba4b..77bfd1e7f9b05 100644 --- a/lib/gpu/render_pass.h +++ b/lib/gpu/render_pass.h @@ -8,9 +8,14 @@ #include "flutter/lib/gpu/command_buffer.h" #include "flutter/lib/gpu/export.h" #include "flutter/lib/ui/dart_wrapper.h" +#include "fml/memory/ref_ptr.h" +#include "impeller/core/vertex_buffer.h" #include "impeller/renderer/command.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/render_target.h" +#include "lib/gpu/device_buffer.h" +#include "lib/gpu/host_buffer.h" +#include "lib/gpu/render_pipeline.h" #include "lib/gpu/texture.h" namespace flutter { @@ -23,21 +28,50 @@ class RenderPass : public RefCountedDartWrappable { public: RenderPass(); + ~RenderPass() override; + const std::weak_ptr& GetContext() const; impeller::Command& GetCommand(); + const impeller::Command& GetCommand() const; impeller::RenderTarget& GetRenderTarget(); + const impeller::RenderTarget& GetRenderTarget() const; + + impeller::VertexBuffer& GetVertexBuffer(); bool Begin(flutter::gpu::CommandBuffer& command_buffer); - ~RenderPass() override; + void SetPipeline(fml::RefPtr pipeline); + + /// Lookup an Impeller pipeline by building a descriptor based on the current + /// command state. + std::shared_ptr> + GetOrCreatePipeline(); + + impeller::Command ProvisionRasterCommand(); + + bool Draw(); private: impeller::RenderTarget render_target_; - impeller::Command command_; std::shared_ptr render_pass_; + // Command encoding state. + impeller::Command command_; + fml::RefPtr render_pipeline_; + impeller::PipelineDescriptor pipeline_descriptor_; + + // Pipeline descriptor layout state. We always keep track of this state, but + // we'll only apply it as necessary to match the RenderTarget. + impeller::ColorAttachmentDescriptor color_desc_; + impeller::StencilAttachmentDescriptor stencil_front_desc_; + impeller::StencilAttachmentDescriptor stencil_back_desc_; + impeller::DepthAttachmentDescriptor depth_desc_; + + // Command state. + impeller::VertexBuffer vertex_buffer_; + FML_DISALLOW_COPY_AND_ASSIGN(RenderPass); }; @@ -75,4 +109,47 @@ extern Dart_Handle InternalFlutterGpu_RenderPass_Begin( flutter::gpu::RenderPass* wrapper, flutter::gpu::CommandBuffer* command_buffer); +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_BindPipeline( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::RenderPipeline* pipeline); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_BindVertexBufferDevice( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::DeviceBuffer* device_buffer, + int offset_in_bytes, + int length_in_bytes, + int vertex_count); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_BindVertexBufferHost( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::HostBuffer* host_buffer, + int offset_in_bytes, + int length_in_bytes, + int vertex_count); + +FLUTTER_GPU_EXPORT +extern bool InternalFlutterGpu_RenderPass_BindUniformDevice( + flutter::gpu::RenderPass* wrapper, + int stage, + int slot_id, + flutter::gpu::DeviceBuffer* device_buffer, + int offset_in_bytes, + int length_in_bytes); + +FLUTTER_GPU_EXPORT +extern bool InternalFlutterGpu_RenderPass_BindUniformHost( + flutter::gpu::RenderPass* wrapper, + int stage, + int slot_id, + flutter::gpu::HostBuffer* host_buffer, + int offset_in_bytes, + int length_in_bytes); + +FLUTTER_GPU_EXPORT +extern bool InternalFlutterGpu_RenderPass_Draw( + flutter::gpu::RenderPass* wrapper); + } // extern "C" diff --git a/lib/gpu/render_pipeline.cc b/lib/gpu/render_pipeline.cc index 9f0490905a9a1..df93e8770ef83 100644 --- a/lib/gpu/render_pipeline.cc +++ b/lib/gpu/render_pipeline.cc @@ -5,12 +5,7 @@ #include "flutter/lib/gpu/render_pipeline.h" #include "flutter/lib/gpu/shader.h" -#include "flutter/lib/ui/painting/image.h" -#include "fml/mapping.h" -#include "impeller/core/allocator.h" -#include "impeller/core/formats.h" -#include "impeller/display_list/dl_image_impeller.h" -#include "third_party/tonic/typed_data/dart_byte_data.h" +#include "impeller/renderer/pipeline_descriptor.h" namespace flutter { namespace gpu { @@ -23,13 +18,17 @@ RenderPipeline::RenderPipeline( : vertex_shader_(std::move(vertex_shader)), fragment_shader_(std::move(fragment_shader)) {} -RenderPipeline::~RenderPipeline() = default; +void RenderPipeline::BindToPipelineDescriptor( + impeller::ShaderLibrary& library, + impeller::PipelineDescriptor& desc) { + desc.SetVertexDescriptor(vertex_shader_->GetVertexDescriptor()); -std::shared_ptr> -RenderPipeline::GetOrCreatePipeline(const RenderPass& render_pass) { - return nullptr; + desc.AddStageEntrypoint(vertex_shader_->GetFunctionFromLibrary(library)); + desc.AddStageEntrypoint(fragment_shader_->GetFunctionFromLibrary(library)); } +RenderPipeline::~RenderPipeline() = default; + } // namespace gpu } // namespace flutter diff --git a/lib/gpu/render_pipeline.h b/lib/gpu/render_pipeline.h index c4e72f6d3ad44..2980d16d22243 100644 --- a/lib/gpu/render_pipeline.h +++ b/lib/gpu/render_pipeline.h @@ -4,14 +4,10 @@ #pragma once -#include - #include "flutter/lib/gpu/context.h" #include "flutter/lib/gpu/export.h" -#include "flutter/lib/gpu/render_pass.h" #include "flutter/lib/gpu/shader.h" #include "flutter/lib/ui/dart_wrapper.h" -#include "impeller/renderer/pipeline.h" #include "impeller/renderer/pipeline_descriptor.h" namespace flutter { @@ -27,10 +23,8 @@ class RenderPipeline : public RefCountedDartWrappable { ~RenderPipeline() override; - /// Lookup an Impeller pipeline by building a descriptor based on the current - /// command state of the given Flutter GPU RenderPass. - std::shared_ptr> - GetOrCreatePipeline(const RenderPass& render_pass); + void BindToPipelineDescriptor(impeller::ShaderLibrary& library, + impeller::PipelineDescriptor& desc); private: fml::RefPtr vertex_shader_; diff --git a/lib/gpu/shader.cc b/lib/gpu/shader.cc index 100a182c7c1c7..0d6eb5d8fbc49 100644 --- a/lib/gpu/shader.cc +++ b/lib/gpu/shader.cc @@ -7,7 +7,10 @@ #include #include "fml/make_copyable.h" +#include "impeller/renderer/shader_function.h" #include "impeller/renderer/shader_library.h" +#include "lib/gpu/shader_library.h" +#include "tonic/converter/dart_converter.h" namespace flutter { namespace gpu { @@ -22,18 +25,25 @@ fml::RefPtr Shader::Make( std::string entrypoint, impeller::ShaderStage stage, std::shared_ptr code_mapping, - std::vector uniforms) { + std::vector uniforms, + std::shared_ptr vertex_desc) { auto shader = fml::MakeRefCounted(); shader->entrypoint_ = std::move(entrypoint); shader->stage_ = stage; shader->code_mapping_ = std::move(code_mapping); shader->uniforms_ = std::move(uniforms); + shader->vertex_desc_ = std::move(vertex_desc); return shader; } +std::shared_ptr Shader::GetFunctionFromLibrary( + impeller::ShaderLibrary& library) { + return library.GetFunction(entrypoint_, stage_); +} + bool Shader::IsRegistered(Context& context) { auto& lib = *context.GetContext()->GetShaderLibrary(); - return lib.GetFunction(entrypoint_, stage_) != nullptr; + return GetFunctionFromLibrary(lib) != nullptr; } bool Shader::RegisterSync(Context& context) { @@ -56,9 +66,37 @@ bool Shader::RegisterSync(Context& context) { return true; } +std::shared_ptr Shader::GetVertexDescriptor() + const { + return vertex_desc_; +} + +impeller::ShaderStage Shader::GetShaderStage() const { + return stage_; +} + +int Shader::GetUniformSlot(const std::string& name) const { + for (const auto& uniform : uniforms_) { + if (name == uniform.name) { + return uniform.location; + } + } + return -1; +} + } // namespace gpu } // namespace flutter //---------------------------------------------------------------------------- /// Exports /// + +int InternalFlutterGpu_Shader_GetShaderStage(flutter::gpu::Shader* wrapper) { + return static_cast(wrapper->GetShaderStage()); +} + +int InternalFlutterGpu_Shader_GetUniformSlot(flutter::gpu::Shader* wrapper, + Dart_Handle name_handle) { + auto name = tonic::StdStringFromDart(name_handle); + return wrapper->GetUniformSlot(name); +} diff --git a/lib/gpu/shader.h b/lib/gpu/shader.h index 7f7fee58206b6..ba453794408be 100644 --- a/lib/gpu/shader.h +++ b/lib/gpu/shader.h @@ -12,6 +12,8 @@ #include "fml/memory/ref_ptr.h" #include "impeller/core/runtime_types.h" #include "impeller/core/shader_types.h" +#include "impeller/renderer/shader_function.h" +#include "impeller/renderer/vertex_descriptor.h" namespace flutter { namespace gpu { @@ -22,17 +24,27 @@ class Shader : public RefCountedDartWrappable { FML_FRIEND_MAKE_REF_COUNTED(Shader); public: + ~Shader() override; + static fml::RefPtr Make( std::string entrypoint, impeller::ShaderStage stage, std::shared_ptr code_mapping, - std::vector uniforms); + std::vector uniforms, + std::shared_ptr vertex_desc); + + std::shared_ptr GetFunctionFromLibrary( + impeller::ShaderLibrary& library); bool IsRegistered(Context& context); bool RegisterSync(Context& context); - ~Shader() override; + std::shared_ptr GetVertexDescriptor() const; + + impeller::ShaderStage GetShaderStage() const; + + int GetUniformSlot(const std::string& name) const; private: Shader(); @@ -41,6 +53,7 @@ class Shader : public RefCountedDartWrappable { impeller::ShaderStage stage_; std::shared_ptr code_mapping_; std::vector uniforms_; + std::shared_ptr vertex_desc_; FML_DISALLOW_COPY_AND_ASSIGN(Shader); }; @@ -54,6 +67,13 @@ class Shader : public RefCountedDartWrappable { extern "C" { -// +FLUTTER_GPU_EXPORT +extern int InternalFlutterGpu_Shader_GetShaderStage( + flutter::gpu::Shader* wrapper); + +FLUTTER_GPU_EXPORT +extern int InternalFlutterGpu_Shader_GetUniformSlot( + flutter::gpu::Shader* wrapper, + Dart_Handle name_handle); } // extern "C" diff --git a/lib/gpu/shader_library.cc b/lib/gpu/shader_library.cc index 1dcc412fc6447..3abea3e574e6f 100644 --- a/lib/gpu/shader_library.cc +++ b/lib/gpu/shader_library.cc @@ -6,14 +6,51 @@ #include -#include "dart_api.h" +#include "flutter/lib/gpu/fixtures.h" #include "flutter/lib/gpu/shader.h" +#include "fml/mapping.h" #include "fml/memory/ref_ptr.h" -#include "tonic/converter/dart_converter.h" +#include "impeller/renderer/vertex_descriptor.h" +#include "impeller/runtime_stage/runtime_stage.h" namespace flutter { namespace gpu { +// ===[ BEGIN MEMES ]=========================================================== +static fml::RefPtr OpenRuntimeStageAsShader( + std::shared_ptr payload, + const std::shared_ptr& vertex_desc) { + impeller::RuntimeStage stage(std::move(payload)); + return Shader::Make(stage.GetEntrypoint(), + ToShaderStage(stage.GetShaderStage()), + stage.GetCodeMapping(), stage.GetUniforms(), vertex_desc); +} + +static void InstantiateTestShaderLibrary() { + ShaderLibrary::ShaderMap shaders; + auto vertex_desc = std::make_shared(); + vertex_desc->SetStageInputs( + // TODO(bdero): The stage inputs need to be packed into the flatbuffer. + FlutterGPUUnlitVertexShader::kAllShaderStageInputs, + // TODO(bdero): Make the vertex attribute layout fully configurable. + // When encoding commands, allow for specifying a stride, + // type, and vertex buffer slot for each attribute. + // Provide a way to lookup vertex attribute slot locations by + // name from the shader. + FlutterGPUUnlitVertexShader::kInterleavedBufferLayout); + shaders["UnlitVertex"] = OpenRuntimeStageAsShader( + std::make_shared(kFlutterGPUUnlitVertIPLR, + kFlutterGPUUnlitVertIPLRLength), + vertex_desc); + shaders["UnlitFragment"] = OpenRuntimeStageAsShader( + std::make_shared(kFlutterGPUUnlitFragIPLR, + kFlutterGPUUnlitFragIPLRLength), + nullptr); + auto library = ShaderLibrary::MakeFromShaders(std::move(shaders)); + ShaderLibrary::SetOverride(library); +} +// ===[ END MEMES ]============================================================= + IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, ShaderLibrary); fml::RefPtr ShaderLibrary::override_shader_library_; @@ -21,11 +58,16 @@ fml::RefPtr ShaderLibrary::override_shader_library_; fml::RefPtr ShaderLibrary::MakeFromAsset( const std::string& name, std::string& out_error) { + // =========================================================================== + // This is a temporary hack to get the shader library populated in the + // framework before the shader bundle format is landed! + InstantiateTestShaderLibrary(); + // =========================================================================== + if (override_shader_library_) { return override_shader_library_; } // TODO(bdero): Load the ShaderLibrary asset. - // auto res = fml::MakeRefCounted(); out_error = "Shader bundle asset unimplemented"; return nullptr; } diff --git a/lib/gpu/shader_library.h b/lib/gpu/shader_library.h index 4a481cd469d94..35fd737f7a7a1 100644 --- a/lib/gpu/shader_library.h +++ b/lib/gpu/shader_library.h @@ -11,7 +11,6 @@ #include "flutter/lib/gpu/shader.h" #include "flutter/lib/ui/dart_wrapper.h" #include "fml/memory/ref_ptr.h" -#include "impeller/renderer/shader_function.h" namespace flutter { namespace gpu { From eb9e0b7ddd18ea73d922228ebcb536f40eda1850 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 22 Nov 2023 14:09:34 -0800 Subject: [PATCH 06/11] license header --- lib/gpu/fixtures.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/gpu/fixtures.cc b/lib/gpu/fixtures.cc index b03a2f2e9259b..c85020b3b7bd3 100644 --- a/lib/gpu/fixtures.cc +++ b/lib/gpu/fixtures.cc @@ -1,5 +1,13 @@ +// 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 "flutter/lib/gpu/fixtures.h" +// These blobs are generated using xxd -i [myfile.iplr]. +// This is a temporary hack to provision the shader library before the importer +// is done. + unsigned char kFlutterGPUUnlitVertIPLR[] = { 0x18, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4c, 0x52, 0x00, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, From 3862ae6db896758ec59210c8e452f87034864dd6 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 22 Nov 2023 14:15:57 -0800 Subject: [PATCH 07/11] Licenses --- ci/licenses_golden/licenses_flutter | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 560e444e869f3..c00ccd102535f 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -5572,20 +5572,36 @@ ORIGIN: ../../../flutter/impeller/typographer/typeface.cc + ../../../flutter/LIC ORIGIN: ../../../flutter/impeller/typographer/typeface.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/typographer/typographer_context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/typographer/typographer_context.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/command_buffer.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/command_buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/context.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/device_buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/device_buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/export.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/export.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/fixtures.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/host_buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/host_buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/lib/gpu.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/lib/src/buffer.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/lib/src/command_buffer.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/lib/src/context.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/lib/src/formats.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/lib/src/render_pass.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/lib/src/render_pipeline.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/lib/src/shader.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/lib/src/shader_library.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/lib/src/smoketest.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/lib/src/texture.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/render_pass.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/render_pass.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/render_pipeline.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/render_pipeline.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/shader.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/shader.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/shader_library.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/shader_library.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/smoketest.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/smoketest.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/texture.cc + ../../../flutter/LICENSE @@ -8348,20 +8364,37 @@ FILE: ../../../flutter/impeller/typographer/typeface.cc FILE: ../../../flutter/impeller/typographer/typeface.h FILE: ../../../flutter/impeller/typographer/typographer_context.cc FILE: ../../../flutter/impeller/typographer/typographer_context.h +FILE: ../../../flutter/lib/gpu/command_buffer.cc +FILE: ../../../flutter/lib/gpu/command_buffer.h FILE: ../../../flutter/lib/gpu/context.cc FILE: ../../../flutter/lib/gpu/context.h FILE: ../../../flutter/lib/gpu/device_buffer.cc FILE: ../../../flutter/lib/gpu/device_buffer.h FILE: ../../../flutter/lib/gpu/export.cc FILE: ../../../flutter/lib/gpu/export.h +FILE: ../../../flutter/lib/gpu/fixtures.cc +FILE: ../../../flutter/lib/gpu/fixtures.h FILE: ../../../flutter/lib/gpu/host_buffer.cc FILE: ../../../flutter/lib/gpu/host_buffer.h FILE: ../../../flutter/lib/gpu/lib/gpu.dart FILE: ../../../flutter/lib/gpu/lib/src/buffer.dart +FILE: ../../../flutter/lib/gpu/lib/src/command_buffer.dart FILE: ../../../flutter/lib/gpu/lib/src/context.dart FILE: ../../../flutter/lib/gpu/lib/src/formats.dart +FILE: ../../../flutter/lib/gpu/lib/src/render_pass.dart +FILE: ../../../flutter/lib/gpu/lib/src/render_pipeline.dart +FILE: ../../../flutter/lib/gpu/lib/src/shader.dart +FILE: ../../../flutter/lib/gpu/lib/src/shader_library.dart FILE: ../../../flutter/lib/gpu/lib/src/smoketest.dart FILE: ../../../flutter/lib/gpu/lib/src/texture.dart +FILE: ../../../flutter/lib/gpu/render_pass.cc +FILE: ../../../flutter/lib/gpu/render_pass.h +FILE: ../../../flutter/lib/gpu/render_pipeline.cc +FILE: ../../../flutter/lib/gpu/render_pipeline.h +FILE: ../../../flutter/lib/gpu/shader.cc +FILE: ../../../flutter/lib/gpu/shader.h +FILE: ../../../flutter/lib/gpu/shader_library.cc +FILE: ../../../flutter/lib/gpu/shader_library.h FILE: ../../../flutter/lib/gpu/smoketest.cc FILE: ../../../flutter/lib/gpu/smoketest.h FILE: ../../../flutter/lib/gpu/texture.cc From 40da2c09299167d3d756558e35485187441a8f8b Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 22 Nov 2023 14:17:46 -0800 Subject: [PATCH 08/11] build fail --- lib/gpu/render_pass.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index 9927b6cb940c4..cc28aa827325f 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -72,7 +72,6 @@ RenderPass::GetOrCreatePipeline() { FML_DCHECK(render_target_.HasColorAttachment(0)) << "The render target has no color attachment. This should never " "happen."; - const auto& color = render_target_.GetColorAttachments().find(0)->second; color_desc_.format = render_target_.GetRenderTargetPixelFormat(); pipeline_desc.SetColorAttachmentDescriptor(0, color_desc_); } From d5bc6132994e41ae75a3870db14a8546699ccc45 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Fri, 24 Nov 2023 03:14:36 -0800 Subject: [PATCH 09/11] Build failures --- impeller/renderer/renderer_dart_unittests.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/impeller/renderer/renderer_dart_unittests.cc b/impeller/renderer/renderer_dart_unittests.cc index 0cc76080e82c1..7e413346cc9a0 100644 --- a/impeller/renderer/renderer_dart_unittests.cc +++ b/impeller/renderer/renderer_dart_unittests.cc @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "impeller/core/shader_types.h" -#include "impeller/renderer/vertex_descriptor.h" #define FML_USED_ON_EMBEDDER #include @@ -19,9 +17,11 @@ #include "flutter/testing/dart_isolate_runner.h" #include "flutter/testing/testing.h" #include "fml/memory/ref_ptr.h" +#include "impeller/core/shader_types.h" #include "impeller/fixtures/flutter_gpu_unlit.vert.h" #include "impeller/playground/playground_test.h" #include "impeller/renderer/render_pass.h" +#include "impeller/renderer/vertex_descriptor.h" #include "impeller/runtime_stage/runtime_stage.h" #include "gtest/gtest.h" From 73cf7e12b4badf5c804b31faf52a735de9db9548 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Fri, 24 Nov 2023 08:50:04 -0800 Subject: [PATCH 10/11] Licenses --- ci/licenses_golden/licenses_flutter | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index c00ccd102535f..c6fac15abab7e 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -5580,6 +5580,7 @@ ORIGIN: ../../../flutter/lib/gpu/device_buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/device_buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/export.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/export.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/fixtures.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/fixtures.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/host_buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/host_buffer.h + ../../../flutter/LICENSE From 9c2265816b4543133402b5da2f3465366352c164 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Fri, 24 Nov 2023 17:11:44 -0800 Subject: [PATCH 11/11] Jonah review --- ci/licenses_golden/licenses_flutter | 4 + lib/gpu/BUILD.gn | 2 + lib/gpu/context.cc | 17 +- lib/gpu/device_buffer.cc | 4 +- lib/gpu/formats.cc | 13 ++ lib/gpu/formats.h | 288 ++++++++++++++++++++++++++++ lib/gpu/lib/src/buffer.dart | 36 +++- lib/gpu/lib/src/formats.dart | 8 +- lib/gpu/lib/src/render_pass.dart | 39 +--- lib/gpu/lib/src/shader.dart | 6 +- lib/gpu/render_pass.cc | 20 +- lib/gpu/texture.cc | 16 +- 12 files changed, 390 insertions(+), 63 deletions(-) create mode 100644 lib/gpu/formats.cc create mode 100644 lib/gpu/formats.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index c6fac15abab7e..8b437f782eb2b 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -5582,6 +5582,8 @@ ORIGIN: ../../../flutter/lib/gpu/export.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/export.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/fixtures.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/fixtures.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/formats.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/gpu/formats.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/host_buffer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/host_buffer.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/gpu/lib/gpu.dart + ../../../flutter/LICENSE @@ -8375,6 +8377,8 @@ FILE: ../../../flutter/lib/gpu/export.cc FILE: ../../../flutter/lib/gpu/export.h FILE: ../../../flutter/lib/gpu/fixtures.cc FILE: ../../../flutter/lib/gpu/fixtures.h +FILE: ../../../flutter/lib/gpu/formats.cc +FILE: ../../../flutter/lib/gpu/formats.h FILE: ../../../flutter/lib/gpu/host_buffer.cc FILE: ../../../flutter/lib/gpu/host_buffer.h FILE: ../../../flutter/lib/gpu/lib/gpu.dart diff --git a/lib/gpu/BUILD.gn b/lib/gpu/BUILD.gn index b9c48610754ea..b26dc419dc864 100644 --- a/lib/gpu/BUILD.gn +++ b/lib/gpu/BUILD.gn @@ -42,6 +42,8 @@ source_set("gpu") { "export.h", "fixtures.cc", "fixtures.h", + "formats.cc", + "formats.h", "host_buffer.cc", "host_buffer.h", "render_pass.cc", diff --git a/lib/gpu/context.cc b/lib/gpu/context.cc index e91e0d1b5a3bd..03536ef352d56 100644 --- a/lib/gpu/context.cc +++ b/lib/gpu/context.cc @@ -6,7 +6,7 @@ #include -#include "dart_api.h" +#include "flutter/lib/gpu/formats.h" #include "flutter/lib/ui/ui_dart_state.h" #include "fml/make_copyable.h" #include "tonic/converter/dart_converter.h" @@ -76,21 +76,22 @@ Dart_Handle InternalFlutterGpu_Context_InitializeDefault(Dart_Handle wrapper) { return Dart_Null(); } -/// extern int InternalFlutterGpu_Context_GetDefaultColorFormat( flutter::gpu::Context* wrapper) { - return static_cast( - wrapper->GetContext()->GetCapabilities()->GetDefaultColorFormat()); + return static_cast(flutter::gpu::FromImpellerPixelFormat( + wrapper->GetContext()->GetCapabilities()->GetDefaultColorFormat())); } extern int InternalFlutterGpu_Context_GetDefaultStencilFormat( flutter::gpu::Context* wrapper) { - return static_cast( - wrapper->GetContext()->GetCapabilities()->GetDefaultStencilFormat()); + return static_cast(flutter::gpu::FromImpellerPixelFormat( + wrapper->GetContext()->GetCapabilities()->GetDefaultStencilFormat())); } extern int InternalFlutterGpu_Context_GetDefaultDepthStencilFormat( flutter::gpu::Context* wrapper) { - return static_cast( - wrapper->GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat()); + return static_cast(flutter::gpu::FromImpellerPixelFormat( + wrapper->GetContext() + ->GetCapabilities() + ->GetDefaultDepthStencilFormat())); } diff --git a/lib/gpu/device_buffer.cc b/lib/gpu/device_buffer.cc index 55a12830731de..f783f9b8ada74 100644 --- a/lib/gpu/device_buffer.cc +++ b/lib/gpu/device_buffer.cc @@ -5,6 +5,7 @@ #include "flutter/lib/gpu/device_buffer.h" #include "dart_api.h" +#include "flutter/lib/gpu/formats.h" #include "fml/mapping.h" #include "impeller/core/device_buffer.h" #include "impeller/core/device_buffer_descriptor.h" @@ -53,7 +54,8 @@ bool InternalFlutterGpu_DeviceBuffer_Initialize( int storage_mode, int size_in_bytes) { impeller::DeviceBufferDescriptor desc; - desc.storage_mode = static_cast(storage_mode); + desc.storage_mode = flutter::gpu::ToImpellerStorageMode( + static_cast(storage_mode)); desc.size = size_in_bytes; auto device_buffer = gpu_context->GetContext()->GetResourceAllocator()->CreateBuffer(desc); diff --git a/lib/gpu/formats.cc b/lib/gpu/formats.cc new file mode 100644 index 0000000000000..07f1f6b17fbd5 --- /dev/null +++ b/lib/gpu/formats.cc @@ -0,0 +1,13 @@ +// 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 "flutter/lib/gpu/formats.h" + +namespace flutter { +namespace gpu { + +// + +} // namespace gpu +} // namespace flutter diff --git a/lib/gpu/formats.h b/lib/gpu/formats.h new file mode 100644 index 0000000000000..86b2cf44ad395 --- /dev/null +++ b/lib/gpu/formats.h @@ -0,0 +1,288 @@ +// 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 "fml/logging.h" +#include "impeller/core/formats.h" +#include "impeller/core/shader_types.h" + +// ATTENTION! ATTENTION! ATTENTION! +// All enums defined in this file must exactly match the contents and order of +// the corresponding enums defined in `gpu/lib/src/formats.dart`. + +namespace flutter { +namespace gpu { + +enum class FlutterGPUStorageMode { + kHostVisible, + kDevicePrivate, + kDeviceTransient, +}; + +constexpr impeller::StorageMode ToImpellerStorageMode( + FlutterGPUStorageMode value) { + switch (value) { + case FlutterGPUStorageMode::kHostVisible: + return impeller::StorageMode::kHostVisible; + case FlutterGPUStorageMode::kDevicePrivate: + return impeller::StorageMode::kDevicePrivate; + case FlutterGPUStorageMode::kDeviceTransient: + return impeller::StorageMode::kDeviceTransient; + } +} + +enum class FlutterGPUPixelFormat { + kUnknown, + kA8UNormInt, + kR8UNormInt, + kR8G8UNormInt, + kR8G8B8A8UNormInt, + kR8G8B8A8UNormIntSRGB, + kB8G8R8A8UNormInt, + kB8G8R8A8UNormIntSRGB, + kR32G32B32A32Float, + kR16G16B16A16Float, + kB10G10R10XR, + kB10G10R10XRSRGB, + kB10G10R10A10XR, + kS8UInt, + kD24UnormS8Uint, + kD32FloatS8UInt, +}; + +constexpr impeller::PixelFormat ToImpellerPixelFormat( + FlutterGPUPixelFormat value) { + switch (value) { + case FlutterGPUPixelFormat::kUnknown: + return impeller::PixelFormat::kUnknown; + case FlutterGPUPixelFormat::kA8UNormInt: + return impeller::PixelFormat::kA8UNormInt; + case FlutterGPUPixelFormat::kR8UNormInt: + return impeller::PixelFormat::kR8UNormInt; + case FlutterGPUPixelFormat::kR8G8UNormInt: + return impeller::PixelFormat::kR8G8UNormInt; + case FlutterGPUPixelFormat::kR8G8B8A8UNormInt: + return impeller::PixelFormat::kR8G8B8A8UNormInt; + case FlutterGPUPixelFormat::kR8G8B8A8UNormIntSRGB: + return impeller::PixelFormat::kR8G8B8A8UNormIntSRGB; + case FlutterGPUPixelFormat::kB8G8R8A8UNormInt: + return impeller::PixelFormat::kB8G8R8A8UNormInt; + case FlutterGPUPixelFormat::kB8G8R8A8UNormIntSRGB: + return impeller::PixelFormat::kB8G8R8A8UNormIntSRGB; + case FlutterGPUPixelFormat::kR32G32B32A32Float: + return impeller::PixelFormat::kR32G32B32A32Float; + case FlutterGPUPixelFormat::kR16G16B16A16Float: + return impeller::PixelFormat::kR16G16B16A16Float; + case FlutterGPUPixelFormat::kB10G10R10XR: + return impeller::PixelFormat::kB10G10R10XR; + case FlutterGPUPixelFormat::kB10G10R10XRSRGB: + return impeller::PixelFormat::kB10G10R10XRSRGB; + case FlutterGPUPixelFormat::kB10G10R10A10XR: + return impeller::PixelFormat::kB10G10R10A10XR; + case FlutterGPUPixelFormat::kS8UInt: + return impeller::PixelFormat::kS8UInt; + case FlutterGPUPixelFormat::kD24UnormS8Uint: + return impeller::PixelFormat::kD24UnormS8Uint; + case FlutterGPUPixelFormat::kD32FloatS8UInt: + return impeller::PixelFormat::kD32FloatS8UInt; + } +} + +constexpr FlutterGPUPixelFormat FromImpellerPixelFormat( + impeller::PixelFormat value) { + switch (value) { + case impeller::PixelFormat::kUnknown: + return FlutterGPUPixelFormat::kUnknown; + case impeller::PixelFormat::kA8UNormInt: + return FlutterGPUPixelFormat::kA8UNormInt; + case impeller::PixelFormat::kR8UNormInt: + return FlutterGPUPixelFormat::kR8UNormInt; + case impeller::PixelFormat::kR8G8UNormInt: + return FlutterGPUPixelFormat::kR8G8UNormInt; + case impeller::PixelFormat::kR8G8B8A8UNormInt: + return FlutterGPUPixelFormat::kR8G8B8A8UNormInt; + case impeller::PixelFormat::kR8G8B8A8UNormIntSRGB: + return FlutterGPUPixelFormat::kR8G8B8A8UNormIntSRGB; + case impeller::PixelFormat::kB8G8R8A8UNormInt: + return FlutterGPUPixelFormat::kB8G8R8A8UNormInt; + case impeller::PixelFormat::kB8G8R8A8UNormIntSRGB: + return FlutterGPUPixelFormat::kB8G8R8A8UNormIntSRGB; + case impeller::PixelFormat::kR32G32B32A32Float: + return FlutterGPUPixelFormat::kR32G32B32A32Float; + case impeller::PixelFormat::kR16G16B16A16Float: + return FlutterGPUPixelFormat::kR16G16B16A16Float; + case impeller::PixelFormat::kB10G10R10XR: + return FlutterGPUPixelFormat::kB10G10R10XR; + case impeller::PixelFormat::kB10G10R10XRSRGB: + return FlutterGPUPixelFormat::kB10G10R10XRSRGB; + case impeller::PixelFormat::kB10G10R10A10XR: + return FlutterGPUPixelFormat::kB10G10R10A10XR; + case impeller::PixelFormat::kS8UInt: + return FlutterGPUPixelFormat::kS8UInt; + case impeller::PixelFormat::kD24UnormS8Uint: + return FlutterGPUPixelFormat::kD24UnormS8Uint; + case impeller::PixelFormat::kD32FloatS8UInt: + return FlutterGPUPixelFormat::kD32FloatS8UInt; + } +} + +enum class FlutterGPUTextureCoordinateSystem { + kUploadFromHost, + kRenderToTexture, +}; + +constexpr impeller::TextureCoordinateSystem ToImpellerTextureCoordinateSystem( + FlutterGPUTextureCoordinateSystem value) { + switch (value) { + case FlutterGPUTextureCoordinateSystem::kUploadFromHost: + return impeller::TextureCoordinateSystem::kUploadFromHost; + case FlutterGPUTextureCoordinateSystem::kRenderToTexture: + return impeller::TextureCoordinateSystem::kRenderToTexture; + } +} + +enum class FlutterGPUBlendFactor { + kZero, + kOne, + kSourceColor, + kOneMinusSourceColor, + kSourceAlpha, + kOneMinusSourceAlpha, + kDestinationColor, + kOneMinusDestinationColor, + kDestinationAlpha, + kOneMinusDestinationAlpha, + kSourceAlphaSaturated, + kBlendColor, + kOneMinusBlendColor, + kBlendAlpha, + kOneMinusBlendAlpha, +}; + +constexpr impeller::BlendFactor ToImpellerBlendFactor( + FlutterGPUBlendFactor value) { + switch (value) { + case FlutterGPUBlendFactor::kZero: + return impeller::BlendFactor::kZero; + case FlutterGPUBlendFactor::kOne: + return impeller::BlendFactor::kOne; + case FlutterGPUBlendFactor::kSourceColor: + return impeller::BlendFactor::kSourceColor; + case FlutterGPUBlendFactor::kOneMinusSourceColor: + return impeller::BlendFactor::kOneMinusSourceColor; + case FlutterGPUBlendFactor::kSourceAlpha: + return impeller::BlendFactor::kSourceAlpha; + case FlutterGPUBlendFactor::kOneMinusSourceAlpha: + return impeller::BlendFactor::kOneMinusSourceAlpha; + case FlutterGPUBlendFactor::kDestinationColor: + return impeller::BlendFactor::kDestinationColor; + case FlutterGPUBlendFactor::kOneMinusDestinationColor: + return impeller::BlendFactor::kOneMinusDestinationColor; + case FlutterGPUBlendFactor::kDestinationAlpha: + return impeller::BlendFactor::kDestinationAlpha; + case FlutterGPUBlendFactor::kOneMinusDestinationAlpha: + return impeller::BlendFactor::kOneMinusDestinationAlpha; + case FlutterGPUBlendFactor::kSourceAlphaSaturated: + return impeller::BlendFactor::kSourceAlphaSaturated; + case FlutterGPUBlendFactor::kBlendColor: + return impeller::BlendFactor::kBlendColor; + case FlutterGPUBlendFactor::kOneMinusBlendColor: + return impeller::BlendFactor::kOneMinusBlendColor; + case FlutterGPUBlendFactor::kBlendAlpha: + return impeller::BlendFactor::kBlendAlpha; + case FlutterGPUBlendFactor::kOneMinusBlendAlpha: + return impeller::BlendFactor::kOneMinusBlendAlpha; + } +} + +enum class FlutterGPUBlendOperation { + kAdd, + kSubtract, + kReverseSubtract, +}; + +constexpr impeller::BlendOperation ToImpellerBlendOperation( + FlutterGPUBlendOperation value) { + switch (value) { + case FlutterGPUBlendOperation::kAdd: + return impeller::BlendOperation::kAdd; + case FlutterGPUBlendOperation::kSubtract: + return impeller::BlendOperation::kSubtract; + case FlutterGPUBlendOperation::kReverseSubtract: + return impeller::BlendOperation::kReverseSubtract; + } +} + +enum class FlutterGPULoadAction { + kDontCare, + kLoad, + kClear, +}; + +constexpr impeller::LoadAction ToImpellerLoadAction( + FlutterGPULoadAction value) { + switch (value) { + case FlutterGPULoadAction::kDontCare: + return impeller::LoadAction::kDontCare; + case FlutterGPULoadAction::kLoad: + return impeller::LoadAction::kLoad; + case FlutterGPULoadAction::kClear: + return impeller::LoadAction::kClear; + } +} + +enum class FlutterGPUStoreAction { + kDontCare, + kStore, + kMultisampleResolve, + kStoreAndMultisampleResolve, +}; + +constexpr impeller::StoreAction ToImpellerStoreAction( + FlutterGPUStoreAction value) { + switch (value) { + case FlutterGPUStoreAction::kDontCare: + return impeller::StoreAction::kDontCare; + case FlutterGPUStoreAction::kStore: + return impeller::StoreAction::kStore; + case FlutterGPUStoreAction::kMultisampleResolve: + return impeller::StoreAction::kMultisampleResolve; + case FlutterGPUStoreAction::kStoreAndMultisampleResolve: + return impeller::StoreAction::kStoreAndMultisampleResolve; + } +} + +enum class FlutterGPUShaderStage { + kVertex, + kFragment, +}; + +constexpr impeller::ShaderStage ToImpellerShaderStage( + FlutterGPUShaderStage value) { + switch (value) { + case FlutterGPUShaderStage::kVertex: + return impeller::ShaderStage::kVertex; + case FlutterGPUShaderStage::kFragment: + return impeller::ShaderStage::kFragment; + } +} + +constexpr FlutterGPUShaderStage FromImpellerShaderStage( + impeller::ShaderStage value) { + switch (value) { + case impeller::ShaderStage::kVertex: + return FlutterGPUShaderStage::kVertex; + case impeller::ShaderStage::kFragment: + return FlutterGPUShaderStage::kFragment; + case impeller::ShaderStage::kUnknown: + case impeller::ShaderStage::kTessellationControl: + case impeller::ShaderStage::kTessellationEvaluation: + case impeller::ShaderStage::kCompute: + FML_LOG(ERROR) << "Invalid Flutter GPU ShaderStage " + << static_cast(value); + FML_UNREACHABLE(); + } +} + +} // namespace gpu +} // namespace flutter diff --git a/lib/gpu/lib/src/buffer.dart b/lib/gpu/lib/src/buffer.dart index 9794e5612b79d..c2b08220f050c 100644 --- a/lib/gpu/lib/src/buffer.dart +++ b/lib/gpu/lib/src/buffer.dart @@ -24,7 +24,13 @@ class BufferView { } /// A buffer that can be referenced by commands on the GPU. -mixin Buffer {} +mixin Buffer { + void _bindAsVertexBuffer(RenderPass renderPass, int offsetInBytes, + int lengthInBytes, int vertexCount); + + bool _bindAsUniform(RenderPass renderPass, UniformSlot slot, + int offsetInBytes, int lengthInBytes); +} /// [DeviceBuffer] is a region of memory allocated on the device heap /// (GPU-resident memory). @@ -52,6 +58,20 @@ base class DeviceBuffer extends NativeFieldWrapperClass1 with Buffer { final StorageMode storageMode; final int sizeInBytes; + @override + void _bindAsVertexBuffer(RenderPass renderPass, int offsetInBytes, + int lengthInBytes, int vertexCount) { + renderPass._bindVertexBufferDevice( + this, offsetInBytes, lengthInBytes, vertexCount); + } + + @override + bool _bindAsUniform(RenderPass renderPass, UniformSlot slot, + int offsetInBytes, int lengthInBytes) { + return renderPass._bindUniformDevice(slot.shaderStage.index, slot.slotId, + this, offsetInBytes, lengthInBytes); + } + /// Wrap with native counterpart. @Native, Int, Int)>( symbol: 'InternalFlutterGpu_DeviceBuffer_Initialize') @@ -109,6 +129,20 @@ base class HostBuffer extends NativeFieldWrapperClass1 with Buffer { _initialize(); } + @override + void _bindAsVertexBuffer(RenderPass renderPass, int offsetInBytes, + int lengthInBytes, int vertexCount) { + renderPass._bindVertexBufferHost( + this, offsetInBytes, lengthInBytes, vertexCount); + } + + @override + bool _bindAsUniform(RenderPass renderPass, UniformSlot slot, + int offsetInBytes, int lengthInBytes) { + return renderPass._bindUniformHost(slot.shaderStage.index, slot.slotId, + this, offsetInBytes, lengthInBytes); + } + /// Wrap with native counterpart. @Native( symbol: 'InternalFlutterGpu_HostBuffer_Initialize') diff --git a/lib/gpu/lib/src/formats.dart b/lib/gpu/lib/src/formats.dart index 56350fc63c522..3252dd31e0db3 100644 --- a/lib/gpu/lib/src/formats.dart +++ b/lib/gpu/lib/src/formats.dart @@ -6,6 +6,10 @@ part of flutter_gpu; +// ATTENTION! ATTENTION! ATTENTION! +// All enum classes defined in this file must exactly match the contents and +// order of the corresponding enums defined in `gpu/formats.h`. + /// Specifies where an allocation resides and how it may be used. enum StorageMode { /// Allocations can be mapped onto the hosts address space and also be used by @@ -98,10 +102,6 @@ enum StoreAction { } enum ShaderStage { - unknown, vertex, fragment, - tessellationControl, - tessellationEvaluation, - compute, } diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart index 62bb90fb0f5cc..e8f1ef4157d77 100644 --- a/lib/gpu/lib/src/render_pass.dart +++ b/lib/gpu/lib/src/render_pass.dart @@ -10,7 +10,7 @@ base class ColorAttachment { ColorAttachment( {this.loadAction = LoadAction.clear, this.storeAction = StoreAction.store, - this.clearColor = const ui.Color(0), + this.clearColor = const ui.Color(0x00000000), required this.texture, this.resolveTexture = null}); @@ -74,42 +74,13 @@ base class RenderPass extends NativeFieldWrapperClass1 { } void bindVertexBuffer(BufferView bufferView, int vertexCount) { - switch (bufferView.buffer.runtimeType) { - case DeviceBuffer: - _bindVertexBufferDevice(bufferView.buffer as DeviceBuffer, - bufferView.offsetInBytes, bufferView.lengthInBytes, vertexCount); - break; - case HostBuffer: - _bindVertexBufferHost(bufferView.buffer as HostBuffer, - bufferView.offsetInBytes, bufferView.lengthInBytes, vertexCount); - break; - default: - throw Exception("Invalid buffer type"); - } + bufferView.buffer._bindAsVertexBuffer( + this, bufferView.offsetInBytes, bufferView.lengthInBytes, vertexCount); } void bindUniform(UniformSlot slot, BufferView bufferView) { - bool success; - switch (bufferView.buffer.runtimeType) { - case DeviceBuffer: - success = _bindUniformDevice( - slot.shaderStage.index, - slot.slotId, - bufferView.buffer as DeviceBuffer, - bufferView.offsetInBytes, - bufferView.lengthInBytes); - break; - case HostBuffer: - success = _bindUniformHost( - slot.shaderStage.index, - slot.slotId, - bufferView.buffer as HostBuffer, - bufferView.offsetInBytes, - bufferView.lengthInBytes); - break; - default: - throw Exception("Invalid buffer type"); - } + bool success = bufferView.buffer._bindAsUniform( + this, slot, bufferView.offsetInBytes, bufferView.lengthInBytes); if (!success) { throw Exception("Failed to bind uniform slot"); } diff --git a/lib/gpu/lib/src/shader.dart b/lib/gpu/lib/src/shader.dart index f5f06bbe87145..9ebbe9280f176 100644 --- a/lib/gpu/lib/src/shader.dart +++ b/lib/gpu/lib/src/shader.dart @@ -7,10 +7,10 @@ part of flutter_gpu; base class UniformSlot { - UniformSlot(this.slotId, this.shaderStage); + const UniformSlot(this.slotId, this.shaderStage); - int slotId; - ShaderStage shaderStage; + final int slotId; + final ShaderStage shaderStage; } base class Shader extends NativeFieldWrapperClass1 { diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index cc28aa827325f..08fbae379368d 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -4,7 +4,8 @@ #include "flutter/lib/gpu/render_pass.h" -#include "dart_api.h" +#include "flutter/lib/gpu/formats.h" +#include "flutter/lib/gpu/render_pipeline.h" #include "fml/memory/ref_ptr.h" #include "impeller/core/buffer_view.h" #include "impeller/core/formats.h" @@ -12,7 +13,6 @@ #include "impeller/core/vertex_buffer.h" #include "impeller/geometry/color.h" #include "impeller/renderer/pipeline_library.h" -#include "lib/gpu/render_pipeline.h" #include "tonic/converter/dart_converter.h" namespace flutter { @@ -143,8 +143,10 @@ Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( flutter::gpu::Texture* texture, Dart_Handle resolve_texture_wrapper) { impeller::ColorAttachment desc; - desc.load_action = static_cast(load_action); - desc.store_action = static_cast(store_action); + desc.load_action = flutter::gpu::ToImpellerLoadAction( + static_cast(load_action)); + desc.store_action = flutter::gpu::ToImpellerStoreAction( + static_cast(store_action)); desc.clear_color = ToImpellerColor(static_cast(clear_color)); desc.texture = texture->GetTexture(); if (!Dart_IsNull(resolve_texture_wrapper)) { @@ -164,8 +166,10 @@ Dart_Handle InternalFlutterGpu_RenderPass_SetStencilAttachment( int clear_stencil, flutter::gpu::Texture* texture) { impeller::StencilAttachment desc; - desc.load_action = static_cast(load_action); - desc.store_action = static_cast(store_action); + desc.load_action = flutter::gpu::ToImpellerLoadAction( + static_cast(load_action)); + desc.store_action = flutter::gpu::ToImpellerStoreAction( + static_cast(store_action)); desc.clear_stencil = clear_stencil; desc.texture = texture->GetTexture(); wrapper->GetRenderTarget().SetStencilAttachment(desc); @@ -240,7 +244,9 @@ static bool BindUniform(flutter::gpu::RenderPass* wrapper, // even use it for anything. slot.ext_res_0 = slot_id; return command.BindResource( - static_cast(stage), slot, metadata, + flutter::gpu::ToImpellerShaderStage( + static_cast(stage)), + slot, metadata, impeller::BufferView{ .buffer = buffer->GetBuffer(), .range = impeller::Range(offset_in_bytes, length_in_bytes), diff --git a/lib/gpu/texture.cc b/lib/gpu/texture.cc index b9e20e233d2dc..49382e631f16d 100644 --- a/lib/gpu/texture.cc +++ b/lib/gpu/texture.cc @@ -4,6 +4,7 @@ #include "flutter/lib/gpu/texture.h" +#include "flutter/lib/gpu/formats.h" #include "flutter/lib/ui/painting/image.h" #include "fml/mapping.h" #include "impeller/core/allocator.h" @@ -82,9 +83,11 @@ bool InternalFlutterGpu_Texture_Initialize(Dart_Handle wrapper, bool enable_shader_read_usage, bool enable_shader_write_usage) { impeller::TextureDescriptor desc; - desc.storage_mode = static_cast(storage_mode); + desc.storage_mode = flutter::gpu::ToImpellerStorageMode( + static_cast(storage_mode)); desc.size = {width, height}; - desc.format = static_cast(format); + desc.format = flutter::gpu::ToImpellerPixelFormat( + static_cast(format)); desc.usage = 0; if (enable_render_target_usage) { desc.usage |= static_cast( @@ -117,8 +120,9 @@ bool InternalFlutterGpu_Texture_Initialize(Dart_Handle wrapper, return false; } - texture->SetCoordinateSystem( - static_cast(coordinate_system)); + texture->SetCoordinateSystem(flutter::gpu::ToImpellerTextureCoordinateSystem( + static_cast( + coordinate_system))); auto res = fml::MakeRefCounted(std::move(texture)); res->AssociateWithDartWrapper(wrapper); @@ -130,7 +134,9 @@ void InternalFlutterGpu_Texture_SetCoordinateSystem( flutter::gpu::Texture* wrapper, int coordinate_system) { return wrapper->SetCoordinateSystem( - static_cast(coordinate_system)); + flutter::gpu::ToImpellerTextureCoordinateSystem( + static_cast( + coordinate_system))); } bool InternalFlutterGpu_Texture_Overwrite(flutter::gpu::Texture* texture,