Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
b34de74f81 | |||
5811d121df | |||
6eb85e846f | |||
c5bddfeab8 | |||
70ec5def9c | |||
7853faa334 | |||
b7fb474bfe | |||
2fa6413ed8 | |||
4523a73f75 |
@ -54,5 +54,6 @@
|
||||
<Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color>
|
||||
<Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="ThemeForegroundColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
||||
</Styles.Resources>
|
||||
</Styles>
|
@ -49,5 +49,6 @@
|
||||
<Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color>
|
||||
<Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="ThemeForegroundColor">#FF000000</Color>
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||
</Styles.Resources>
|
||||
</Styles>
|
@ -221,6 +221,7 @@
|
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundColor}" />
|
||||
</Style>
|
||||
<Styles.Resources>
|
||||
<SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundSelected" ResourceKey="ThemeAccentColorBrush" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundPressed" ResourceKey="SystemAccentColorDark1" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundPointerOver" ResourceKey="SystemAccentColorDark2" />
|
||||
@ -232,7 +233,7 @@
|
||||
Color="{DynamicResource SystemBaseMediumLowColor}" />
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" Color="{DynamicResource DataGridSelectionColor}" />
|
||||
<SolidColorBrush x:Key="MenuFlyoutPresenterBorderBrush" Color="{DynamicResource MenuFlyoutPresenterBorderColor}" />
|
||||
<SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="FlyoutBorderThemeBrush" Color="{DynamicResource MenuFlyoutPresenterBorderColor}" />
|
||||
<SolidColorBrush x:Key="ListBoxBackground" Color="{DynamicResource ThemeContentBackgroundColor}" />
|
||||
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{DynamicResource ThemeForegroundColor}" />
|
||||
<SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}" />
|
||||
|
@ -28,7 +28,7 @@
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1" />
|
||||
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.4.0-build9" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="OpenTK.Graphics" Version="4.7.2" />
|
||||
<PackageReference Include="SPB" Version="0.0.4-build17" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.3.3" />
|
||||
|
@ -535,6 +535,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowConsoleVisible
|
||||
{
|
||||
get => ConsoleHelper.SetConsoleWindowStateSupported;
|
||||
}
|
||||
|
||||
public ObservableCollection<ApplicationData> Applications
|
||||
{
|
||||
get => _applications;
|
||||
|
@ -128,7 +128,7 @@
|
||||
<CheckBox IsChecked="{Binding StartGamesInFullscreen, Mode=TwoWay}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="{locale:Locale MenuBarOptionsShowConsole}">
|
||||
<MenuItem Header="{locale:Locale MenuBarOptionsShowConsole}" IsVisible="{Binding ShowConsoleVisible}">
|
||||
<MenuItem.Icon>
|
||||
<CheckBox IsChecked="{Binding ShowConsole, Mode=TwoWay}" />
|
||||
</MenuItem.Icon>
|
||||
|
@ -208,7 +208,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
|
||||
Span<byte> dstSpan = memoryManager.GetSpan(dstGpuVa + (ulong)dstBaseOffset, dstSize).ToArray();
|
||||
|
||||
bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
|
||||
bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
|
||||
@ -262,43 +261,63 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
target.SynchronizeMemory();
|
||||
target.SetData(data);
|
||||
target.SignalModified();
|
||||
|
||||
return;
|
||||
}
|
||||
else if (srcCalculator.LayoutMatches(dstCalculator))
|
||||
{
|
||||
srcSpan.CopyTo(dstSpan); // No layout conversion has to be performed, just copy the data entirely.
|
||||
|
||||
memoryManager.Write(dstGpuVa + (ulong)dstBaseOffset, dstSpan);
|
||||
|
||||
// No layout conversion has to be performed, just copy the data entirely.
|
||||
memoryManager.Write(dstGpuVa + (ulong)dstBaseOffset, srcSpan);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe bool Convert<T>(Span<byte> dstSpan, ReadOnlySpan<byte> srcSpan) where T : unmanaged
|
||||
{
|
||||
fixed (byte* dstPtr = dstSpan, srcPtr = srcSpan)
|
||||
if (srcLinear && dstLinear && srcBpp == dstBpp)
|
||||
{
|
||||
byte* dstBase = dstPtr - dstBaseOffset; // Layout offset is relative to the base, so we need to subtract the span's offset.
|
||||
byte* srcBase = srcPtr - srcBaseOffset;
|
||||
|
||||
// Optimized path for purely linear copies - we don't need to calculate every single byte offset,
|
||||
// and we can make use of Span.CopyTo which is very very fast (even compared to pointers)
|
||||
for (int y = 0; y < yCount; y++)
|
||||
{
|
||||
srcCalculator.SetY(srcRegionY + y);
|
||||
dstCalculator.SetY(dstRegionY + y);
|
||||
int srcOffset = srcCalculator.GetOffset(srcRegionX);
|
||||
int dstOffset = dstCalculator.GetOffset(dstRegionX);
|
||||
srcSpan.Slice(srcOffset - srcBaseOffset, xCount * srcBpp)
|
||||
.CopyTo(dstSpan.Slice(dstOffset - dstBaseOffset, xCount * dstBpp));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed (byte* dstPtr = dstSpan, srcPtr = srcSpan)
|
||||
{
|
||||
byte* dstBase = dstPtr - dstBaseOffset; // Layout offset is relative to the base, so we need to subtract the span's offset.
|
||||
byte* srcBase = srcPtr - srcBaseOffset;
|
||||
|
||||
for (int x = 0; x < xCount; x++)
|
||||
for (int y = 0; y < yCount; y++)
|
||||
{
|
||||
int srcOffset = srcCalculator.GetOffset(srcRegionX + x);
|
||||
int dstOffset = dstCalculator.GetOffset(dstRegionX + x);
|
||||
srcCalculator.SetY(srcRegionY + y);
|
||||
dstCalculator.SetY(dstRegionY + y);
|
||||
|
||||
*(T*)(dstBase + dstOffset) = *(T*)(srcBase + srcOffset);
|
||||
for (int x = 0; x < xCount; x++)
|
||||
{
|
||||
int srcOffset = srcCalculator.GetOffset(srcRegionX + x);
|
||||
int dstOffset = dstCalculator.GetOffset(dstRegionX + x);
|
||||
|
||||
*(T*)(dstBase + dstOffset) = *(T*)(srcBase + srcOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// OPT: This allocates a (potentially) huge temporary array and then copies an existing
|
||||
// region of memory into it, data that might get overwritten entirely anyways. Ideally this should
|
||||
// all be rewritten to use pooled arrays, but that gets complicated with packed data and strides
|
||||
Span<byte> dstSpan = memoryManager.GetSpan(dstGpuVa + (ulong)dstBaseOffset, dstSize).ToArray();
|
||||
|
||||
bool _ = srcBpp switch
|
||||
{
|
||||
1 => Convert<byte>(dstSpan, srcSpan),
|
||||
|
@ -174,6 +174,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
if (info.Width == info.Height * info.Height)
|
||||
{
|
||||
// Possibly used for a "3D texture" drawn onto a 2D surface.
|
||||
// Some games do this to generate a tone mapping LUT without rendering into 3D texture slices.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
private const ushort FileFormatVersionMajor = 1;
|
||||
private const ushort FileFormatVersionMinor = 1;
|
||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||
private const uint CodeGenVersion = 3069;
|
||||
private const uint CodeGenVersion = 3478;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
private const string SharedDataFileName = "shared.data";
|
||||
|
@ -1,23 +1,21 @@
|
||||
using FFmpeg.AutoGen;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
{
|
||||
unsafe class FFmpegContext : IDisposable
|
||||
{
|
||||
private readonly AVCodec_decode _decodeFrame;
|
||||
private static readonly av_log_set_callback_callback _logFunc;
|
||||
private readonly FFCodec.AVCodec_decode _decodeFrame;
|
||||
private static readonly FFmpegApi.av_log_set_callback_callback _logFunc;
|
||||
private readonly AVCodec* _codec;
|
||||
private AVPacket* _packet;
|
||||
private AVCodecContext* _context;
|
||||
|
||||
public FFmpegContext(AVCodecID codecId)
|
||||
{
|
||||
_codec = ffmpeg.avcodec_find_decoder(codecId);
|
||||
_codec = FFmpegApi.avcodec_find_decoder(codecId);
|
||||
if (_codec == null)
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, $"Codec wasn't found. Make sure you have the {codecId} codec present in your FFmpeg installation.");
|
||||
@ -25,7 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
return;
|
||||
}
|
||||
|
||||
_context = ffmpeg.avcodec_alloc_context3(_codec);
|
||||
_context = FFmpegApi.avcodec_alloc_context3(_codec);
|
||||
if (_context == null)
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Codec context couldn't be allocated.");
|
||||
@ -33,14 +31,14 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
return;
|
||||
}
|
||||
|
||||
if (ffmpeg.avcodec_open2(_context, _codec, null) != 0)
|
||||
if (FFmpegApi.avcodec_open2(_context, _codec, null) != 0)
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Codec couldn't be opened.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_packet = ffmpeg.av_packet_alloc();
|
||||
_packet = FFmpegApi.av_packet_alloc();
|
||||
if (_packet == null)
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Packet couldn't be allocated.");
|
||||
@ -48,52 +46,39 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
return;
|
||||
}
|
||||
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(_codec->decode.Pointer);
|
||||
int avCodecRawVersion = FFmpegApi.avcodec_version();
|
||||
int avCodecMajorVersion = avCodecRawVersion >> 16;
|
||||
int avCodecMinorVersion = (avCodecRawVersion >> 8) & 0xFF;
|
||||
|
||||
// libavcodec 59.24 changed AvCodec to move its private API and also move the codec function to an union.
|
||||
if (avCodecMajorVersion > 59 || (avCodecMajorVersion == 59 && avCodecMinorVersion > 24))
|
||||
{
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodec*)_codec)->CodecCallback);
|
||||
}
|
||||
// libavcodec 59.x changed AvCodec private API layout.
|
||||
else if (avCodecMajorVersion == 59)
|
||||
{
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodecLegacy<AVCodec>*)_codec)->Decode);
|
||||
}
|
||||
// libavcodec 58.x and lower
|
||||
else
|
||||
{
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodecLegacy<AVCodecLegacy>*)_codec)->Decode);
|
||||
}
|
||||
}
|
||||
|
||||
static FFmpegContext()
|
||||
{
|
||||
SetRootPath();
|
||||
|
||||
_logFunc = Log;
|
||||
|
||||
// Redirect log output.
|
||||
ffmpeg.av_log_set_level(ffmpeg.AV_LOG_MAX_OFFSET);
|
||||
ffmpeg.av_log_set_callback(_logFunc);
|
||||
FFmpegApi.av_log_set_level(AVLog.MaxOffset);
|
||||
FFmpegApi.av_log_set_callback(_logFunc);
|
||||
}
|
||||
|
||||
private static void SetRootPath()
|
||||
private static void Log(void* ptr, AVLog level, string format, byte* vl)
|
||||
{
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
// Configure FFmpeg search path
|
||||
Process lddProcess = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "/bin/sh",
|
||||
Arguments = "-c \"ldd $(which ffmpeg 2>/dev/null) | grep libavfilter\" 2>/dev/null",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true
|
||||
});
|
||||
|
||||
string lddOutput = lddProcess.StandardOutput.ReadToEnd();
|
||||
|
||||
lddProcess.WaitForExit();
|
||||
lddProcess.Close();
|
||||
|
||||
if (lddOutput.Contains(" => "))
|
||||
{
|
||||
ffmpeg.RootPath = Path.GetDirectoryName(lddOutput.Split(" => ")[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "FFmpeg wasn't found. Make sure that you have it installed and up to date.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Log(void* p0, int level, string format, byte* vl)
|
||||
{
|
||||
if (level > ffmpeg.av_log_get_level())
|
||||
if (level > FFmpegApi.av_log_get_level())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -102,65 +87,67 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
byte* lineBuffer = stackalloc byte[lineSize];
|
||||
int printPrefix = 1;
|
||||
|
||||
ffmpeg.av_log_format_line(p0, level, format, vl, lineBuffer, lineSize, &printPrefix);
|
||||
FFmpegApi.av_log_format_line(ptr, level, format, vl, lineBuffer, lineSize, &printPrefix);
|
||||
|
||||
string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer).Trim();
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case ffmpeg.AV_LOG_PANIC:
|
||||
case ffmpeg.AV_LOG_FATAL:
|
||||
case ffmpeg.AV_LOG_ERROR:
|
||||
case AVLog.Panic:
|
||||
case AVLog.Fatal:
|
||||
case AVLog.Error:
|
||||
Logger.Error?.Print(LogClass.FFmpeg, line);
|
||||
break;
|
||||
case ffmpeg.AV_LOG_WARNING:
|
||||
case AVLog.Warning:
|
||||
Logger.Warning?.Print(LogClass.FFmpeg, line);
|
||||
break;
|
||||
case ffmpeg.AV_LOG_INFO:
|
||||
case AVLog.Info:
|
||||
Logger.Info?.Print(LogClass.FFmpeg, line);
|
||||
break;
|
||||
case ffmpeg.AV_LOG_VERBOSE:
|
||||
case ffmpeg.AV_LOG_DEBUG:
|
||||
case ffmpeg.AV_LOG_TRACE:
|
||||
case AVLog.Verbose:
|
||||
case AVLog.Debug:
|
||||
Logger.Debug?.Print(LogClass.FFmpeg, line);
|
||||
break;
|
||||
case AVLog.Trace:
|
||||
Logger.Trace?.Print(LogClass.FFmpeg, line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public int DecodeFrame(Surface output, ReadOnlySpan<byte> bitstream)
|
||||
{
|
||||
ffmpeg.av_frame_unref(output.Frame);
|
||||
FFmpegApi.av_frame_unref(output.Frame);
|
||||
|
||||
int result;
|
||||
int gotFrame;
|
||||
|
||||
fixed (byte* ptr = bitstream)
|
||||
{
|
||||
_packet->data = ptr;
|
||||
_packet->size = bitstream.Length;
|
||||
_packet->Data = ptr;
|
||||
_packet->Size = bitstream.Length;
|
||||
result = _decodeFrame(_context, output.Frame, &gotFrame, _packet);
|
||||
}
|
||||
|
||||
if (gotFrame == 0)
|
||||
{
|
||||
ffmpeg.av_frame_unref(output.Frame);
|
||||
FFmpegApi.av_frame_unref(output.Frame);
|
||||
|
||||
// If the frame was not delivered, it was probably delayed.
|
||||
// Get the next delayed frame by passing a 0 length packet.
|
||||
_packet->data = null;
|
||||
_packet->size = 0;
|
||||
_packet->Data = null;
|
||||
_packet->Size = 0;
|
||||
result = _decodeFrame(_context, output.Frame, &gotFrame, _packet);
|
||||
|
||||
// We need to set B frames to 0 as we already consumed all delayed frames.
|
||||
// This prevents the decoder from trying to return a delayed frame next time.
|
||||
_context->has_b_frames = 0;
|
||||
_context->HasBFrames = 0;
|
||||
}
|
||||
|
||||
ffmpeg.av_packet_unref(_packet);
|
||||
FFmpegApi.av_packet_unref(_packet);
|
||||
|
||||
if (gotFrame == 0)
|
||||
{
|
||||
ffmpeg.av_frame_unref(output.Frame);
|
||||
FFmpegApi.av_frame_unref(output.Frame);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -172,14 +159,14 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
{
|
||||
fixed (AVPacket** ppPacket = &_packet)
|
||||
{
|
||||
ffmpeg.av_packet_free(ppPacket);
|
||||
FFmpegApi.av_packet_free(ppPacket);
|
||||
}
|
||||
|
||||
ffmpeg.avcodec_close(_context);
|
||||
FFmpegApi.avcodec_close(_context);
|
||||
|
||||
fixed (AVCodecContext** ppContext = &_context)
|
||||
{
|
||||
ffmpeg.avcodec_free_context(ppContext);
|
||||
FFmpegApi.avcodec_free_context(ppContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FFmpeg.AutoGen;
|
||||
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
|
||||
|
25
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodec.cs
Normal file
25
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodec.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct AVCodec
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public unsafe byte* Name;
|
||||
public unsafe byte* LongName;
|
||||
public int Type;
|
||||
public AVCodecID Id;
|
||||
public int Capabilities;
|
||||
public byte MaxLowRes;
|
||||
public unsafe AVRational* SupportedFramerates;
|
||||
public IntPtr PixFmts;
|
||||
public IntPtr SupportedSamplerates;
|
||||
public IntPtr SampleFmts;
|
||||
// Deprecated
|
||||
public unsafe ulong* ChannelLayouts;
|
||||
public unsafe IntPtr PrivClass;
|
||||
public IntPtr Profiles;
|
||||
public unsafe byte* WrapperName;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
171
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecContext.cs
Normal file
171
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecContext.cs
Normal file
@ -0,0 +1,171 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct AVCodecContext
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public unsafe IntPtr AvClass;
|
||||
public int LogLevelOffset;
|
||||
public int CodecType;
|
||||
public unsafe AVCodecLegacy* Codec;
|
||||
public AVCodecID CodecId;
|
||||
public uint CodecTag;
|
||||
public IntPtr PrivData;
|
||||
public IntPtr Internal;
|
||||
public IntPtr Opaque;
|
||||
public long BitRate;
|
||||
public int BitRateTolerance;
|
||||
public int GlobalQuality;
|
||||
public int CompressionLevel;
|
||||
public int Flags;
|
||||
public int Flags2;
|
||||
public IntPtr ExtraData;
|
||||
public int ExtraDataSize;
|
||||
public AVRational TimeBase;
|
||||
public int TicksPerFrame;
|
||||
public int Delay;
|
||||
public int Width;
|
||||
public int Height;
|
||||
public int CodedWidth;
|
||||
public int CodedHeight;
|
||||
public int GopSize;
|
||||
public int PixFmt;
|
||||
public IntPtr DrawHorizBand;
|
||||
public IntPtr GetFormat;
|
||||
public int MaxBFrames;
|
||||
public float BQuantFactor;
|
||||
public float BQuantOffset;
|
||||
public int HasBFrames;
|
||||
public float IQuantFactor;
|
||||
public float IQuantOffset;
|
||||
public float LumiMasking;
|
||||
public float TemporalCplxMasking;
|
||||
public float SpatialCplxMasking;
|
||||
public float PMasking;
|
||||
public float DarkMasking;
|
||||
public int SliceCount;
|
||||
public IntPtr SliceOffset;
|
||||
public AVRational SampleAspectRatio;
|
||||
public int MeCmp;
|
||||
public int MeSubCmp;
|
||||
public int MbCmp;
|
||||
public int IldctCmp;
|
||||
public int DiaSize;
|
||||
public int LastPredictorCount;
|
||||
public int MePreCmp;
|
||||
public int PreDiaSize;
|
||||
public int MeSubpelQuality;
|
||||
public int MeRange;
|
||||
public int SliceFlags;
|
||||
public int MbDecision;
|
||||
public IntPtr IntraMatrix;
|
||||
public IntPtr InterMatrix;
|
||||
public int IntraDcPrecision;
|
||||
public int SkipTop;
|
||||
public int SkipBottom;
|
||||
public int MbLmin;
|
||||
public int MbLmax;
|
||||
public int BidirRefine;
|
||||
public int KeyintMin;
|
||||
public int Refs;
|
||||
public int Mv0Threshold;
|
||||
public int ColorPrimaries;
|
||||
public int ColorPrc;
|
||||
public int Colorspace;
|
||||
public int ColorRange;
|
||||
public int ChromaSampleLocation;
|
||||
public int Slices;
|
||||
public int FieldOrder;
|
||||
public int SampleRate;
|
||||
public int Channels;
|
||||
public int SampleFmt;
|
||||
public int FrameSize;
|
||||
public int FrameNumber;
|
||||
public int BlockAlign;
|
||||
public int CutOff;
|
||||
public ulong ChannelLayout;
|
||||
public ulong RequestChannelLayout;
|
||||
public int AudioServiceType;
|
||||
public int RequestSampleFmt;
|
||||
public IntPtr GetBuffer2;
|
||||
public float QCompress;
|
||||
public float QBlur;
|
||||
public int QMin;
|
||||
public int QMax;
|
||||
public int MaxQdiff;
|
||||
public int RcBufferSize;
|
||||
public int RcOverrideCount;
|
||||
public IntPtr RcOverride;
|
||||
public long RcMaxRate;
|
||||
public long RcMinRate;
|
||||
public float RcMax_available_vbv_use;
|
||||
public float RcMin_vbv_overflow_use;
|
||||
public int RcInitialBufferOccupancy;
|
||||
public int Trellis;
|
||||
public IntPtr StatsOut;
|
||||
public IntPtr StatsIn;
|
||||
public int WorkaroundBugs;
|
||||
public int StrictStdCompliance;
|
||||
public int ErrorConcealment;
|
||||
public int Debug;
|
||||
public int ErrRecognition;
|
||||
public long ReorderedOpaque;
|
||||
public IntPtr HwAccel;
|
||||
public IntPtr HwAccelContext;
|
||||
public Array8<ulong> Error;
|
||||
public int DctAlgo;
|
||||
public int IdctAlgo;
|
||||
public int BitsPerCodedSample;
|
||||
public int BitsPerRawSample;
|
||||
public int LowRes;
|
||||
public int ThreadCount;
|
||||
public int ThreadType;
|
||||
public int ActiveThreadType;
|
||||
public int ThreadSafeCallbacks;
|
||||
public IntPtr Execute;
|
||||
public IntPtr Execute2;
|
||||
public int NsseWeight;
|
||||
public int Profile;
|
||||
public int Level;
|
||||
public int SkipLoopFilter;
|
||||
public int SkipIdct;
|
||||
public int SkipFrame;
|
||||
public IntPtr SubtitleHeader;
|
||||
public int SubtitleHeaderSize;
|
||||
public int InitialPadding;
|
||||
public AVRational Framerate;
|
||||
public int SwPixFmt;
|
||||
public AVRational PktTimebase;
|
||||
public IntPtr CodecDescriptor;
|
||||
public long PtsCorrectionNumFaultyPts;
|
||||
public long PtsCorrectionNumFaultyDts;
|
||||
public long PtsCorrectionLastPts;
|
||||
public long PtsCorrectionLastDts;
|
||||
public IntPtr SubCharenc;
|
||||
public int SubCharencMode;
|
||||
public int SkipAlpha;
|
||||
public int SeekPreroll;
|
||||
public int DebugMv;
|
||||
public IntPtr ChromaIntraMatrix;
|
||||
public IntPtr DumpSeparator;
|
||||
public IntPtr CodecWhitelist;
|
||||
public uint Properties;
|
||||
public IntPtr CodedSideData;
|
||||
public int NbCodedSideData;
|
||||
public IntPtr HwFramesCtx;
|
||||
public int SubTextFormat;
|
||||
public int TrailingPadding;
|
||||
public long MaxPixels;
|
||||
public IntPtr HwDeviceCtx;
|
||||
public int HwAccelFlags;
|
||||
public int applyCropping;
|
||||
public int ExtraHwFrames;
|
||||
public int DiscardDamagedPercentage;
|
||||
public long MaxSamples;
|
||||
public int ExportSideData;
|
||||
public IntPtr GetEncodeBuffer;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecID.cs
Normal file
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecID.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
enum AVCodecID
|
||||
{
|
||||
AV_CODEC_ID_H264 = 27,
|
||||
AV_CODEC_ID_VP8 = 139,
|
||||
}
|
||||
}
|
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecLegacy.cs
Normal file
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecLegacy.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct AVCodecLegacy
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public unsafe byte* Name;
|
||||
public unsafe byte* LongName;
|
||||
public int Type;
|
||||
public AVCodecID Id;
|
||||
public int Capabilities;
|
||||
public byte MaxLowRes;
|
||||
public unsafe AVRational* SupportedFramerates;
|
||||
public IntPtr PixFmts;
|
||||
public IntPtr SupportedSamplerates;
|
||||
public IntPtr SampleFmts;
|
||||
// Deprecated
|
||||
public unsafe ulong* ChannelLayouts;
|
||||
public unsafe IntPtr PrivClass;
|
||||
public IntPtr Profiles;
|
||||
public unsafe byte* WrapperName;
|
||||
public IntPtr ChLayouts;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
37
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVFrame.cs
Normal file
37
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVFrame.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct AVFrame
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public Array8<IntPtr> Data;
|
||||
public Array8<int> LineSize;
|
||||
public IntPtr ExtendedData;
|
||||
public int Width;
|
||||
public int Height;
|
||||
public int NumSamples;
|
||||
public int Format;
|
||||
public int KeyFrame;
|
||||
public int PictureType;
|
||||
public AVRational SampleAspectRatio;
|
||||
public long Pts;
|
||||
public long PktDts;
|
||||
public AVRational TimeBase;
|
||||
public int CodedPictureNumber;
|
||||
public int DisplayPictureNumber;
|
||||
public int Quality;
|
||||
public IntPtr Opaque;
|
||||
public int RepeatPicture;
|
||||
public int InterlacedFrame;
|
||||
public int TopFieldFirst;
|
||||
public int PaletteHasChanged;
|
||||
public long ReorderedOpaque;
|
||||
public int SampleRate;
|
||||
public ulong ChannelLayout;
|
||||
#pragma warning restore CS0649
|
||||
|
||||
// NOTE: There is more after, but the layout kind of changed a bit and we don't need more than this. This is safe as we only manipulate this behind a reference.
|
||||
}
|
||||
}
|
15
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVLog.cs
Normal file
15
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVLog.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
enum AVLog
|
||||
{
|
||||
Panic = 0,
|
||||
Fatal = 8,
|
||||
Error = 16,
|
||||
Warning = 24,
|
||||
Info = 32,
|
||||
Verbose = 40,
|
||||
Debug = 48,
|
||||
Trace = 56,
|
||||
MaxOffset = 64
|
||||
}
|
||||
}
|
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVPacket.cs
Normal file
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVPacket.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
using AVBufferRef = System.IntPtr;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct AVPacket
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public unsafe AVBufferRef *Buf;
|
||||
public long Pts;
|
||||
public long Dts;
|
||||
public unsafe byte* Data;
|
||||
public int Size;
|
||||
public int StreamIndex;
|
||||
public int Flags;
|
||||
public IntPtr SizeData;
|
||||
public int SizeDataElems;
|
||||
public long Duration;
|
||||
public long Position;
|
||||
public IntPtr Opaque;
|
||||
public unsafe AVBufferRef *OpaqueRef;
|
||||
public AVRational TimeBase;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVRational.cs
Normal file
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVRational.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
public struct AVRational
|
||||
{
|
||||
public int Numerator;
|
||||
public int Denominator;
|
||||
}
|
||||
}
|
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodec.cs
Normal file
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodec.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct FFCodec
|
||||
{
|
||||
public unsafe delegate int AVCodec_decode(AVCodecContext* avctx, void* outdata, int* got_frame_ptr, AVPacket* avpkt);
|
||||
|
||||
#pragma warning disable CS0649
|
||||
public AVCodec Base;
|
||||
public int CapsInternalOrCbType;
|
||||
public int PrivDataSize;
|
||||
public IntPtr UpdateThreadContext;
|
||||
public IntPtr UpdateThreadContextForUser;
|
||||
public IntPtr Defaults;
|
||||
public IntPtr InitStaticData;
|
||||
public IntPtr Init;
|
||||
public IntPtr CodecCallback;
|
||||
#pragma warning restore CS0649
|
||||
|
||||
// NOTE: There is more after, but the layout kind of changed a bit and we don't need more than this. This is safe as we only manipulate this behind a reference.
|
||||
}
|
||||
}
|
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodecLegacy.cs
Normal file
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodecLegacy.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct FFCodecLegacy<T> where T: struct
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public T Base;
|
||||
public uint CapsInternalOrCbType;
|
||||
public int PrivDataSize;
|
||||
public IntPtr UpdateThreadContext;
|
||||
public IntPtr UpdateThreadContextForUser;
|
||||
public IntPtr Defaults;
|
||||
public IntPtr InitStaticData;
|
||||
public IntPtr Init;
|
||||
public IntPtr EncodeSub;
|
||||
public IntPtr Encode2;
|
||||
public IntPtr Decode;
|
||||
#pragma warning restore CS0649
|
||||
|
||||
// NOTE: There is more after, but the layout kind of changed a bit and we don't need more than this. This is safe as we only manipulate this behind a reference.
|
||||
}
|
||||
}
|
129
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs
Normal file
129
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
static class FFmpegApi
|
||||
{
|
||||
public const string AvCodecLibraryName = "avcodec";
|
||||
public const string AvUtilLibraryName = "avutil";
|
||||
|
||||
private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new Dictionary<string, (int, int)>
|
||||
{
|
||||
{ AvCodecLibraryName, (58, 59) },
|
||||
{ AvUtilLibraryName, (56, 57) }
|
||||
};
|
||||
|
||||
private static string FormatLibraryNameForCurrentOs(string libraryName, int version)
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
return $"{libraryName}-{version}.dll";
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
return $"lib{libraryName}.so.{version}";
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
return $"lib{libraryName}.{version}.dylib";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException($"Unsupported OS for FFmpeg: {RuntimeInformation.RuntimeIdentifier}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static bool TryLoadWhitelistedLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
|
||||
{
|
||||
handle = IntPtr.Zero;
|
||||
|
||||
if (_librariesWhitelist.TryGetValue(libraryName, out var value))
|
||||
{
|
||||
(int minVersion, int maxVersion) = value;
|
||||
|
||||
for (int version = minVersion; version <= maxVersion; version++)
|
||||
{
|
||||
if (NativeLibrary.TryLoad(FormatLibraryNameForCurrentOs(libraryName, version), assembly, searchPath, out handle))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static FFmpegApi()
|
||||
{
|
||||
NativeLibrary.SetDllImportResolver(typeof(FFmpegApi).Assembly, (name, assembly, path) =>
|
||||
{
|
||||
IntPtr handle;
|
||||
|
||||
if (name == AvUtilLibraryName && TryLoadWhitelistedLibrary(AvUtilLibraryName, assembly, path, out handle))
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
else if (name == AvCodecLibraryName && TryLoadWhitelistedLibrary(AvCodecLibraryName, assembly, path, out handle))
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
});
|
||||
}
|
||||
|
||||
public unsafe delegate void av_log_set_callback_callback(void* a0, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string a2, byte* a3);
|
||||
|
||||
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern AVFrame* av_frame_alloc();
|
||||
|
||||
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void av_frame_unref(AVFrame* frame);
|
||||
|
||||
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void av_free(AVFrame* frame);
|
||||
|
||||
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void av_log_set_level(AVLog level);
|
||||
|
||||
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void av_log_set_callback(av_log_set_callback_callback callback);
|
||||
|
||||
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern AVLog av_log_get_level();
|
||||
|
||||
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void av_log_format_line(void* ptr, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string fmt, byte* vl, byte* line, int lineSize, int* printPrefix);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern AVCodec* avcodec_find_decoder(AVCodecID id);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern AVCodecContext* avcodec_alloc_context3(AVCodec* codec);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern int avcodec_open2(AVCodecContext* avctx, AVCodec* codec, void **options);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern int avcodec_close(AVCodecContext* avctx);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void avcodec_free_context(AVCodecContext** avctx);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern AVPacket* av_packet_alloc();
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void av_packet_unref(AVPacket* pkt);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern void av_packet_free(AVPacket** pkt);
|
||||
|
||||
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static unsafe extern int avcodec_version();
|
||||
}
|
||||
}
|
@ -1,14 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FFmpeg.AutoGen" Version="4.4.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FFmpeg.AutoGen;
|
||||
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
|
||||
@ -11,31 +11,31 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
public int RequestedWidth { get; }
|
||||
public int RequestedHeight { get; }
|
||||
|
||||
public Plane YPlane => new Plane((IntPtr)Frame->data[0], Stride * Height);
|
||||
public Plane UPlane => new Plane((IntPtr)Frame->data[1], UvStride * UvHeight);
|
||||
public Plane VPlane => new Plane((IntPtr)Frame->data[2], UvStride * UvHeight);
|
||||
public Plane YPlane => new Plane((IntPtr)Frame->Data[0], Stride * Height);
|
||||
public Plane UPlane => new Plane((IntPtr)Frame->Data[1], UvStride * UvHeight);
|
||||
public Plane VPlane => new Plane((IntPtr)Frame->Data[2], UvStride * UvHeight);
|
||||
|
||||
public FrameField Field => Frame->interlaced_frame != 0 ? FrameField.Interlaced : FrameField.Progressive;
|
||||
public FrameField Field => Frame->InterlacedFrame != 0 ? FrameField.Interlaced : FrameField.Progressive;
|
||||
|
||||
public int Width => Frame->width;
|
||||
public int Height => Frame->height;
|
||||
public int Stride => Frame->linesize[0];
|
||||
public int Width => Frame->Width;
|
||||
public int Height => Frame->Height;
|
||||
public int Stride => Frame->LineSize[0];
|
||||
public int UvWidth => (Width + 1) >> 1;
|
||||
public int UvHeight => (Height + 1) >> 1;
|
||||
public int UvStride => Frame->linesize[1];
|
||||
public int UvStride => Frame->LineSize[1];
|
||||
|
||||
public Surface(int width, int height)
|
||||
{
|
||||
RequestedWidth = width;
|
||||
RequestedHeight = height;
|
||||
|
||||
Frame = ffmpeg.av_frame_alloc();
|
||||
Frame = FFmpegApi.av_frame_alloc();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ffmpeg.av_frame_unref(Frame);
|
||||
ffmpeg.av_free(Frame);
|
||||
FFmpegApi.av_frame_unref(Frame);
|
||||
FFmpegApi.av_free(Frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FFmpeg.AutoGen;
|
||||
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
|
||||
|
@ -45,12 +45,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
if (isFP64)
|
||||
{
|
||||
return context.PackDouble2x32(
|
||||
context.Config.CreateCbuf(cbufSlot, cbufOffset),
|
||||
context.Config.CreateCbuf(cbufSlot, cbufOffset + 1));
|
||||
Cbuf(cbufSlot, cbufOffset),
|
||||
Cbuf(cbufSlot, cbufOffset + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Config.CreateCbuf(cbufSlot, cbufOffset);
|
||||
return Cbuf(cbufSlot, cbufOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,6 +300,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
|
||||
if (operand.Type != OperandType.LocalVariable)
|
||||
{
|
||||
if (operand.Type == OperandType.ConstantBuffer)
|
||||
{
|
||||
Config.SetUsedConstantBuffer(operand.GetCbufSlot());
|
||||
}
|
||||
|
||||
return new AstOperand(operand);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
{
|
||||
Operand addrLow = operation.GetSource(0);
|
||||
|
||||
Operand baseAddrLow = config.CreateCbuf(0, GetStorageCbOffset(config.Stage, storageIndex));
|
||||
Operand baseAddrLow = Cbuf(0, GetStorageCbOffset(config.Stage, storageIndex));
|
||||
|
||||
Operand baseAddrTrunc = Local();
|
||||
|
||||
@ -152,7 +152,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
{
|
||||
Operand addrLow = operation.GetSource(0);
|
||||
|
||||
Operand baseAddrLow = config.CreateCbuf(0, UbeBaseOffset + storageIndex * StorageDescSize);
|
||||
Operand baseAddrLow = Cbuf(0, UbeBaseOffset + storageIndex * StorageDescSize);
|
||||
|
||||
Operand baseAddrTrunc = Local();
|
||||
|
||||
|
@ -45,6 +45,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
|
||||
if (!(node.Value is Operation operation) || isUnused)
|
||||
{
|
||||
if (node.Value is PhiNode phi && !isUnused)
|
||||
{
|
||||
isUnused = PropagatePhi(phi);
|
||||
}
|
||||
|
||||
if (isUnused)
|
||||
{
|
||||
RemoveNode(block, node);
|
||||
@ -101,6 +106,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
{
|
||||
// Propagate copy source operand to all uses of
|
||||
// the destination operand.
|
||||
|
||||
Operand dest = copyOp.Dest;
|
||||
Operand src = copyOp.GetSource(0);
|
||||
|
||||
@ -118,6 +124,53 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PropagatePhi(PhiNode phi)
|
||||
{
|
||||
// If all phi sources are the same, we can propagate it and remove the phi.
|
||||
|
||||
Operand firstSrc = phi.GetSource(0);
|
||||
|
||||
for (int index = 1; index < phi.SourcesCount; index++)
|
||||
{
|
||||
if (!IsSameOperand(firstSrc, phi.GetSource(index)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// All sources are equal, we can propagate the value.
|
||||
|
||||
Operand dest = phi.Dest;
|
||||
|
||||
INode[] uses = dest.UseOps.ToArray();
|
||||
|
||||
foreach (INode useNode in uses)
|
||||
{
|
||||
for (int index = 0; index < useNode.SourcesCount; index++)
|
||||
{
|
||||
if (useNode.GetSource(index) == dest)
|
||||
{
|
||||
useNode.SetSource(index, firstSrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsSameOperand(Operand x, Operand y)
|
||||
{
|
||||
if (x.Type != y.Type || x.Value != y.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.Type == OperandType.Attribute ||
|
||||
x.Type == OperandType.AttributePerPatch ||
|
||||
x.Type == OperandType.Constant ||
|
||||
x.Type == OperandType.ConstantBuffer;
|
||||
}
|
||||
|
||||
private static bool PropagatePack(Operation packOp)
|
||||
{
|
||||
// Propagate pack source operands to uses by unpack
|
||||
|
@ -75,9 +75,9 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
int cbOffset = GetStorageCbOffset(config.Stage, slot);
|
||||
|
||||
Operand baseAddrLow = config.CreateCbuf(0, cbOffset);
|
||||
Operand baseAddrHigh = config.CreateCbuf(0, cbOffset + 1);
|
||||
Operand size = config.CreateCbuf(0, cbOffset + 2);
|
||||
Operand baseAddrLow = Cbuf(0, cbOffset);
|
||||
Operand baseAddrHigh = Cbuf(0, cbOffset + 1);
|
||||
Operand size = Cbuf(0, cbOffset + 2);
|
||||
|
||||
Operand offset = PrependOperation(Instruction.Subtract, addrLow, baseAddrLow);
|
||||
Operand borrow = PrependOperation(Instruction.CompareLessU32, addrLow, baseAddrLow);
|
||||
|
@ -360,12 +360,6 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
UsedFeatures |= flags;
|
||||
}
|
||||
|
||||
public Operand CreateCbuf(int slot, int offset)
|
||||
{
|
||||
SetUsedConstantBuffer(slot);
|
||||
return OperandHelper.Cbuf(slot, offset);
|
||||
}
|
||||
|
||||
public void SetUsedConstantBuffer(int slot)
|
||||
{
|
||||
_usedConstantBuffers |= 1 << slot;
|
||||
|
@ -184,18 +184,35 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||
|
||||
public LinuxError Receive(out int receiveSize, Span<byte> buffer, BsdSocketFlags flags)
|
||||
{
|
||||
LinuxError result;
|
||||
|
||||
bool shouldBlockAfterOperation = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (Blocking && flags.HasFlag(BsdSocketFlags.DontWait))
|
||||
{
|
||||
Blocking = false;
|
||||
shouldBlockAfterOperation = true;
|
||||
}
|
||||
|
||||
receiveSize = Socket.Receive(buffer, ConvertBsdSocketFlags(flags));
|
||||
|
||||
return LinuxError.SUCCESS;
|
||||
result = LinuxError.SUCCESS;
|
||||
}
|
||||
catch (SocketException exception)
|
||||
{
|
||||
receiveSize = -1;
|
||||
|
||||
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
|
||||
result = WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
|
||||
}
|
||||
|
||||
if (shouldBlockAfterOperation)
|
||||
{
|
||||
Blocking = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public LinuxError ReceiveFrom(out int receiveSize, Span<byte> buffer, int size, BsdSocketFlags flags, out IPEndPoint remoteEndPoint)
|
||||
@ -304,7 +321,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||
return LinuxError.EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int value = MemoryMarshal.Read<int>(optionValue);
|
||||
int value = optionValue.Length >= 4 ? MemoryMarshal.Read<int>(optionValue) : MemoryMarshal.Read<byte>(optionValue);
|
||||
|
||||
if (option == BsdSocketOption.SoLinger)
|
||||
{
|
||||
|
@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.4.0-build7" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GtkSharp" Version="3.22.25.128" />
|
||||
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.4.0-build9" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="OpenTK.Graphics" Version="4.7.2" />
|
||||
<PackageReference Include="SPB" Version="0.0.4-build17" />
|
||||
|
Reference in New Issue
Block a user