blob: e7c6e45bd752db48f56dcee0130ecd0e0f0a73e4 [file] [log] [blame]
// 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/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 shader compiler subprocess fails, it will print the stdout and
/// stderr to the log and throw a [ShaderCompilerException]. Otherwise, it
/// will return true.
Future<bool> compileShader({
required File input,
required String outputPath,
}) async {
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}',
'--input-type=frag',
];
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';
}