mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Don't hardcode ink sparkle spir-v (#102674)
This commit is contained in:
parent
d1bbd822c0
commit
577919dbfe
@ -472,6 +472,7 @@ Future<void> verifyNoMissingLicense(String workingDirectory, { bool checkMinimum
|
||||
failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'ps1', overrideMinimumMatches ?? 1, _generateLicense('# '));
|
||||
failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'html', overrideMinimumMatches ?? 1, '<!-- ${_generateLicense('')} -->', trailingBlank: false, header: r'<!DOCTYPE HTML>\n');
|
||||
failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'xml', overrideMinimumMatches ?? 1, '<!-- ${_generateLicense('')} -->', header: r'(<\?xml version="1.0" encoding="utf-8"\?>\n)?');
|
||||
failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'frag', overrideMinimumMatches ?? 1, _generateLicense('// '), header: r'#version 320 es(\n)+');
|
||||
if (failed > 0) {
|
||||
exitWithError(<String>['License check failed.']);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
106
packages/flutter/lib/src/material/shaders/ink_sparkle.frag
Normal file
106
packages/flutter/lib/src/material/shaders/ink_sparkle.frag
Normal file
@ -0,0 +1,106 @@
|
||||
#version 320 es
|
||||
|
||||
// Copyright 2014 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.
|
||||
|
||||
precision highp float;
|
||||
|
||||
// TODO(antrob): Put these in a more logical order (e.g. separate consts vs varying, etc)
|
||||
|
||||
layout(location = 0) uniform vec4 u_color;
|
||||
layout(location = 1) uniform float u_alpha;
|
||||
layout(location = 2) uniform vec4 u_sparkle_color;
|
||||
layout(location = 3) uniform float u_sparkle_alpha;
|
||||
layout(location = 4) uniform float u_blur;
|
||||
layout(location = 5) uniform vec2 u_center;
|
||||
layout(location = 6) uniform float u_radius_scale;
|
||||
layout(location = 7) uniform float u_max_radius;
|
||||
layout(location = 8) uniform vec2 u_resolution_scale;
|
||||
layout(location = 9) uniform vec2 u_noise_scale;
|
||||
layout(location = 10) uniform float u_noise_phase;
|
||||
layout(location = 11) uniform vec2 u_circle1;
|
||||
layout(location = 12) uniform vec2 u_circle2;
|
||||
layout(location = 13) uniform vec2 u_circle3;
|
||||
layout(location = 14) uniform vec2 u_rotation1;
|
||||
layout(location = 15) uniform vec2 u_rotation2;
|
||||
layout(location = 16) uniform vec2 u_rotation3;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
const float PI = 3.1415926535897932384626;
|
||||
const float PI_ROTATE_RIGHT = PI * 0.0078125;
|
||||
const float PI_ROTATE_LEFT = PI * -0.0078125;
|
||||
const float ONE_THIRD = 1./3.;
|
||||
const vec2 TURBULENCE_SCALE = vec2(0.8);
|
||||
|
||||
float saturate(float x) {
|
||||
return clamp(x, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float triangle_noise(highp vec2 n) {
|
||||
n = fract(n * vec2(5.3987, 5.4421));
|
||||
n += dot(n.yx, n.xy + vec2(21.5351, 14.3137));
|
||||
float xy = n.x * n.y;
|
||||
return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
|
||||
}
|
||||
|
||||
float threshold(float v, float l, float h) {
|
||||
return step(l, v) * (1.0 - step(h, v));
|
||||
}
|
||||
|
||||
mat2 rotate2d(vec2 rad){
|
||||
return mat2(rad.x, -rad.y, rad.y, rad.x);
|
||||
}
|
||||
|
||||
float soft_circle(vec2 uv, vec2 xy, float radius, float blur) {
|
||||
float blur_half = blur * 0.5;
|
||||
float d = distance(uv, xy);
|
||||
return 1.0 - smoothstep(1.0 - blur_half, 1.0 + blur_half, d / radius);
|
||||
}
|
||||
|
||||
float soft_ring(vec2 uv, vec2 xy, float radius, float thickness, float blur) {
|
||||
float circle_outer = soft_circle(uv, xy, radius + thickness, blur);
|
||||
float circle_inner = soft_circle(uv, xy, max(radius - thickness, 0.0), blur);
|
||||
return saturate(circle_outer - circle_inner);
|
||||
}
|
||||
|
||||
float circle_grid(vec2 resolution, vec2 p, vec2 xy, vec2 rotation, float cell_diameter) {
|
||||
p = rotate2d(rotation) * (xy - p) + xy;
|
||||
p = mod(p, cell_diameter) / resolution;
|
||||
float cell_uv = cell_diameter / resolution.y * 0.5;
|
||||
float r = 0.65 * cell_uv;
|
||||
return soft_circle(p, vec2(cell_uv), r, r * 50.0);
|
||||
}
|
||||
|
||||
float sparkle(vec2 uv, float t) {
|
||||
float n = triangle_noise(uv);
|
||||
float s = threshold(n, 0.0, 0.05);
|
||||
s += threshold(n + sin(PI * (t + 0.35)), 0.1, 0.15);
|
||||
s += threshold(n + sin(PI * (t + 0.7)), 0.2, 0.25);
|
||||
s += threshold(n + sin(PI * (t + 1.05)), 0.3, 0.35);
|
||||
return saturate(s) * 0.55;
|
||||
}
|
||||
|
||||
float turbulence(vec2 uv) {
|
||||
vec2 uv_scale = uv * TURBULENCE_SCALE;
|
||||
float g1 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle1, u_rotation1, 0.17);
|
||||
float g2 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle2, u_rotation2, 0.2);
|
||||
float g3 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle3, u_rotation3, 0.275);
|
||||
float v = (g1 * g1 + g2 - g3) * 0.5;
|
||||
return saturate(0.45 + 0.8 * v);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 p = gl_FragCoord.xy;
|
||||
vec2 uv = p * u_resolution_scale;
|
||||
vec2 density_uv = uv - mod(p, u_noise_scale);
|
||||
float radius = u_max_radius * u_radius_scale;
|
||||
float turbulence = turbulence(uv);
|
||||
float ring = soft_ring(p, u_center, radius, 0.05 * u_max_radius, u_blur);
|
||||
float sparkle = sparkle(density_uv, u_noise_phase) * ring * turbulence * u_sparkle_alpha;
|
||||
float wave_alpha = soft_circle(p, u_center, radius, u_blur) * u_alpha * u_color.a;
|
||||
vec4 wave_color = vec4(u_color.rgb * wave_alpha, wave_alpha);
|
||||
vec4 sparkle_color = vec4(u_sparkle_color.rgb * u_sparkle_color.a, u_sparkle_color.a);
|
||||
fragColor = mix(wave_color, sparkle_color, sparkle);
|
||||
}
|
||||
@ -43,6 +43,10 @@ const List<Map<String, Object>> kMaterialFonts = <Map<String, Object>>[
|
||||
},
|
||||
];
|
||||
|
||||
const List<String> kMaterialShaders = <String>[
|
||||
'shaders/ink_sparkle.frag',
|
||||
];
|
||||
|
||||
/// Injected factory class for spawning [AssetBundle] instances.
|
||||
abstract class AssetBundleFactory {
|
||||
/// The singleton instance, pulled from the [AppContext].
|
||||
@ -404,11 +408,15 @@ class ManifestAssetBundle implements AssetBundle {
|
||||
}
|
||||
final List<_Asset> materialAssets = <_Asset>[
|
||||
if (flutterManifest.usesMaterialDesign)
|
||||
..._getMaterialAssets(),
|
||||
..._getMaterialFonts(),
|
||||
// Include the shaders unconditionally. They are small, and whether
|
||||
// they're used is determined only by the app source code and not by
|
||||
// the Flutter manifest.
|
||||
..._getMaterialShaders(),
|
||||
];
|
||||
for (final _Asset asset in materialAssets) {
|
||||
final File assetFile = asset.lookupAssetFile(_fileSystem);
|
||||
assert(assetFile.existsSync());
|
||||
assert(assetFile.existsSync(), 'Missing ${assetFile.path}');
|
||||
entries[asset.entryUri.path] ??= DevFSFileContent(assetFile);
|
||||
}
|
||||
|
||||
@ -490,7 +498,7 @@ class ManifestAssetBundle implements AssetBundle {
|
||||
}
|
||||
}
|
||||
|
||||
List<_Asset> _getMaterialAssets() {
|
||||
List<_Asset> _getMaterialFonts() {
|
||||
final List<_Asset> result = <_Asset>[];
|
||||
for (final Map<String, Object> family in kMaterialFonts) {
|
||||
final Object? fonts = family['fonts'];
|
||||
@ -504,7 +512,10 @@ class ManifestAssetBundle implements AssetBundle {
|
||||
}
|
||||
final Uri entryUri = _fileSystem.path.toUri(asset);
|
||||
result.add(_Asset(
|
||||
baseDir: _fileSystem.path.join(Cache.flutterRoot!, 'bin', 'cache', 'artifacts', 'material_fonts'),
|
||||
baseDir: _fileSystem.path.join(
|
||||
Cache.flutterRoot!,
|
||||
'bin', 'cache', 'artifacts', 'material_fonts',
|
||||
),
|
||||
relativeUri: Uri(path: entryUri.pathSegments.last),
|
||||
entryUri: entryUri,
|
||||
package: null,
|
||||
@ -515,6 +526,32 @@ class ManifestAssetBundle implements AssetBundle {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<_Asset> _getMaterialShaders() {
|
||||
final String shaderPath = _fileSystem.path.join(
|
||||
Cache.flutterRoot!,
|
||||
'packages', 'flutter', 'lib', 'src', 'material', 'shaders',
|
||||
);
|
||||
// This file will exist in a real invocation unless the git checkout is
|
||||
// corrupted somehow, but unit tests generally don't create this file
|
||||
// in their mock file systems. Leaving it out in those cases is harmless.
|
||||
if (!_fileSystem.directory(shaderPath).existsSync()) {
|
||||
return <_Asset>[];
|
||||
}
|
||||
|
||||
final List<_Asset> result = <_Asset>[];
|
||||
for (final String shader in kMaterialShaders) {
|
||||
final Uri entryUri = _fileSystem.path.toUri(shader);
|
||||
result.add(_Asset(
|
||||
baseDir: shaderPath,
|
||||
relativeUri: Uri(path: entryUri.pathSegments.last),
|
||||
entryUri: entryUri,
|
||||
package: null,
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
List<Map<String, Object?>> _parseFonts(
|
||||
FlutterManifest manifest,
|
||||
PackageConfig packageConfig, {
|
||||
|
||||
@ -14,6 +14,7 @@ import '../build_system.dart';
|
||||
import '../depfile.dart';
|
||||
import 'common.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'shader_compiler.dart';
|
||||
|
||||
/// A helper function to copy an asset bundle into an [environment]'s output
|
||||
/// directory.
|
||||
@ -24,7 +25,9 @@ import 'icon_tree_shaker.dart';
|
||||
/// included in the final bundle, but not the AssetManifest.json file.
|
||||
///
|
||||
/// Returns a [Depfile] containing all assets used in the build.
|
||||
Future<Depfile> copyAssets(Environment environment, Directory outputDirectory, {
|
||||
Future<Depfile> copyAssets(
|
||||
Environment environment,
|
||||
Directory outputDirectory, {
|
||||
Map<String, DevFSContent>? additionalContent,
|
||||
required TargetPlatform targetPlatform,
|
||||
BuildMode? buildMode,
|
||||
@ -72,6 +75,12 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory, {
|
||||
fileSystem: environment.fileSystem,
|
||||
artifacts: environment.artifacts,
|
||||
);
|
||||
final ShaderCompiler shaderCompiler = ShaderCompiler(
|
||||
processManager: environment.processManager,
|
||||
logger: environment.logger,
|
||||
fileSystem: environment.fileSystem,
|
||||
artifacts: environment.artifacts,
|
||||
);
|
||||
|
||||
final Map<String, DevFSContent> assetEntries = <String, DevFSContent>{
|
||||
...assetBundle.entries,
|
||||
@ -100,6 +109,9 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory, {
|
||||
input: content.file as File,
|
||||
outputPath: file.path,
|
||||
relativePath: entry.key,
|
||||
) && !await shaderCompiler.compileShader(
|
||||
input: content.file as File,
|
||||
outputPath: file.path,
|
||||
)) {
|
||||
await (content.file as File).copy(file.path);
|
||||
}
|
||||
@ -258,6 +270,7 @@ class CopyAssets extends Target {
|
||||
List<Source> get inputs => const <Source>[
|
||||
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/assets.dart'),
|
||||
...IconTreeShaker.inputs,
|
||||
...ShaderCompiler.inputs,
|
||||
];
|
||||
|
||||
@override
|
||||
|
||||
@ -18,6 +18,7 @@ import 'assets.dart';
|
||||
import 'dart_plugin_registrant.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'localizations.dart';
|
||||
import 'shader_compiler.dart';
|
||||
|
||||
/// Copies the pre-built flutter bundle.
|
||||
// This is a one-off rule for implementing build bundle in terms of assemble.
|
||||
@ -33,6 +34,7 @@ class CopyFlutterBundle extends Target {
|
||||
Source.artifact(Artifact.isolateSnapshotData, mode: BuildMode.debug),
|
||||
Source.pattern('{BUILD_DIR}/app.dill'),
|
||||
...IconTreeShaker.inputs,
|
||||
...ShaderCompiler.inputs,
|
||||
];
|
||||
|
||||
@override
|
||||
|
||||
@ -19,6 +19,7 @@ import '../exceptions.dart';
|
||||
import 'assets.dart';
|
||||
import 'common.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'shader_compiler.dart';
|
||||
|
||||
/// Supports compiling a dart kernel file to an assembly file.
|
||||
///
|
||||
@ -439,6 +440,7 @@ abstract class IosAssetBundle extends Target {
|
||||
Source.pattern('{BUILD_DIR}/App.framework/App'),
|
||||
Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
|
||||
...IconTreeShaker.inputs,
|
||||
...ShaderCompiler.inputs,
|
||||
];
|
||||
|
||||
@override
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
import 'package:process/process.dart';
|
||||
|
||||
import '../../artifacts.dart';
|
||||
import '../../base/common.dart';
|
||||
import '../../base/file_system.dart';
|
||||
import '../../base/io.dart';
|
||||
import '../../base/logger.dart';
|
||||
import '../../convert.dart';
|
||||
import '../build_system.dart';
|
||||
|
||||
/// A class the wraps the functionality of the Impeller shader compiler
|
||||
/// impellerc.
|
||||
class ShaderCompiler {
|
||||
ShaderCompiler({
|
||||
required ProcessManager processManager,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
required Artifacts artifacts,
|
||||
}) : _processManager = processManager,
|
||||
_logger = logger,
|
||||
_fs = fileSystem,
|
||||
_artifacts = artifacts;
|
||||
|
||||
final ProcessManager _processManager;
|
||||
final Logger _logger;
|
||||
final FileSystem _fs;
|
||||
final Artifacts _artifacts;
|
||||
|
||||
/// The [Source] inputs that targets using this should depend on.
|
||||
///
|
||||
/// See [Target.inputs].
|
||||
static const List<Source> inputs = <Source>[
|
||||
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/shader_compiler.dart'),
|
||||
Source.hostArtifact(HostArtifact.impellerc),
|
||||
];
|
||||
|
||||
/// Calls impellerc, which transforms the [input] glsl shader into a
|
||||
/// platform specific shader at [outputPath].
|
||||
///
|
||||
/// All parameters are required.
|
||||
///
|
||||
/// If the input file is not a fragment shader, this returns false.
|
||||
/// If the shader compiler subprocess fails, it will [throwToolExit].
|
||||
/// Otherwise, it will return true.
|
||||
Future<bool> compileShader({
|
||||
required File input,
|
||||
required String outputPath,
|
||||
}) async {
|
||||
if (!input.path.endsWith('.frag')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final File impellerc = _fs.file(
|
||||
_artifacts.getHostArtifact(HostArtifact.impellerc),
|
||||
);
|
||||
if (!impellerc.existsSync()) {
|
||||
throw ShaderCompilerException._(
|
||||
'The impellerc utility is missing at "${impellerc.path}". '
|
||||
'Run "flutter doctor".',
|
||||
);
|
||||
}
|
||||
|
||||
final List<String> cmd = <String>[
|
||||
impellerc.path,
|
||||
// TODO(zanderso): When impeller is enabled, the correct flags for the
|
||||
// target backend will need to be passed.
|
||||
// https://github.com/flutter/flutter/issues/102853
|
||||
'--flutter-spirv',
|
||||
'--spirv=$outputPath',
|
||||
'--input=${input.path}',
|
||||
];
|
||||
final Process impellercProcess = await _processManager.start(cmd);
|
||||
final int code = await impellercProcess.exitCode;
|
||||
if (code != 0) {
|
||||
_logger.printTrace(await utf8.decodeStream(impellercProcess.stdout));
|
||||
_logger.printError(await utf8.decodeStream(impellercProcess.stderr));
|
||||
throw ShaderCompilerException._(
|
||||
'Shader compilation of "${input.path}" to "$outputPath" '
|
||||
'failed with exit code $code.',
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class ShaderCompilerException implements Exception {
|
||||
ShaderCompilerException._(this.message);
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => 'ShaderCompilerException: $message\n\n';
|
||||
}
|
||||
@ -13,6 +13,7 @@ import 'build_info.dart';
|
||||
import 'build_system/build_system.dart';
|
||||
import 'build_system/depfile.dart';
|
||||
import 'build_system/targets/common.dart';
|
||||
import 'build_system/targets/shader_compiler.dart';
|
||||
import 'bundle.dart';
|
||||
import 'cache.dart';
|
||||
import 'devfs.dart';
|
||||
@ -148,6 +149,13 @@ Future<void> writeBundle(
|
||||
}
|
||||
bundleDir.createSync(recursive: true);
|
||||
|
||||
final ShaderCompiler shaderCompiler = ShaderCompiler(
|
||||
processManager: globals.processManager,
|
||||
logger: globals.logger,
|
||||
fileSystem: globals.fs,
|
||||
artifacts: globals.artifacts!,
|
||||
);
|
||||
|
||||
// Limit number of open files to avoid running out of file descriptors.
|
||||
final Pool pool = Pool(64);
|
||||
await Future.wait<void>(
|
||||
@ -161,7 +169,15 @@ Future<void> writeBundle(
|
||||
// and the native APIs will look for files this way.
|
||||
final File file = globals.fs.file(globals.fs.path.join(bundleDir.path, entry.key));
|
||||
file.parent.createSync(recursive: true);
|
||||
await file.writeAsBytes(await entry.value.contentsAsBytes());
|
||||
final DevFSContent devFSContent = entry.value;
|
||||
if (devFSContent is DevFSFileContent) {
|
||||
final File input = devFSContent.file as File;
|
||||
if (!await shaderCompiler.compileShader(input: input, outputPath: file.path)) {
|
||||
input.copySync(file.path);
|
||||
}
|
||||
} else {
|
||||
await file.writeAsBytes(await entry.value.contentsAsBytes());
|
||||
}
|
||||
} finally {
|
||||
resource.release();
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/asset.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
@ -387,6 +388,63 @@ flutter:
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
|
||||
group('Shaders: ', () {
|
||||
MemoryFileSystem fileSystem;
|
||||
Artifacts artifacts;
|
||||
String impellerc;
|
||||
Directory output;
|
||||
String shaderPath;
|
||||
String outputPath;
|
||||
|
||||
setUp(() {
|
||||
artifacts = Artifacts.test();
|
||||
fileSystem = MemoryFileSystem.test();
|
||||
impellerc = artifacts.getHostArtifact(HostArtifact.impellerc).path;
|
||||
|
||||
fileSystem.file(impellerc).createSync(recursive: true);
|
||||
|
||||
output = fileSystem.directory('asset_output')..createSync(recursive: true);
|
||||
shaderPath = fileSystem.path.join('assets', 'shader.frag');
|
||||
outputPath = fileSystem.path.join(output.path, 'assets', 'shader.frag');
|
||||
fileSystem.file(shaderPath).createSync(recursive: true);
|
||||
});
|
||||
|
||||
testUsingContext('Including a shader triggers the shader compiler', () async {
|
||||
fileSystem.file('.packages').createSync();
|
||||
fileSystem.file('pubspec.yaml')
|
||||
..createSync()
|
||||
..writeAsStringSync(r'''
|
||||
name: example
|
||||
flutter:
|
||||
assets:
|
||||
- assets/shader.frag
|
||||
''');
|
||||
final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
|
||||
|
||||
expect(await bundle.build(manifestPath: 'pubspec.yaml', packagesPath: '.packages'), 0);
|
||||
|
||||
await writeBundle(output, bundle.entries, loggerOverride: testLogger);
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
Artifacts: () => artifacts,
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: <String>[
|
||||
impellerc,
|
||||
'--flutter-spirv',
|
||||
'--spirv=$outputPath',
|
||||
'--input=/$shaderPath',
|
||||
],
|
||||
onRun: () {
|
||||
fileSystem.file(outputPath).createSync(recursive: true);
|
||||
},
|
||||
),
|
||||
]),
|
||||
});
|
||||
});
|
||||
|
||||
testUsingContext('Does not insert dummy file into additionalDependencies '
|
||||
'when wildcards are used by dependencies', () async {
|
||||
globals.fs.file('.packages').writeAsStringSync(r'''
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/build_system/targets/shader_compiler.dart';
|
||||
|
||||
import '../../../src/common.dart';
|
||||
import '../../../src/fake_process_manager.dart';
|
||||
|
||||
const String shaderPath = '/shaders/my_shader.frag';
|
||||
const String notShaderPath = '/shaders/not_a_shader.file';
|
||||
const String outputPath = '/output/shaders/my_shader.spv';
|
||||
|
||||
void main() {
|
||||
late BufferLogger logger;
|
||||
late MemoryFileSystem fileSystem;
|
||||
late Artifacts artifacts;
|
||||
late String impellerc;
|
||||
|
||||
setUp(() {
|
||||
artifacts = Artifacts.test();
|
||||
fileSystem = MemoryFileSystem.test();
|
||||
logger = BufferLogger.test();
|
||||
impellerc = artifacts.getHostArtifact(HostArtifact.impellerc).path;
|
||||
|
||||
fileSystem.file(impellerc).createSync(recursive: true);
|
||||
fileSystem.file(shaderPath).createSync(recursive: true);
|
||||
fileSystem.file(notShaderPath).createSync(recursive: true);
|
||||
});
|
||||
|
||||
testWithoutContext('compileShader returns false for non-shader files', () async {
|
||||
final ShaderCompiler shaderCompiler = ShaderCompiler(
|
||||
processManager: FakeProcessManager.empty(),
|
||||
logger: logger,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
|
||||
expect(
|
||||
await shaderCompiler.compileShader(
|
||||
input: fileSystem.file(notShaderPath),
|
||||
outputPath: outputPath,
|
||||
),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('compileShader returns true for shader files', () async {
|
||||
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: <String>[
|
||||
impellerc,
|
||||
'--flutter-spirv',
|
||||
'--spirv=$outputPath',
|
||||
'--input=$shaderPath',
|
||||
],
|
||||
onRun: () {
|
||||
fileSystem.file(outputPath).createSync(recursive: true);
|
||||
},
|
||||
),
|
||||
]);
|
||||
final ShaderCompiler shaderCompiler = ShaderCompiler(
|
||||
processManager: processManager,
|
||||
logger: logger,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
|
||||
expect(
|
||||
await shaderCompiler.compileShader(
|
||||
input: fileSystem.file(shaderPath),
|
||||
outputPath: outputPath,
|
||||
),
|
||||
true,
|
||||
);
|
||||
expect(fileSystem.file(outputPath).existsSync(), true);
|
||||
});
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user