Skip to content
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

fix: Make build_shaders script compatible with other platforms [flame_3d] #3395

Merged
merged 3 commits into from
Dec 14, 2024
Merged
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
100 changes: 97 additions & 3 deletions packages/flame_3d/bin/build_shaders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ Future<void> compute(Directory assets, Directory shaders) async {
};

stdout.writeln('Computing shader "$name"');
final result = await Process.run(impellerC, [
final impellerC = await findImpellerC();
final result = await Process.run(impellerC.toFilePath(), [
'--sl=${assets.path}/$name.shaderbundle',
'--shader-bundle=${jsonEncode(bundle)}',
]);
Expand All @@ -68,5 +69,98 @@ Future<void> compute(Directory assets, Directory shaders) async {
}
}

final impellerC =
'${Platform.environment['FLUTTER_HOME']}/bin/cache/artifacts/engine/darwin-x64/impellerc';
// Copied from https://github.com/bdero/flutter_gpu_shaders/blob/master/lib/environment.dart#L53
const _macosHostArtifacts = 'darwin-x64';
const _linuxHostArtifacts = 'linux-x64';
const _windowsHostArtifacts = 'windows-x64';

const _impellercLocations = [
'$_macosHostArtifacts/impellerc',
'$_linuxHostArtifacts/impellerc',
'$_windowsHostArtifacts/impellerc.exe',
];

/// Locate the engine artifacts cache directory in the Flutter SDK.
Uri findEngineArtifactsDir({String? dartPath}) {
// Could be:
// `/path/to/flutter/bin/cache/dart-sdk/bin/dart`
// `/path/to/flutter/bin/cache/artifacts/engine/darwin-x64/flutter_tester`
// `/path/to/.user/shared/caches/94cf8c8fad31206e440611e309757a5a9b3be712/dart-sdk/bin/dart`
final dartExec = Uri.file(dartPath ?? Platform.resolvedExecutable);

Uri? cacheDir;
// Search backwards through the segment list until finding `bin` and `cache`
// in sequence.
for (var i = dartExec.pathSegments.length - 1; i >= 0; i--) {
if (dartExec.pathSegments[i] == 'dart-sdk' ||
dartExec.pathSegments[i] == 'artifacts') {
// Note: The final empty string denotes that this is a directory path.
cacheDir = dartExec.replace(
pathSegments: dartExec.pathSegments.sublist(0, i) + [''],
);
break;
}
}
if (cacheDir == null) {
throw Exception(
'Unable to find Flutter SDK cache directory! '
'Dart executable: `${dartExec.toFilePath()}`',
);
}
// We should now have a path of `/path/to/flutter/bin/cache/`.

final engineArtifactsDir = cacheDir
.resolve('./artifacts/engine/'); // Note: The final slash is important.

return engineArtifactsDir;
}

/// Locate the ImpellerC offline shader compiler in the engine artifacts cache
/// directory.
Future<Uri> findImpellerC() async {
/////////////////////////////////////////////////////////////////////////////
/// 1. If the `IMPELLERC` environment variable is set, use it.
///

// ignore: do_not_use_environment
const impellercEnvVar = String.fromEnvironment('IMPELLERC');
if (impellercEnvVar != '') {
if (!doesFileExist(impellercEnvVar)) {
throw Exception(
'IMPELLERC environment variable is set, '
"but it doesn't point to a valid file!",
);
}
return Uri.file(impellercEnvVar);
}

/////////////////////////////////////////////////////////////////////////////
/// 3. Search for the `impellerc` binary within the host-specific artifacts.
///

final engineArtifactsDir = findEngineArtifactsDir();

// No need to get fancy. Just search all the possible directories rather than
// picking the correct one for the specific host type.
Uri? found;
final tried = <Uri>[];
for (final variant in _impellercLocations) {
final impellercPath = engineArtifactsDir.resolve(variant);
if (doesFileExist(impellercPath.toFilePath())) {
found = impellercPath;
break;
}
tried.add(impellercPath);
}
if (found == null) {
throw Exception(
'Unable to find impellerc! Tried the following locations: $tried',
);
}

return found;
}

bool doesFileExist(String path) {
return File(path).existsSync();
}
Loading