Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Starts a transition to an async FragmentProgram.fromAsset #34922

Merged
merged 1 commit into from
Jul 26, 2022
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 lib/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4049,6 +4049,12 @@ class FragmentProgram extends NativeFieldWrapperClass1 {
return program;
}

// TODO(zra): This is part of a soft transition of the framework to this
// API, which pushes the asset load to an asynchronous operation.
static Future<FragmentProgram> fromAssetAsync(String assetKey) {
return Future<FragmentProgram>.microtask(() => FragmentProgram.fromAsset(assetKey));
}

static Map<String, WeakReference<FragmentProgram>> _shaderRegistry =
<String, WeakReference<FragmentProgram>>{};

Expand Down
4 changes: 4 additions & 0 deletions lib/web_ui/lib/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,10 @@ class FragmentProgram {
throw UnsupportedError('FragmentProgram is not supported for the CanvasKit or HTML renderers.');
}

static Future<FragmentProgram> fromAssetAsync(String assetKey) {
return Future<FragmentProgram>.microtask(() => FragmentProgram.fromAsset(assetKey));
}

FragmentProgram._();

Shader shader({
Expand Down
51 changes: 29 additions & 22 deletions testing/dart/fragment_shader_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import 'package:path/path.dart' as path;

import 'shader_test_file_utils.dart';

void main() {
void main() async {
test('simple shader renders correctly', () async {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'functions.frag.iplr',
);
final Shader shader = program.shader(
Expand All @@ -25,7 +25,7 @@ void main() {
});

test('blue-green image renders green', () async {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'blue_green_sampler.frag.iplr',
);
final Image blueGreenImage = await _createBlueGreenImage();
Expand All @@ -39,7 +39,7 @@ void main() {
});

test('shader with uniforms renders correctly', () async {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'uniforms.frag.iplr',
);

Expand All @@ -65,7 +65,7 @@ void main() {
});

test('The ink_sparkle shader is accepted', () async {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'ink_sparkle.frag.iplr',
);
final Shader shader = program.shader(
Expand All @@ -79,7 +79,7 @@ void main() {
});

test('Uniforms are sorted correctly', () async {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'uniforms_sorted.frag.iplr',
);

Expand All @@ -97,7 +97,7 @@ void main() {
test('fromAsset throws an exception on invalid assetKey', () async {
bool throws = false;
try {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'<invalid>',
);
} catch (e) {
Expand All @@ -109,7 +109,7 @@ void main() {
test('fromAsset throws an exception on invalid data', () async {
bool throws = false;
try {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'DashInNooglerHat.jpg',
);
} catch (e) {
Expand All @@ -119,31 +119,31 @@ void main() {
});

test('fromAsset accepts a shader with no uniforms', () async {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'no_uniforms.frag.iplr',
);
final Shader shader = program.shader();
await _expectShaderRendersGreen(shader);
});

// Test all supported GLSL ops. See lib/spirv/lib/src/constants.dart
final Map<String, FragmentProgram> iplrSupportedGLSLOpShaders = _loadShaderAssets(
final Map<String, FragmentProgram> iplrSupportedGLSLOpShaders = await _loadShaderAssets(
path.join('supported_glsl_op_shaders', 'iplr'),
'.iplr',
);
expect(iplrSupportedGLSLOpShaders.isNotEmpty, true);
_expectIplrShadersRenderGreen(iplrSupportedGLSLOpShaders);

// Test all supported instructions. See lib/spirv/lib/src/constants.dart
final Map<String, FragmentProgram> iplrSupportedOpShaders = _loadShaderAssets(
final Map<String, FragmentProgram> iplrSupportedOpShaders = await _loadShaderAssets(
path.join('supported_op_shaders', 'iplr'),
'.iplr',
);
expect(iplrSupportedOpShaders.isNotEmpty, true);
_expectIplrShadersRenderGreen(iplrSupportedOpShaders);

test('Equality depends on floatUniforms', () {
final FragmentProgram program = FragmentProgram.fromAsset(
test('Equality depends on floatUniforms', () async {
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'simple.frag.iplr',
);
final Float32List ones = Float32List.fromList(<double>[1]);
Expand All @@ -165,10 +165,10 @@ void main() {
});

test('Equality depends on data', () async {
final FragmentProgram programA = FragmentProgram.fromAsset(
final FragmentProgram programA = await FragmentProgram.fromAssetAsync(
'simple.frag.iplr',
);
final FragmentProgram programB = FragmentProgram.fromAsset(
final FragmentProgram programB = await FragmentProgram.fromAssetAsync(
'uniforms.frag.iplr',
);
final Shader a = programA.shader();
Expand Down Expand Up @@ -225,21 +225,28 @@ Future<ByteData?> _imageByteDataFromShader({
// $FLUTTER_BUILD_DIRECTORY/gen/flutter/lib/spirv/test/$leafFolderName
// This is synchronous so that tests can be inside of a loop with
// the proper test name.
Map<String, FragmentProgram> _loadShaderAssets(String leafFolderName, String ext) {
Future<Map<String, FragmentProgram>> _loadShaderAssets(
String leafFolderName,
String ext,
) async {
final Map<String, FragmentProgram> out = SplayTreeMap<String, FragmentProgram>();

final Directory directory = shaderDirectory(leafFolderName);
if (!directory.existsSync()) {
return out;
}

directory
await Future.forEach(
directory
.listSync()
.where((FileSystemEntity entry) => path.extension(entry.path) == ext)
.forEach((FileSystemEntity entry) {
final String key = path.basenameWithoutExtension(entry.path);
out[key] = FragmentProgram.fromAsset(path.basename(entry.path));
});
.where((FileSystemEntity entry) => path.extension(entry.path) == ext),
(FileSystemEntity entry) async {
final String key = path.basenameWithoutExtension(entry.path);
out[key] = await FragmentProgram.fromAssetAsync(
path.basename(entry.path),
);
},
);
return out;
}

Expand Down
2 changes: 1 addition & 1 deletion testing/dart/observatory/shader_reload_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ void main() {
test('simple iplr shader can be re-initialized', () async {
vms.VmService? vmService;
try {
final FragmentProgram program = FragmentProgram.fromAsset(
final FragmentProgram program = await FragmentProgram.fromAssetAsync(
'functions.frag.iplr',
);
final Shader shader = program.shader(
Expand Down