Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Flutter GPU] Move method tests to flutter_tester. #51223

Merged
merged 2 commits into from
Mar 6, 2024
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
141 changes: 0 additions & 141 deletions impeller/fixtures/dart_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,147 +19,6 @@ void instantiateDefaultContext() {
final gpu.GpuContext context = gpu.gpuContext;
}

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

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);
}

@pragma('vm:entry-point')
void canCreateDeviceBuffer() {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);
assert(deviceBuffer!.sizeInBytes == 4);
}

@pragma('vm:entry-point')
void canOverwriteDeviceBuffer() {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);
final bool success = deviceBuffer!
.overwrite(Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData());
assert(success);
}

@pragma('vm:entry-point')
void deviceBufferOverwriteFailsWhenOutOfBounds() {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);
final bool success = deviceBuffer!.overwrite(
Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData(),
destinationOffsetInBytes: 1);
assert(!success);
}

@pragma('vm:entry-point')
void deviceBufferOverwriteThrowsForNegativeDestinationOffset() {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);
String? exception;
try {
deviceBuffer!.overwrite(
Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData(),
destinationOffsetInBytes: -1);
} catch (e) {
exception = e.toString();
}
assert(exception!.contains('destinationOffsetInBytes must be positive'));
}

@pragma('vm:entry-point')
void canCreateTexture() {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100);
assert(texture != null);

// Check the defaults.
assert(
texture!.coordinateSystem == gpu.TextureCoordinateSystem.renderToTexture);
assert(texture!.width == 100);
assert(texture!.height == 100);
assert(texture!.storageMode == gpu.StorageMode.hostVisible);
assert(texture!.sampleCount == 1);
assert(texture!.format == gpu.PixelFormat.r8g8b8a8UNormInt);
assert(texture!.enableRenderTargetUsage);
assert(texture!.enableShaderReadUsage);
assert(!texture!.enableShaderWriteUsage);
assert(texture!.bytesPerTexel == 4);
assert(texture!.GetBaseMipLevelSizeInBytes() == 40000);
}

@pragma('vm:entry-point')
void canOverwriteTexture() {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 2, 2);
assert(texture != null);
final ui.Color red = ui.Color.fromARGB(0xFF, 0xFF, 0, 0);
final ui.Color green = ui.Color.fromARGB(0xFF, 0, 0xFF, 0);
final bool success = texture!.overwrite(
Int32List.fromList(<int>[red.value, green.value, green.value, red.value])
.buffer
.asByteData());
assert(success);
}

@pragma('vm:entry-point')
void textureOverwriteThrowsForWrongBufferSize() {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100);
assert(texture != null);
final ui.Color red = ui.Color.fromARGB(0xFF, 0xFF, 0, 0);
String? exception;
try {
texture!.overwrite(
Int32List.fromList(<int>[red.value, red.value, red.value, red.value])
.buffer
.asByteData());
} catch (e) {
exception = e.toString();
}
assert(exception!.contains(
'The length of sourceBytes (bytes: 16) must exactly match the size of the base mip level (bytes: 40000)'));
}

@pragma('vm:entry-point')
void textureAsImageReturnsAValidUIImageHandle() {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100);
assert(texture != null);

final ui.Image image = texture!.asImage();
assert(image.width == 100);
assert(image.height == 100);
}

@pragma('vm:entry-point')
void textureAsImageThrowsWhenNotShaderReadable() {
final gpu.Texture? texture = gpu.gpuContext.createTexture(
gpu.StorageMode.hostVisible, 100, 100,
enableShaderReadUsage: false);
assert(texture != null);
String? exception;
try {
texture!.asImage();
} catch (e) {
exception = e.toString();
}
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');
Expand Down
13 changes: 0 additions & 13 deletions impeller/renderer/renderer_dart_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,6 @@ TEST_P(RendererDartTest, CanInstantiateFlutterGPUContext) {
/// These test entries correspond to Dart functions located in
/// `flutter/impeller/fixtures/dart_tests.dart`

DART_TEST_CASE(canEmplaceHostBuffer);

DART_TEST_CASE(canCreateDeviceBuffer);
DART_TEST_CASE(canOverwriteDeviceBuffer);
DART_TEST_CASE(deviceBufferOverwriteFailsWhenOutOfBounds);
DART_TEST_CASE(deviceBufferOverwriteThrowsForNegativeDestinationOffset);

DART_TEST_CASE(canCreateTexture);
DART_TEST_CASE(canOverwriteTexture);
DART_TEST_CASE(textureOverwriteThrowsForWrongBufferSize);
DART_TEST_CASE(textureAsImageReturnsAValidUIImageHandle);
DART_TEST_CASE(textureAsImageThrowsWhenNotShaderReadable);

DART_TEST_CASE(canCreateShaderLibrary);
DART_TEST_CASE(canReflectUniformStructs);
DART_TEST_CASE(uniformBindFailsForInvalidHostBufferOffset);
Expand Down
147 changes: 146 additions & 1 deletion testing/dart/gpu_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

// ignore_for_file: avoid_relative_lib_imports

import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:litetest/litetest.dart';
import '../../lib/gpu/lib/gpu.dart' as gpu;

import '../../lib/gpu/lib/gpu.dart' as gpu;
import 'impeller_enabled.dart';

void main() {
Expand Down Expand Up @@ -41,4 +44,146 @@ void main() {
'Flutter GPU requires the Impeller rendering backend to be enabled.'));
}
});

