Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1728,7 +1728,10 @@ ORIGIN: ../../../flutter/lib/gpu/context.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/gpu/context.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/gpu/export.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/gpu/export.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/context.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/gpu/lib/src/smoketest.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/gpu/smoketest.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -4456,7 +4459,10 @@ FILE: ../../../flutter/lib/gpu/context.cc
FILE: ../../../flutter/lib/gpu/context.h
FILE: ../../../flutter/lib/gpu/export.cc
FILE: ../../../flutter/lib/gpu/export.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/context.dart
FILE: ../../../flutter/lib/gpu/lib/src/smoketest.dart
FILE: ../../../flutter/lib/gpu/smoketest.cc
Expand Down
16 changes: 16 additions & 0 deletions impeller/fixtures/dart_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';
import 'dart:ui' as ui;
import '../../lib/gpu/lib/gpu.dart' as gpu;

Expand All @@ -17,3 +18,18 @@ void instantiateDefaultContext() {
// ignore: unused_local_variable
final gpu.GpuContext context = gpu.gpuContext;
}

@pragma('vm:entry-point')
void canEmplaceHostBuffer() {
final gpu.HostBuffer hostBuffer = gpu.HostBuffer();

final gpu.BufferView view0 = hostBuffer
.emplace(Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData());
assert(view0.offsetInBytes == 0);
assert(view0.lengthInBytes == 4);

final gpu.BufferView view1 = hostBuffer
.emplace(Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData());
assert(view1.offsetInBytes >= 4);
assert(view1.lengthInBytes == 4);
}
14 changes: 14 additions & 0 deletions impeller/renderer/renderer_dart_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,19 @@ TEST_P(RendererDartTest, CanInstantiateFlutterGPUContext) {
ASSERT_TRUE(result);
}

TEST_P(RendererDartTest, CanEmplaceHostBuffer) {
auto isolate = GetIsolate();
bool result = isolate->RunInIsolateScope([]() -> bool {
if (tonic::CheckAndHandleError(
::Dart_Invoke(Dart_RootLibrary(),
tonic::ToDart("canEmplaceHostBuffer"), 0, nullptr))) {
return false;
}
return true;
});

ASSERT_TRUE(result);
}

} // namespace testing
} // namespace impeller
2 changes: 2 additions & 0 deletions lib/gpu/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ source_set("gpu") {
"context.h",
"export.cc",
"export.h",
"host_buffer.cc",
"host_buffer.h",
"smoketest.cc",
"smoketest.h",
]
Expand Down
14 changes: 9 additions & 5 deletions lib/gpu/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,25 @@ namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(gpu, Context);

std::shared_ptr<impeller::Context> Context::override_context_;
std::shared_ptr<impeller::Context> Context::default_context_;

void Context::SetOverrideContext(std::shared_ptr<impeller::Context> context) {
override_context_ = std::move(context);
default_context_ = std::move(context);
}

std::shared_ptr<impeller::Context> Context::GetOverrideContext() {
return override_context_;
std::shared_ptr<impeller::Context> Context::GetDefaultContext() {
return default_context_;
}

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

Context::~Context() = default;

std::shared_ptr<impeller::Context> Context::GetContext() {
return context_;
}

} // namespace flutter

