Skip to content

Commit

Permalink
[Impeller] Start of Dart GPU prototype (flutter#42228)
Browse files Browse the repository at this point in the history
I've been slowly hacking on a prototype alongside a doc (public go link [imminent](flutter/website#8716)) for a while (the doc has been changing a lot as a result of prototyping) and I think it's time to start landing parts of this prototype/experiment in-tree.

This initial PR just sets up the main context singleton on the UI thread. After this, I'll land the shader management stuff.

I re-used the existing experimental 3D flag for this, since this is meant to replace what can be done with Impeller Scene anyway.
  • Loading branch information
bdero authored May 24, 2023
1 parent 308c769 commit cbfcb77
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 4 deletions.
5 changes: 4 additions & 1 deletion BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ group("unittests") {
}

if (is_mac || is_linux || is_win) {
public_deps += [ "//flutter/impeller:impeller_unittests" ]
public_deps += [
"//flutter/impeller:impeller_dart_unittests",
"//flutter/impeller:impeller_unittests",
]
}

if (is_mac) {
Expand Down
6 changes: 6 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1699,11 +1699,14 @@ ORIGIN: ../../../flutter/lib/ui/dart_runtime_hooks.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/dart_ui.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/dart_ui.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/dart_wrapper.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/experiments/gpu.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/experiments/scene.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/experiments/setup_hooks.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/experiments/ui.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/floating_point.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/geometry.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/gpu/context.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/gpu/context.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/hash_codes.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/hooks.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/ui/io_manager.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -4342,11 +4345,14 @@ FILE: ../../../flutter/lib/ui/dart_runtime_hooks.h
FILE: ../../../flutter/lib/ui/dart_ui.cc
FILE: ../../../flutter/lib/ui/dart_ui.h
FILE: ../../../flutter/lib/ui/dart_wrapper.h
FILE: ../../../flutter/lib/ui/experiments/gpu.dart
FILE: ../../../flutter/lib/ui/experiments/scene.dart
FILE: ../../../flutter/lib/ui/experiments/setup_hooks.dart
FILE: ../../../flutter/lib/ui/experiments/ui.dart
FILE: ../../../flutter/lib/ui/floating_point.h
FILE: ../../../flutter/lib/ui/geometry.dart
FILE: ../../../flutter/lib/ui/gpu/context.cc
FILE: ../../../flutter/lib/ui/gpu/context.h
FILE: ../../../flutter/lib/ui/hash_codes.dart
FILE: ../../../flutter/lib/ui/hooks.dart
FILE: ../../../flutter/lib/ui/io_manager.cc
Expand Down
3 changes: 2 additions & 1 deletion impeller/fixtures/dart_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui';
import 'dart:ui' as ui;
//import 'dart:gpu';

void main() {}

Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,6 @@ impeller_component("renderer_dart_unittests") {
"../playground:playground_test",
"//flutter/runtime:runtime",
"//flutter/testing:fixture_test",
"//flutter/testing:testing_lib",
"//flutter/testing:testing",
]
}
7 changes: 7 additions & 0 deletions impeller/renderer/renderer_dart_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define FML_USED_ON_EMBEDDER

#include <memory>

#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/ui/ui_dart_state.h"
#include "flutter/runtime/dart_isolate.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
Expand All @@ -21,6 +25,7 @@
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"

#include "gtest/gtest.h"
#include "third_party/imgui/imgui.h"

namespace impeller {
Expand All @@ -33,7 +38,9 @@ class RendererDartTest : public PlaygroundTest,
: settings_(CreateSettingsForFixture()),
vm_ref_(flutter::DartVMRef::Create(settings_)) {
fml::MessageLoop::EnsureInitializedForCurrentThread();

current_task_runner_ = fml::MessageLoop::GetCurrent().GetTaskRunner();

isolate_ = CreateDartIsolate();
assert(isolate_);
assert(isolate_->get()->GetPhase() == flutter::DartIsolate::Phase::Running);
Expand Down
6 changes: 6 additions & 0 deletions lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ source_set("ui") {
"painting/scene/scene_shader.h",
]

# Experimental "Impeller Dart" API.
sources += [
"gpu/context.cc",
"gpu/context.h",
]

deps += [ "//flutter/impeller/scene" ]
}
}
Expand Down
9 changes: 9 additions & 0 deletions lib/ui/dart_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "flutter/lib/ui/compositing/scene.h"
#include "flutter/lib/ui/compositing/scene_builder.h"
#include "flutter/lib/ui/dart_runtime_hooks.h"
#include "flutter/lib/ui/gpu/context.h"
#include "flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h"
#include "flutter/lib/ui/painting/canvas.h"
#include "flutter/lib/ui/painting/codec.h"
Expand Down Expand Up @@ -315,6 +316,10 @@ typedef CanvasPath Path;
V(SceneShader, SetCameraTransform, 2) \
V(SceneShader, Dispose, 1)

#define FFI_FUNCTION_LIST_GPU(V) V(GpuContext::InitializeDefault, 1)

#define FFI_METHOD_LIST_GPU(V)

#endif // IMPELLER_ENABLE_3D

#define FFI_FUNCTION_INSERT(FUNCTION, ARGS) \
Expand Down Expand Up @@ -343,9 +348,13 @@ void* ResolveFfiNativeFunction(const char* name, uintptr_t args) {
void InitDispatcherMap() {
FFI_FUNCTION_LIST(FFI_FUNCTION_INSERT)
FFI_METHOD_LIST(FFI_METHOD_INSERT)

#ifdef IMPELLER_ENABLE_3D
FFI_FUNCTION_LIST_3D(FFI_FUNCTION_INSERT)
FFI_METHOD_LIST_3D(FFI_METHOD_INSERT)

FFI_FUNCTION_LIST_GPU(FFI_FUNCTION_INSERT)
FFI_METHOD_LIST_GPU(FFI_METHOD_INSERT)
#endif // IMPELLER_ENABLE_3D
}

Expand Down
184 changes: 184 additions & 0 deletions lib/ui/experiments/gpu.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// 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 dart.ui;

class GpuContextException implements Exception {
GpuContextException(this.message);
String message;

@override
String toString() {
return 'GpuContextException: $message';
}
}

enum BlendOperation { add, subtract, reverseSubtract }

enum BlendFactor {
zero,
one,
sourceColor,
oneMinusSourceColor,
sourceAlpha,
oneMinusSourceAlpha,
destinationColor,
oneMinusDestinationColor,
destinationAlpha,
oneMinusDestinationAlpha,
sourceAlphaSaturated,
blendColor,
oneMinusBlendColor,
blendAlpha,
oneMinusBlendAlpha,
}

class BlendOptions {
const BlendOptions({
this.colorOperation = BlendOperation.add,
this.sourceColorFactor = BlendFactor.one,
this.destinationColorFactor = BlendFactor.oneMinusSourceAlpha,
this.alphaOperation = BlendOperation.add,
this.sourceAlphaFactor = BlendFactor.one,
this.destinationAlphaFactor = BlendFactor.oneMinusSourceAlpha,
});

final BlendOperation colorOperation;
final BlendFactor sourceColorFactor;
final BlendFactor destinationColorFactor;
final BlendOperation alphaOperation;
final BlendFactor sourceAlphaFactor;
final BlendFactor destinationAlphaFactor;
}

enum StencilOperation {
keep,
zero,
setToReferenceValue,
incrementClamp,
decrementClamp,
invert,
incrementWrap,
decrementWrap,
}

enum CompareFunction {
never,
always,
less,
equal,
lessEqual,
greater,
notEqual,
greaterEqual,
}

class StencilOptions {
const StencilOptions({
this.operation = StencilOperation.incrementClamp,
this.compare = CompareFunction.always,
});

final StencilOperation operation;
final CompareFunction compare;
}

enum ShaderType {
unknown,
voidType,
booleanType,
signedByteType,
unsignedByteType,
signedShortType,
unsignedShortType,
signedIntType,
unsignedIntType,
signedInt64Type,
unsignedInt64Type,
atomicCounterType,
halfFloatType,
floatType,
doubleType,
structType,
imageType,
sampledImageType,
samplerType,
}

class VertexAttribute {
const VertexAttribute({
this.name = '',
this.location = 0,
this.set = 0,
this.binding = 0,
this.type = ShaderType.floatType,
this.elements = 2,
});

final String name;
final int location;
final int set;
final int binding;
final ShaderType type;
final int elements;
}

class UniformSlot {
const UniformSlot({
this.name = '',
this.set = 0,
this.extRes0 = 0,
this.binding = 0,
});

final String name;
final int set;
final int extRes0;
final int binding;
}

class GpuShader {}

class RasterPipeline {}

/// A handle to a graphics context. Used to create and manage GPU resources.
///
/// To obtain the default graphics context, use [getGpuContext].
class GpuContext extends NativeFieldWrapperClass1 {
/// Creates a new graphics context that corresponds to the default Impeller
/// context.
GpuContext._createDefault() {
final String error = _initializeDefault();
if (error.isNotEmpty) {
throw GpuContextException(error);
}
}

//registerShaderLibrary() async

Future<RasterPipeline> createRasterPipeline({
required GpuShader vertex,
required GpuShader fragment,
BlendOptions blendOptions = const BlendOptions(),
StencilOptions stencilOptions = const StencilOptions(),
List<VertexAttribute> vertexLayout = const <VertexAttribute>[],
List<UniformSlot> uniformLayout = const <UniformSlot>[],
}) async {
return RasterPipeline();
}

/// Associates the default Impeller context with this GpuContext.
@Native<Handle Function(Handle)>(symbol: 'GpuContext::InitializeDefault')
external String _initializeDefault();
}

GpuContext? _defaultGpuContext;

/// Returns the default graphics context.
GpuContext getGpuContext() {
_defaultGpuContext ??= GpuContext._createDefault();
return _defaultGpuContext!;
}
4 changes: 3 additions & 1 deletion lib/ui/experiments/ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ part '../painting.dart';
part '../platform_dispatcher.dart';
part '../plugins.dart';
part '../pointer.dart';
part 'scene.dart';
part '../semantics.dart';
part 'setup_hooks.dart';
part '../text.dart';
part '../window.dart';

part 'gpu.dart';
part 'scene.dart';
54 changes: 54 additions & 0 deletions lib/ui/gpu/context.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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/ui/gpu/context.h"

#include <memory>
#include <sstream>

#include "flutter/fml/log_level.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/tonic/dart_wrappable.h"

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(ui, GpuContext);

std::string GpuContext::InitializeDefault(Dart_Handle wrapper) {
auto dart_state = UIDartState::Current();
if (!dart_state->IsImpellerEnabled()) {
return "The GpuContext API requires the Impeller rendering backend to be "
"enabled.";
}

// Grab the Impeller context from the IO manager.

std::promise<std::shared_ptr<impeller::Context>> context_promise;
auto impeller_context_future = context_promise.get_future();
dart_state->GetTaskRunners().GetIOTaskRunner()->PostTask(
fml::MakeCopyable([promise = std::move(context_promise),
io_manager = dart_state->GetIOManager()]() mutable {
promise.set_value(io_manager ? io_manager->GetImpellerContext()
: nullptr);
}));

auto impeller_context = impeller_context_future.get();
if (!impeller_context) {
return "Unable to retrieve the Impeller context.";
}
auto res = fml::MakeRefCounted<GpuContext>(impeller_context);
res->AssociateWithDartWrapper(wrapper);

return "";
}

GpuContext::GpuContext(std::shared_ptr<impeller::Context> context)
: context_(std::move(context)) {}

GpuContext::~GpuContext() = default;

} // namespace flutter
Loading

0 comments on commit cbfcb77

Please sign in to comment.