blob: 9794e5612b79d03f886dd38e60a19c8633911e6a [file] [log] [blame]
// 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;
/// A reference to a byte range within a GPU-resident [Buffer].
class BufferView {
/// The buffer of this view.
final Buffer 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.
const BufferView(this.buffer,
{required this.offsetInBytes, required this.lengthInBytes});
}
/// A buffer that can be referenced by commands on the GPU.
mixin Buffer {}
/// [DeviceBuffer] is a region of memory allocated on the device heap
/// (GPU-resident memory).
base class DeviceBuffer extends NativeFieldWrapperClass1 with Buffer {
bool _valid = false;
get isValid {
return _valid;
}
/// Creates a new DeviceBuffer.
DeviceBuffer._initialize(
GpuContext gpuContext, StorageMode storageMode, int sizeInBytes)
: storageMode = storageMode,
sizeInBytes = sizeInBytes {
_valid = _initialize(gpuContext, storageMode.index, sizeInBytes);
}
/// Creates a new host visible DeviceBuffer with data copied from the host.
DeviceBuffer._initializeWithHostData(GpuContext gpuContext, ByteData data)
: storageMode = StorageMode.hostVisible,
sizeInBytes = data.lengthInBytes {
_valid = _initializeWithHostData(gpuContext, data);
}
final StorageMode storageMode;
final int sizeInBytes;
/// Wrap with native counterpart.
@Native<Bool Function(Handle, Pointer<Void>, Int, Int)>(
symbol: 'InternalFlutterGpu_DeviceBuffer_Initialize')
external bool _initialize(
GpuContext gpuContext, int storageMode, int sizeInBytes);
/// Wrap with native counterpart.
@Native<Bool Function(Handle, Pointer<Void>, Handle)>(
symbol: 'InternalFlutterGpu_DeviceBuffer_InitializeWithHostData')
external bool _initializeWithHostData(GpuContext gpuContext, ByteData data);
/// Overwrite a range of bytes in the already created [DeviceBuffer].
///
/// This method can only be used if the [DeviceBuffer] was created with
/// [StorageMode.hostVisible]. An exception will be thrown otherwise.
///
/// The entire length of [sourceBytes] will be copied into the [DeviceBuffer],
/// starting at byte index [destinationOffsetInBytes] in the [DeviceBuffer].
/// If performing this copy would result in an out of bounds write to the
/// buffer, then the write will not be attempted and will fail.
///
/// Returns [true] if the write was successful, or [false] if the write
/// failed due to an internal error.
bool overwrite(ByteData sourceBytes, {int destinationOffsetInBytes = 0}) {
if (storageMode != StorageMode.hostVisible) {
throw Exception(
'DeviceBuffer.overwrite can only be used with DeviceBuffers that are host visible');
}
if (destinationOffsetInBytes < 0) {
throw Exception('destinationOffsetInBytes must be positive');
}
return _overwrite(sourceBytes, destinationOffsetInBytes);
}
@Native<Bool Function(Pointer<Void>, Handle, Int)>(
symbol: 'InternalFlutterGpu_DeviceBuffer_Overwrite')
external bool _overwrite(ByteData bytes, int destinationOffsetInBytes);
}
/// [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 with Buffer {
/// 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);
}