Skip to content

[Flutter GPU] Add automation to make importing Flutter GPU shaders easy. #144259

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

Closed
bdero opened this issue Feb 27, 2024 · 2 comments
Closed

[Flutter GPU] Add automation to make importing Flutter GPU shaders easy. #144259

bdero opened this issue Feb 27, 2024 · 2 comments
Assignees
Labels
c: proposal A detailed proposal for a change to Flutter flutter-gpu P2 Important issues not at the top of the work list r: fixed Issue is closed as already fixed in a newer version team-engine Owned by Engine team tool Affects the "flutter" command-line tool. See also t: labels. triaged-engine Triaged by Engine team

Comments

@bdero
Copy link
Member

bdero commented Feb 27, 2024

Part of #130921

Option 1: Offer a library for making native_asset build hooks easy.

Proof of concept build hook lib: https://github.com/bdero/test_native_assets/blob/master/hook/build.dart#L9-L138

To set up automated shaderbundle compilation, the user would:

  1. Define special json or yaml files in their project.
  2. Add a hook/build.dart file that invokes an imported function from the flutter_gpu package:
void main(List<String> args) async {
  await build(args, (config, output) async {
    await buildShaderBundle(
        buildConfig: config,
        buildOutput: output,
        manifestFileName: 'mybundle.shaderbundle.json');
  });
}
  1. Add watch rules for assets in the project's build directory.

Option 2: Use an Asset Transformer.

Make a simple transformer package that just ingests a manifest text file and finds/invokes impellerc, replacing this temp solution.

A few thoughts:

  • I'm not sure what the current status is for hot reloading in asset transformers, but we'll eventually want to support hot reloading shader bundles (which would require somehow instructing the tool to watch a list of dependent files for changes), but I don't see that as a super high priority right now.
  • Same goes for model imports in Flutter Scene, which is usually a simpler 1-1 model import situation, but will sometimes require watching multiple files similar to the shader bundle case (for example, glTFs with separated image files, or OBJs with separated MTLs).
  • The importer is locked to a specific version of ImpellerC. Rather than publish it on pub.dev, we should ship it as an SDK package under the packages directory in the flutter/flutter repo with an integration test ensuring that it doesn't break against the version of impellerc shipping in the engine artifacts.
  • Not a huge deal, but it would be nice if we could implicitly activate this particular transformer for all projects when they depend on the flutter_gpu SDK package automatically. Without this, I believe users of Flutter GPU will need to both depend on and activate the asset transformer by adding configuration similar to the following in pubspec.yaml:
dependencies:
  flutter_gpu:
    sdk: flutter
dev_dependencies:
  flutter_gpu_shaders:
    sdk: flutter
flutter:
  assets:
    - path: *.shaderbundle.yaml
      transformers:
        - package: flutter_gpu_shaders

Option 3: Add support directly to the Flutter tool.

Flutter GPU shaders are stored in libraries, and these libraries can be deserialized from "shader bundle" files.
For this task, add support to the Flutter tool for importing a collection of shader files as a shader bundle.

Here's an example of a shader bundle defined in a package pubspec.yaml file:

### pubspec.yaml ###
  - shader_bundle:
    - CoolShaderBundle:
      - FlatShadeVertex:
          type: vertex
          file: assets/shaders/flatshade.vert
      - FlatShadeFragment:
          type: fragment
          file: assets/shaders/flatshade.frag

This creates one shader bundle called "CoolShaderBundle" with two shader inputs: "FlatShadeVertex" and "FlatShadeFragment".

To produce this shader bundle asset, the flutter tool should run impellerc with the --shader_bundle parameter. Taking the example above, the call should look like this:

impellerc --sl="CoolShaderBundle.shaderbundle" \
  --shader_bundle="{\
    \"FlatShadeVertex\": { \
        \"type\": \"vertex\", \
        \"file\": \"assets/shaders/flatshade.vert\" \
      }, \
    \"FlatShadeVertex\": { \
        \"type\": \"vertex\", \
        \"file\": \"assets/shaders/flatshade.vert\" \
      } \
    } \
  }";

If any of the input source shader files have change, then the output shader bundle file (CoolShaderBundle.shaderbundle) needs to be rebuilt.

See also the Flutter GPU doc.

The shader bundle spec

For Flutter GPU's MVP, ImpellerC's --shader_bundle accepts a JSON string in the following form:

{
  "$shader_name" {
    "type": "[vertex|fragment]",
    "file": "$file_name"
  }
}

