mirror of
https://github.com/par274/sharpemu.git
synced 2026-08-11 20:18:45 +08:00
Astrobot - Canonicalize fix and ffmpeg library on build (#817)
This commit is contained in:
+19
-15
@@ -47,24 +47,28 @@ built against `ffmpeg-core` specifically.
|
|||||||
|
|
||||||
## Supplying the FFmpeg libraries
|
## Supplying the FFmpeg libraries
|
||||||
|
|
||||||
`dotnet publish` fetches a prebuilt release of `github.com/sharpemu/ffmpeg-core`
|
Both `dotnet build` and `dotnet publish` fetch a prebuilt release of
|
||||||
(the tag is pinned in `SharpEmu.CLI.csproj`'s `FfmpegRuntimeTag`, matched to
|
`github.com/sharpemu/ffmpeg-core` (the tag is pinned in
|
||||||
the `FFmpeg.AutoGen` package version in `Directory.Packages.props` -- both
|
`SharpEmu.CLI.csproj`'s `FfmpegRuntimeTag`, matched to the `FFmpeg.AutoGen`
|
||||||
need to agree on the same FFmpeg ABI) and copies its dynamically linked
|
package version in `Directory.Packages.props` -- both need to agree on the
|
||||||
libraries into a `plugins` folder next to the published executable. No C
|
same FFmpeg ABI) and copy its dynamically linked libraries into a `plugins`
|
||||||
toolchain is required to build SharpEmu; publishing just downloads a zip.
|
folder next to the resulting executable (`artifacts/bin/...` for build,
|
||||||
`plugins` is a loose, unpacked folder rather than something embedded in the
|
`artifacts/publish/...` for publish). No C toolchain is required to build
|
||||||
single-file bundle, so the OS loader can resolve the libraries' own
|
SharpEmu; both just download a zip once (cached under
|
||||||
inter-dependencies (`avcodec` depends on `avutil`, etc.) itself.
|
`$(BaseIntermediateOutputPath)ffmpeg-runtime/`, so later builds/publishes
|
||||||
|
reuse it instead of re-fetching). `plugins` is a loose, unpacked folder
|
||||||
|
rather than something embedded in the single-file bundle, so the OS loader
|
||||||
|
can resolve the libraries' own inter-dependencies (`avcodec` depends on
|
||||||
|
`avutil`, etc.) itself.
|
||||||
|
|
||||||
A plain `dotnet publish` with no `-r` still works: it defaults to the host
|
A plain `dotnet build`/`dotnet publish` with no `-r` still works: it defaults
|
||||||
machine's own RID (see `Directory.Build.props`), so it fetches the matching
|
to the host machine's own RID (see `Directory.Build.props`), so it fetches
|
||||||
`ffmpeg-core` archive and populates `plugins` without any extra flags.
|
the matching `ffmpeg-core` archive and populates `plugins` without any extra
|
||||||
Passing an explicit `-r <rid>` (e.g. to cross-publish `linux-x64` from
|
flags. Passing an explicit `-r <rid>` (e.g. to cross-publish `linux-x64` from
|
||||||
Windows) still overrides that default normally.
|
Windows) still overrides that default normally.
|
||||||
|
|
||||||
To use a different set of FFmpeg libraries, drop them into the published
|
To use a different set of FFmpeg libraries, drop them into the build or
|
||||||
`plugins` folder yourself (matching FFmpeg's own file-naming and versioning
|
published `plugins` folder yourself (matching FFmpeg's own file-naming and versioning
|
||||||
conventions, e.g. `avformat-61.dll` / `libavformat.so.61` / matching
|
conventions, e.g. `avformat-61.dll` / `libavformat.so.61` / matching
|
||||||
`.dylib`) -- `FfmpegNativeBinkFrameSource` points `ffmpeg.RootPath` at that
|
`.dylib`) -- `FfmpegNativeBinkFrameSource` points `ffmpeg.RootPath` at that
|
||||||
folder and does not otherwise care where the files came from.
|
folder and does not otherwise care where the files came from.
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Target Name="FetchFfmpegRuntime"
|
<Target Name="FetchFfmpegRuntime"
|
||||||
BeforeTargets="Publish"
|
BeforeTargets="Publish;Build"
|
||||||
Condition="'$(RuntimeIdentifier)' != '' And '$(FfmpegRuntimePackage)' != ''">
|
Condition="'$(RuntimeIdentifier)' != '' And '$(FfmpegRuntimePackage)' != ''">
|
||||||
<DownloadFile
|
<DownloadFile
|
||||||
SourceUrl="https://github.com/sharpemu/ffmpeg-core/releases/download/$(FfmpegRuntimeTag)/$(FfmpegRuntimePackage)"
|
SourceUrl="https://github.com/sharpemu/ffmpeg-core/releases/download/$(FfmpegRuntimeTag)/$(FfmpegRuntimePackage)"
|
||||||
@@ -161,4 +161,23 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
SkipUnchangedFiles="true" />
|
SkipUnchangedFiles="true" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
<!-- Mirrors PublishFfmpegRuntime for plain `dotnet build`: devs running
|
||||||
|
straight out of the build output directory (no publish step) still
|
||||||
|
need the FFmpeg plugins present, otherwise AvPlayer/Bink video probing
|
||||||
|
throws NotSupportedException the first time a guest opens a movie. -->
|
||||||
|
<Target Name="BuildFfmpegRuntime"
|
||||||
|
AfterTargets="Build"
|
||||||
|
DependsOnTargets="FetchFfmpegRuntime"
|
||||||
|
Condition="'$(RuntimeIdentifier)' != '' And '$(FfmpegRuntimePackage)' != ''">
|
||||||
|
<ItemGroup>
|
||||||
|
<_FfmpegRuntimeFiles Condition="$(RuntimeIdentifier.StartsWith('win'))"
|
||||||
|
Include="$(FfmpegRuntimeExtractDir)/bin/*.dll" />
|
||||||
|
<_FfmpegRuntimeFiles Condition="!$(RuntimeIdentifier.StartsWith('win'))"
|
||||||
|
Include="$(FfmpegRuntimeExtractDir)/lib/*.so;$(FfmpegRuntimeExtractDir)/lib/*.so.*;$(FfmpegRuntimeExtractDir)/lib/*.dylib" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Copy SourceFiles="@(_FfmpegRuntimeFiles)"
|
||||||
|
DestinationFolder="$(OutDir)$(NativeLibraryFolderName)"
|
||||||
|
SkipUnchangedFiles="true" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -60,9 +60,7 @@ internal static class GpuWaitRegistry
|
|||||||
// address) so distinct guest processes never alias.
|
// address) so distinct guest processes never alias.
|
||||||
private static readonly Dictionary<(object, ulong), ulong> _lastProduced = new();
|
private static readonly Dictionary<(object, ulong), ulong> _lastProduced = new();
|
||||||
|
|
||||||
// Unwraps to the shared root: per-thread TrackedCpuMemory decorators
|
|
||||||
// over ONE virtual memory are not reference-equal, so a raw-reference
|
|
||||||
// filter would make waits invisible across threads.
|
|
||||||
private static object? Canonicalize(object? memory)
|
private static object? Canonicalize(object? memory)
|
||||||
{
|
{
|
||||||
while (memory is SharpEmu.HLE.ICpuMemoryWrapper wrapper)
|
while (memory is SharpEmu.HLE.ICpuMemoryWrapper wrapper)
|
||||||
@@ -120,6 +118,7 @@ internal static class GpuWaitRegistry
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static OutstandingSnapshot SnapshotOutstanding(object? memory = null)
|
public static OutstandingSnapshot SnapshotOutstanding(object? memory = null)
|
||||||
{
|
{
|
||||||
|
memory = Canonicalize(memory);
|
||||||
lock (_gate)
|
lock (_gate)
|
||||||
{
|
{
|
||||||
var outstanding = 0;
|
var outstanding = 0;
|
||||||
@@ -346,6 +345,7 @@ internal static class GpuWaitRegistry
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool LatchSatisfiedByValue(object memory, ulong address, ulong value)
|
public static bool LatchSatisfiedByValue(object memory, ulong address, ulong value)
|
||||||
{
|
{
|
||||||
|
memory = Canonicalize(memory)!;
|
||||||
var latchedAny = false;
|
var latchedAny = false;
|
||||||
lock (_gate)
|
lock (_gate)
|
||||||
{
|
{
|
||||||
@@ -431,6 +431,7 @@ internal static class GpuWaitRegistry
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static List<WaitingDcb>? CollectExpiredRetries(object memory, long nowTicks)
|
public static List<WaitingDcb>? CollectExpiredRetries(object memory, long nowTicks)
|
||||||
{
|
{
|
||||||
|
memory = Canonicalize(memory)!;
|
||||||
List<WaitingDcb>? expired = null;
|
List<WaitingDcb>? expired = null;
|
||||||
lock (_gate)
|
lock (_gate)
|
||||||
{
|
{
|
||||||
@@ -473,6 +474,7 @@ internal static class GpuWaitRegistry
|
|||||||
|
|
||||||
public static List<WaitingDcb>? CollectAllForMemory(object memory)
|
public static List<WaitingDcb>? CollectAllForMemory(object memory)
|
||||||
{
|
{
|
||||||
|
memory = Canonicalize(memory)!;
|
||||||
List<WaitingDcb>? collected = null;
|
List<WaitingDcb>? collected = null;
|
||||||
lock (_gate)
|
lock (_gate)
|
||||||
{
|
{
|
||||||
@@ -558,6 +560,7 @@ internal static class GpuWaitRegistry
|
|||||||
/// breaker. Also latches any already-waiting waiter it satisfies.</summary>
|
/// breaker. Also latches any already-waiting waiter it satisfies.</summary>
|
||||||
public static bool RecordProduced(object memory, ulong address, ulong value)
|
public static bool RecordProduced(object memory, ulong address, ulong value)
|
||||||
{
|
{
|
||||||
|
memory = Canonicalize(memory)!;
|
||||||
lock (_gate)
|
lock (_gate)
|
||||||
{
|
{
|
||||||
if (_lastProduced.Count >= 8192)
|
if (_lastProduced.Count >= 8192)
|
||||||
@@ -591,6 +594,7 @@ internal static class GpuWaitRegistry
|
|||||||
long nowTicks,
|
long nowTicks,
|
||||||
long minAgeTicks)
|
long minAgeTicks)
|
||||||
{
|
{
|
||||||
|
memory = Canonicalize(memory)!;
|
||||||
List<WaitingDcb>? broken = null;
|
List<WaitingDcb>? broken = null;
|
||||||
lock (_gate)
|
lock (_gate)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user