flutter / flutter/flutter

flutter gpu: quick start flutter gpu example not working

Open
#169,062 10 comments 5 reactions 0 assignees View on GitHub
a: gamedev e: impeller engine flutter-gpu found in release: 3.33 found in release: 3.35 has reproducible steps P3 platform-android team-engine triaged-engine
Dominant language
Dart
Stars
179k
Forks
31.1k
PR merge metrics
PR metrics pending

Description

Steps to reproduce

A white screen is showing with a 300X300 not blue background is showing and no triangle is showing below is the reference image
[
![Image](https://github.com/user-attachments/assets/4912ef2c-5d1f-4ca5-8a82-58665d13ffa9)
](url)

1. i followed the instruction from this [link](https://medium.com/flutter/getting-started-with-flutter-gpu-f33d497b7c11) as mentioned in[ flutter gpu guide markdown file](https://github.com/flutter/engine/blob/main/docs/impeller/Flutter-GPU.md) from flutter/engine
2. the code for the main.dart is

```
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_gpu/gpu.dart' as gpu;
import 'package:vector_math/vector_math.dart' as vm;
import 'shaders.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter GPU Triangle Example',
home: Scaffold(
body: Center(
child: CustomPaint(
size: const Size(300, 300),
painter: TrianglePainter(),
),
),
),
);
}
}

class TrianglePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
try {
print('--- Starting GPU triangle rendering ---');

// 1. Create texture
final texture = gpu.gpuContext.createTexture(
gpu.StorageMode.hostVisible,
size.width.toInt(),
size.height.toInt(),
);
if (texture == null) throw Exception('Texture creation failed');
print('Texture created: ${size.width} x ${size.height}');

// 2. Set up render target
final renderTarget = gpu.RenderTarget.singleColor(
gpu.ColorAttachment(
texture: texture,
clearValue: vm.Vector4(0.0, 0.0, 1.0, 1.0), // Clear to blue
),
);
print('Render target created');

// 3. Create command buffer and render pass
final commandBuffer = gpu.gpuContext.createCommandBuffer();
final renderPass = commandBuffer.createRenderPass(renderTarget);
print('Render pass created');

// 4. Load shaders
final vert = shaderLibrary['SimpleVertex'];
final frag = shaderLibrary['SimpleFragment'];
if (vert == null || frag == null) {
throw Exception('Shader(s) missing! Vertex: $vert, Fragment: $frag');
}
print('Shaders loaded');

// 5. Create pipeline
final pipeline = gpu.gpuContext.createRenderPipeline(vert, frag);
print('Render pipeline created');

// 6. Define triangle vertices
final vertices = Float32List.fromList([
-1.0, -1.0, // Bottom-left
1.0, -1.0, // Bottom-right
0.0, 1.0, // Top-center
]);
print('Vertices defined: $vertices');

// 7. Upload vertices to GPU
final vertexBuffer = gpu.gpuContext.createDeviceBufferWithCopy(
ByteData.sublistView(vertices),
);
if (vertexBuffer == null) throw Exception('Vertex buffer creation failed');
print('Vertex buffer created and uploaded');

// 8. Bind pipeline and vertex buffer
final vertexBufferView = gpu.BufferView(
vertexBuffer, // Positional DeviceBuffer argument
offsetInBytes: 0, // Named
lengthInBytes: vertices.lengthInBytes, // Named (24 bytes)
);
renderPass.bindPipeline(pipeline);
renderPass.bindVertexBuffer(vertexBufferView, 8); // 2 floats × 4 bytes per vertex
renderPass.draw();
print('Draw commands issued');

// 9. Submit command buffer
commandBuffer.submit();
print('Command buffer submitted');

// 10. Convert texture to image
final image = texture.asImage();
if (image != null) {
canvas.drawImage(image, Offset.zero, Paint());
print('Image drawn on canvas');
} else {
throw Exception('Failed to convert texture to image');
}

} catch (e, stackTrace) {
print('Rendering error: $e\n$stackTrace');
// Red background if rendering fails
canvas.drawRect(
Rect.fromLTWH(0, 0, size.width, size.height),
Paint()..color = Colors.red,
);
}
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
```

3. the code for the shaders.dart is

```
import 'package:flutter_gpu/gpu.dart' as gpu;

const String _kShaderBundlePath =
'build/shaderbundles/my_renderer.shaderbundle';
// NOTE: If you're building a library, the path must be prefixed
// with a package name. For example:
// 'packages/my_cool_renderer/build/shaderbundles/my_renderer.shaderbundle'

gpu.ShaderLibrary? _shaderLibrary;
gpu.ShaderLibrary get shaderLibrary {
if (_shaderLibrary != null) {
print('Returning cached shader library');
return _shaderLibrary!;
}

print('Attempting to load shader bundle from: $_kShaderBundlePath');
try {
_shaderLibrary = gpu.ShaderLibrary.fromAsset(_kShaderBundlePath);
print('Shader library loaded: ${_shaderLibrary != null}');
} catch (e) {
print('Error loading shader bundle: $e');
rethrow;
}

if (_shaderLibrary != null) {
return _shaderLibrary!;
}

throw Exception("Failed to load shader bundle! ($_kShaderBundlePath)");
}
```

4. simple.frag

```
// Copy into: shaders/simple.frag

out vec4 frag_color;
void main() {
frag_color = vec4(1.0, 0.0, 0.0, 1.0); // Solid red
}

```

5. simple.vert

```
// simple.vert
layout(location = 0) in vec2 position;

void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
```

6. hook/build.dart
```
// Copy into: hook/build.dart

import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:flutter_gpu_shaders/build.dart';

void main(List args) async {
await build(args, (config, output) async {
await buildShaderBundleJson(
buildOutput: output,
manifestFileName: 'my_renderer.shaderbundle.json', buildInput: config);
});
}
```

7. pubspec.yaml

```
name: test_gpu
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1

environment:
sdk: ^3.9.0-100.2.beta

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
flutter_gpu:
sdk: flutter
flutter_gpu_shaders: ^0.3.0
vector_math: ^2.1.4
# native_assets_cli: ^0.13.0
# flutter_scene_importer: ^0.9.0-0

dev_dependencies:
flutter_test:
sdk: flutter

# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^5.0.0

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter packages.
flutter:

# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true

# To add assets to your application, add an assets section, like this:
# assets:
assets:
- build/shaderbundles/my_renderer.shaderbundle
# - build/models/
# - assets/DamagedHelmet.glb/

# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg

# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images

# For details regarding adding assets from package dependencies, see
# https://flutter.dev/to/asset-from-package

# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/to/font-from-package
```

8. defaultConfig of android/app/build.gradle.kts

```
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}

android {
namespace = "com.example.test_gpu"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.test_gpu"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}

flutter {
source = "../.."
}

```

9. i tried flutter run -d android --enable-impeller, i got

```
PS C:\Users\jahan\AndroidStudioProjects\test_gpu> flutter run -d 23129RN51X --enable-impeller
Launching lib\main.dart on 23129RN51X in debug mode...
Running Gradle task 'assembleDebug'... 5.6s
√ Built build\app\outputs\flutter-apk\app-debug.apk
Installing build\app\outputs\flutter-apk\app-debug.apk... 4.4s
I/flutter ( 2125): [IMPORTANT:flutter/shell/platform/android/android_context_vk_impeller.cc(62)] Using the Impeller rendering backend (Vulkan).
I/flutter ( 2125): [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(104)] Using the Impeller rendering backend (OpenGLES).
Syncing files to device 23129RN51X... 66ms

Flutter run key commands.
r Hot reload.
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

A Dart VM Service on 23129RN51X is available at: http://127.0.0.1:62053/O126ZRQaUVo=/
The Flutter DevTools debugger and profiler on 23129RN51X is available at: http://127.0.0.1:9100?uri=http://127.0.0.1:62053/O126ZRQaUVo=/
I/Choreographer( 2125): Skipped 378 frames! The application may be doing too much work on its main thread.
D/BufferQueueConsumer( 2125): [](id:84d00000000,api:0,p:-1,c:2125) connect: controlledByApp=false
D/libMEOW ( 2125): meow new tls: 0xd0e70580
D/libMEOW ( 2125): applied 1 plugins for [com.example.test_gpu]:
D/libMEOW ( 2125): plugin 1: [libMEOW_gift.so]: 0xec8f2800
D/libMEOW ( 2125): rebuild call chain: 0xd0980600
E/OpenGLRenderer( 2125): Unable to match the desired swap behavior.
D/BufferQueueConsumer( 2125): [](id:84d00000001,api:0,p:-1,c:2125) connect: controlledByApp=false
D/MAGT_SYNC_FRAME( 2125): MAGT Sync: MAGT is not supported. Disabling Sync.
I/flutter ( 2125): --- Starting GPU triangle rendering ---
E/libEGL ( 2125): call to OpenGL ES API with no current context (logged once per thread)
I/flutter ( 2125): Texture created: 300.0 x 300.0
I/flutter ( 2125): Render target created
I/flutter ( 2125): Render pass created
I/flutter ( 2125): Attempting to load shader bundle from: build/shaderbundles/my_renderer.shaderbundle
I/flutter ( 2125): Shader library loaded: true
I/flutter ( 2125): Returning cached shader library
I/flutter ( 2125): Shaders loaded
I/flutter ( 2125): Render pipeline created
I/flutter ( 2125): Vertices defined: [-1.0, -1.0, 1.0, -1.0, 0.0, 1.0]
I/flutter ( 2125): Vertex buffer created and uploaded
I/flutter ( 2125): Draw commands issued
I/flutter ( 2125): Command buffer submitted
I/flutter ( 2125): Image drawn on canvas
D/BLASTBufferQueue( 2125): [SurfaceView[com.example.test_gpu/com.example.test_gpu.MainActivity]#1](f:0,a:1) acquireNextBufferLocked size=720x1554 mFrameNumber=1 applyTransaction=true mTimestamp=288625502225972(auto) mPendingTransactions.size=0 graphicBufferId=9126805504001 transform=0
I/Choreographer( 2125): Skipped 43 frames! The application may be doing too much work on its main thread.
D/BLASTBufferQueue( 2125): [VRI[MainActivity]#0](f:0,a:1) acquireNextBufferLocked size=720x1650 mFrameNumber=1 applyTransaction=true mTimestamp=288625609604972(auto) mPendingTransactions.size=0 graphicBufferId=9126805504002 transform=0
I/OpenGLRenderer( 2125): Davey! duration=772ms; Flags=1, FrameTimelineVsyncId=4908439, IntendedVsync=288624835949320, Vsync=288625552616001, InputEventId=0, HandleInputStart=288625568669972, AnimationSt
art=288625568675741, PerformTraversalsStart=288625568678280, DrawStart=288625590868741, FrameDeadline=288624855949320, FrameInterval=288625567787818, FrameStartTime=16666667, SyncQueued=288625594032972,
SyncStart=288625598439511, IssueDrawCommandsStart=288625599634895, SwapBuffers=288625607535741, FrameCompleted=288625612432741, DequeueBufferDuration=0, QueueBufferDuration=1375384, GpuCompleted=288625612432741, SwapBuffersCompleted=288625611498280, DisplayPresentTime=0, CommandSubmissionCompleted=288625607535741,
D/ProfileInstaller( 2125): Installing profile for com.example.test_gpu
```
### Expected results
i was expecting that a triangle would be drawn and displayed.

### Actual results
[
![Image](https://github.com/user-attachments/assets/4912ef2c-5d1f-4ca5-8a82-58665d13ffa9)
](url)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.