Later on, other per-shader parameters can be supported, such as ("language" and "entry_point").

Building shader bundles manually

Up until now, I've been building shader bundles manually in order to bootstrap some renderer projects. These bundles are produced using the impellerc executable shipped in the engine artifacts.

Here's an example of a valid invocation of ImpellerC, which builds a shader bundle asset named "assets/base.shaderbundle" with 5 builtin shaders:

BUNDLE_OUTPUT_FILENAME="assets/base.shaderbundle"
BASE_BUNDLE_JSON='
{
    "SimpleVertex": {
        "type": "vertex",
        "file": "shaders/flutter_scene_simple.vert"
    },
    "SimpleFragment": {
        "type": "fragment",
        "file": "shaders/flutter_scene_simple.frag"
    },
    "UnskinnedVertex": {
        "type": "vertex",
        "file": "shaders/flutter_scene_unskinned.vert"
    },
    "SkinnedVertex": {
        "type": "vertex",
        "file": "shaders/flutter_scene_skinned.vert"
    },
    "UnlitFragment": {
        "type": "fragment",
        "file": "shaders/flutter_scene_unlit.frag"
    }
}'
SHADER_BUNDLE_JSON=$(echo $2 | tr -d '\n')
impellerc --sl="$BUNDLE_OUTPUT_FILENAME" --shader-bundle="$BASE_BUNDLE_JSON"

Note that the actual names of the shaders in the bundle (SimpleVertex, SimpleFragment, etc) are entirely the user's choice.

How manually built shader bundles are imported.

Here's a simplified example of a Flutter GPU ShaderLibrary being deserialized from a shader bundle (as seen in the flutter_scene package):

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

final String _kBaseShaderBundlePath =
    'packages/flutter_scene/assets/base.shaderbundle';
gpu.ShaderLibrary get baseShaderLibrary {
  gpu.ShaderLibrary? result = gpu.ShaderLibrary.fromAsset(_kBaseShaderBundlePath);
  if (result != null) {
    return result!;
  }
  throw Exception(
      "Failed to load base shader bundle! ($_kBaseShaderBundlePath)");
}

From here, a ShaderBundle can be used by looking up shader names

gpu.Shader? myVertexShader = baseShaderLibrary["UnlitVertex"];
@github-project-automation github-project-automation bot moved this to 🤔 Needs Triage in Flutter GPU Feb 27, 2024
@chinmaygarde chinmaygarde moved this from 🤔 Needs Triage to 🔧 Internals in Flutter GPU Feb 27, 2024
@bdero bdero added this to the Flutter GPU MVP milestone Feb 27, 2024
@danagbemava-nc danagbemava-nc added in triage Presently being triaged by the triage team tool Affects the "flutter" command-line tool. See also t: labels. c: proposal A detailed proposal for a change to Flutter team-engine Owned by Engine team and removed in triage Presently being triaged by the triage team labels Feb 28, 2024
@jonahwilliams jonahwilliams added P2 Important issues not at the top of the work list triaged-engine Triaged by Engine team labels Mar 4, 2024
@bdero bdero self-assigned this Jun 18, 2024
@bdero bdero changed the title [Flutter GPU] Produce Flutter GPU shader bundles in the Flutter tool. [Flutter GPU] Add automation to make producing Flutter GPU shaderbundles easy. Jun 25, 2024
@bdero bdero changed the title [Flutter GPU] Add automation to make producing Flutter GPU shaderbundles easy. [Flutter GPU] Add automation to make importing Flutter GPU shaders easy. Jun 25, 2024
@bdero
Copy link
Member Author

bdero commented Sep 17, 2024

This is done. We ended up rolling a Native Assets solution for this: https://pub.dev/packages/flutter_gpu_shaders

@bdero bdero closed this as completed Sep 17, 2024
@github-project-automation github-project-automation bot moved this from 🔧 Internals to ✅ Done in Flutter GPU Sep 17, 2024
@danagbemava-nc danagbemava-nc added the r: fixed Issue is closed as already fixed in a newer version label Sep 18, 2024
Copy link

github-actions bot commented Oct 2, 2024

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
c: proposal A detailed proposal for a change to Flutter flutter-gpu P2 Important issues not at the top of the work list r: fixed Issue is closed as already fixed in a newer version team-engine Owned by Engine team tool Affects the "flutter" command-line tool. See also t: labels. triaged-engine Triaged by Engine team
Projects
Archived in project
Development

No branches or pull requests

3 participants