test('HostBuffer.emplace', () async {
final gpu.HostBuffer hostBuffer = gpu.gpuContext.createHostBuffer();

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

final gpu.BufferView view1 = hostBuffer
.emplace(Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData());
expect(view1.offsetInBytes >= 4, true);
expect(view1.lengthInBytes, 4);
}, skip: !impellerEnabled);

test('GpuContext.createDeviceBuffer', () async {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);

expect(deviceBuffer!.sizeInBytes, 4);
}, skip: !impellerEnabled);

test('DeviceBuffer.overwrite', () async {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);

final bool success = deviceBuffer!
.overwrite(Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData());
expect(success, true);
}, skip: !impellerEnabled);

test('DeviceBuffer.overwrite fails when out of bounds', () async {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);

final bool success = deviceBuffer!.overwrite(
Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData(),
destinationOffsetInBytes: 1);
expect(success, false);
}, skip: !impellerEnabled);

test('DeviceBuffer.overwrite throws for negative destination offset',
() async {
final gpu.DeviceBuffer? deviceBuffer =
gpu.gpuContext.createDeviceBuffer(gpu.StorageMode.hostVisible, 4);
assert(deviceBuffer != null);

try {
deviceBuffer!.overwrite(
Int8List.fromList(<int>[0, 1, 2, 3]).buffer.asByteData(),
destinationOffsetInBytes: -1);
fail('Exception not thrown for negative destination offset.');
} catch (e) {
expect(
e.toString(), contains('destinationOffsetInBytes must be positive'));
}
}, skip: !impellerEnabled);

test('GpuContext.createTexture', () async {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100);
assert(texture != null);

// Check the defaults.
expect(
texture!.coordinateSystem, gpu.TextureCoordinateSystem.renderToTexture);
expect(texture.width, 100);
expect(texture.height, 100);
expect(texture.storageMode, gpu.StorageMode.hostVisible);
expect(texture.sampleCount, 1);
expect(texture.format, gpu.PixelFormat.r8g8b8a8UNormInt);
expect(texture.enableRenderTargetUsage, true);
expect(texture.enableShaderReadUsage, true);
expect(!texture.enableShaderWriteUsage, true);
expect(texture.bytesPerTexel, 4);
expect(texture.GetBaseMipLevelSizeInBytes(), 40000);
}, skip: !impellerEnabled);

test('Texture.overwrite', () async {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 2, 2);
assert(texture != null);

const ui.Color red = ui.Color.fromARGB(0xFF, 0xFF, 0, 0);
const ui.Color green = ui.Color.fromARGB(0xFF, 0, 0xFF, 0);
final bool success = texture!.overwrite(Int32List.fromList(
<int>[red.value, green.value, green.value, red.value])
.buffer
.asByteData());

expect(success, true);
}, skip: !impellerEnabled);

test('Texture.overwrite throws for wrong buffer size', () async {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100);
assert(texture != null);

const ui.Color red = ui.Color.fromARGB(0xFF, 0xFF, 0, 0);
try {
texture!.overwrite(
Int32List.fromList(<int>[red.value, red.value, red.value, red.value])
.buffer
.asByteData());
fail('Exception not thrown for wrong buffer size.');
} catch (e) {
expect(
e.toString(),
contains(
'The length of sourceBytes (bytes: 16) must exactly match the size of the base mip level (bytes: 40000)'));
}
}, skip: !impellerEnabled);

test('Texture.asImage returns a valid ui.Image handle', () async {
final gpu.Texture? texture =
gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100);
assert(texture != null);

final ui.Image image = texture!.asImage();
expect(image.width, 100);
expect(image.height, 100);
}, skip: !impellerEnabled);

test('Texture.asImage throws when not shader readable', () async {
final gpu.Texture? texture = gpu.gpuContext.createTexture(
gpu.StorageMode.hostVisible, 100, 100,
enableShaderReadUsage: false);
assert(texture != null);

try {
texture!.asImage();
fail('Exception not thrown when not shader readable.');
} catch (e) {
expect(
e.toString(),
contains(
'Only shader readable Flutter GPU textures can be used as UI Images'));
}
}, skip: !impellerEnabled);
}