//----------------------------------------------------------------------------
Expand All @@ -40,7 +44,7 @@ Dart_Handle InternalFlutterGpu_Context_InitializeDefault(Dart_Handle wrapper) {
auto dart_state = flutter::UIDartState::Current();

std::shared_ptr<impeller::Context> impeller_context =
flutter::Context::GetOverrideContext();
flutter::Context::GetDefaultContext();

if (!impeller_context) {
if (!dart_state->IsImpellerEnabled()) {
Expand Down
9 changes: 5 additions & 4 deletions lib/gpu/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ class Context : public RefCountedDartWrappable<Context> {
public:
static void SetOverrideContext(std::shared_ptr<impeller::Context> context);

static std::shared_ptr<impeller::Context> GetOverrideContext();
static std::shared_ptr<impeller::Context> GetDefaultContext();

explicit Context(std::shared_ptr<impeller::Context> context);
~Context() override;

protected:
std::shared_ptr<impeller::Context> GetContext();

private:
/// An Impeller context that takes precedent over the IO state context when
/// set. This is used to inject the context when running with the Impeller
/// playground, which doesn't instantiate an Engine instance.
static std::shared_ptr<impeller::Context> override_context_;
static std::shared_ptr<impeller::Context> default_context_;

private:
std::shared_ptr<impeller::Context> context_;

FML_DISALLOW_COPY_AND_ASSIGN(Context);
Expand Down
40 changes: 40 additions & 0 deletions lib/gpu/host_buffer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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/host_buffer.h"

#include "impeller/core/host_buffer.h"
#include "impeller/core/platform.h"
#include "third_party/tonic/typed_data/dart_byte_data.h"

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(gpu, HostBuffer);

HostBuffer::HostBuffer() : host_buffer_(impeller::HostBuffer::Create()) {}

HostBuffer::~HostBuffer() = default;

size_t HostBuffer::EmplaceBytes(const tonic::DartByteData& byte_data) {
auto view =
host_buffer_->Emplace(byte_data.data(), byte_data.length_in_bytes(),
impeller::DefaultUniformAlignment());
return view.range.offset;
}

} // namespace flutter

//----------------------------------------------------------------------------
/// Exports
///

void InternalFlutterGpu_HostBuffer_Initialize(Dart_Handle wrapper) {
auto res = fml::MakeRefCounted<flutter::HostBuffer>();
res->AssociateWithDartWrapper(wrapper);
}

size_t InternalFlutterGpu_HostBuffer_EmplaceBytes(flutter::HostBuffer* wrapper,
Dart_Handle byte_data) {
return wrapper->EmplaceBytes(tonic::DartByteData(byte_data));
}
47 changes: 47 additions & 0 deletions lib/gpu/host_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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/export.h"
#include "flutter/lib/ui/dart_wrapper.h"
#include "impeller/core/host_buffer.h"
#include "third_party/tonic/typed_data/dart_byte_data.h"

namespace flutter {

class HostBuffer : public RefCountedDartWrappable<HostBuffer> {
DEFINE_WRAPPERTYPEINFO();
FML_FRIEND_MAKE_REF_COUNTED(HostBuffer);

public:
explicit HostBuffer();

~HostBuffer() override;

size_t EmplaceBytes(const tonic::DartByteData& byte_data);

private:
std::shared_ptr<impeller::HostBuffer> host_buffer_;

FML_DISALLOW_COPY_AND_ASSIGN(HostBuffer);
};

} // namespace flutter

//----------------------------------------------------------------------------
/// Exports
///

extern "C" {

FLUTTER_GPU_EXPORT
extern void InternalFlutterGpu_HostBuffer_Initialize(Dart_Handle wrapper);

FLUTTER_GPU_EXPORT
extern size_t InternalFlutterGpu_HostBuffer_EmplaceBytes(
flutter::HostBuffer* wrapper,
Dart_Handle byte_data);

} // extern "C"
4 changes: 3 additions & 1 deletion lib/gpu/lib/gpu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@
/// * [Flutter GPU Wiki page](https://github.com/flutter/flutter/wiki/Flutter-GPU).
library flutter_gpu;

export 'src/context.dart';
export 'src/smoketest.dart';

export 'src/context.dart';
export 'src/buffer.dart';
67 changes: 67 additions & 0 deletions lib/gpu/lib/src/buffer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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.

import 'dart:ffi';
import 'dart:nativewrappers';
import 'dart:typed_data';

/// A reference to a byte range within a GPU-resident [Buffer].
class BufferView {
/// The buffer of this view.
final HostBuffer buffer;

/// The start of the view, in bytes starting from the beginning of the
/// [buffer].
final int offsetInBytes;

/// The length of the view.
final int lengthInBytes;

/// Create a new view into a buffer on the GPU.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its not really "on the gpu though"? For more functional pieces like the buffer view it may be easier to document once there are things that can be done with it. for example, "a view into a buffer that can be used for binding uniform data yada yada"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think BufferViews are effectively GPU-only because they'll only be used for binding buffers to Commands. I don't think we'd use a BufferView for updating a range on the host buffer, for example.

const BufferView(this.buffer,
{required this.offsetInBytes, required this.lengthInBytes});
}

/// [HostBuffer] is a [Buffer] which is allocated on the host (native CPU
/// resident memory) and lazily uploaded to the GPU. A [HostBuffer] can be
/// safely mutated or extended at any time on the host, and will be
/// automatically re-uploaded to the GPU the next time a GPU operation needs to
/// access it.
///
/// This is useful for efficiently chunking sparse data uploads, especially
/// ephemeral uniform data that needs to change from frame to frame.
///
/// Different platforms have different data alignment requirements for accessing
/// device buffer data. The [HostBuffer] takes these requirements into account
/// and automatically inserts padding between emplaced data if necessary.
base class HostBuffer extends NativeFieldWrapperClass1 {
/// Creates a new HostBuffer.
HostBuffer() {
_initialize();
}

/// Wrap with native counterpart.
@Native<Void Function(Handle)>(
symbol: 'InternalFlutterGpu_HostBuffer_Initialize')
external void _initialize();

/// Append byte data to the end of the [HostBuffer] and produce a [BufferView]
/// that references the new data in the buffer.
///
/// This method automatically inserts padding in-between emplace calls in the
/// buffer if necessary to abide by platform-specific uniform alignment
/// requirements.
///
/// The updated buffer will be uploaded to the GPU if the returned
/// [BufferView] is used by a rendering command.
BufferView emplace(ByteData bytes) {
int resultOffset = _emplaceBytes(bytes);
return BufferView(this,
offsetInBytes: resultOffset, lengthInBytes: bytes.lengthInBytes);
}

@Native<Uint64 Function(Pointer<Void>, Handle)>(
symbol: 'InternalFlutterGpu_HostBuffer_EmplaceBytes')
external int _emplaceBytes(ByteData bytes);
}